운영체제 - 병행제어(2)
OS를 공부하면서 정리를 한 내용들 입니다.
동기화의 문제를 알기 위해서는 어떤 식으로 데이터가 접근을 해서 원하는 것들을 가져오는지에 대해서 알아야 합니다.
컴퓨터 안에서 연산을 할때는 항상 아래와 같은 형식을 취합니다.
-
데이터를 Storage Box에서 읽어옴.
-
연산할 데이터를 Execution Box로 가져옴.
-
Execution Box에서 연산을 함.
-
연산 결과를 Storage Box로 옮김.
간단한 예를 들어봅시다.
E-box | S-box |
---|---|
CPU | Memory |
컴퓨터 내부 | 디스크 |
프로세스 | 그 프로세스의 주소 공간 |
여기서 문제는.
데이터를 여러 곳에서 읽어 들일 때 발생합니다.
E-box(CPU 프로세스)가 두 곳이 있는데 S-box(Memory address space)의 count를 변경하는 기능을 합니다.
E(1)에서는 count++을 하고 저장하고,
E(2)에서는 count–를 하고 저장 시킨다고 생각해봅시다.
이때 E(1)에서 연산을 하는 도중에 E(2)가 S-box에서 값을 가져갔다면?
E(1)에서는 문제가 없었지만 E(2)의 연산에서 E(1)에서의 결과를 반영하지 못해
최종적으론 원하는 결과를 얻을 수 없습니다.
즉, 하나의 공유 데이터를 여럿이 접근하려할 때 생기는 문제를 Race Condition
이라고 합니다.
OS에서 race condition은 언제 발생가하는가?
1. Kerenl 수행 중 인터럽트 발생 시
운영체제 코드가 수행 중 이면서 공유 데이터를 건드리려 하는데,
그 데이터를 불러들여서 값을 변경하려 하는데, 인터럽트가 발생한 경우입니다.
이런 경우 무조건 하던 일을 저장하고, 인터럽트의 일을 처리합니다.
위의 예시 처럼, 원래 가져왔던 데이터를 저장한 상태에서 인터럽트가 발생했기에
인터럽트 동작은 반영이 안되어서 원하지 않는 값이 저장됩니다.
해결책 : 커널 모드가 동작중일 때 인터럽트를 disable 시켜서,
동작중엔 인터럽트가 발생할 수 없도록 하는 것으로 문제를 해결할 수 있습니다.
2. Process가 System call을 하여 kernel mode로 수행 중인데 context switch가 일어나는 경우
A라는 Program이 user mode에서 본인의 코드를 실행할 때는 본인의 주소공간에 있는 데이터를 활용하기에 문제가 없습니다.
그런데 System call을 해서 kernel의 code가 수행중 일 때는 kernel의 데이터를 건드리게 되는데,
이 kernel의 데이터는 프로세스의 입장에선 공유 데이터로 볼 수 있습니다.
A만 쓰는게 아니라 B도 kernel을 호출할 수 있는 것 처럼.
해결책 : 커널 모드에서 수행 중일 때는 CPU를 preempt하지 않음,
커널 모드에서 사용자 모드로 돌아갈 때 preempt
3. Multiprocessor에서 shared memory 내의 kernel data
CPU가 여러 개 있는 상황에서 Process A와 Process B가 운영체제의 code를 건드려서 발생할 수 있습니다.
CPU가 여러개 있을 때는 1번에서 발생했던 인터럽트를 disable하는 방법으로는 CPU가 데이터를 끌고가는 것을 해결하지 못합니다.
해결책(1) : 한번에 하나의 CPU만이 커널에 들어갈 수 있게 하는 방법
해결책(2) : 커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대한 lock/ unlock을 하는 방법
-참고 KOCW 이화여자 대학교 반효경 교수님 : 운영체제 강의