본 포스팅은
https://core.ewha.ac.kr/publicview/C0101020140401134252676046?vmode=f 강의를 참고하여 정리했습니다.
(반드시 이전 포스팅을 학습하고 읽어주세요)
컴퓨터에서 데이터를 접근하려면,
의 과정을 거칠 것이다. Storage는 메모리가 될 수도, 디스크가 될 수도 있겠다.
프로세스끼리는 독립적이기에 사실 발생할 일이 거의 없는데,
커널 영역은 다르다. 커널은 전체에 1개 있고, 내부 데이터를 모든 프로세스들이 접근하기 때문이다.
공유하는 데이터를 동시에 여러 CPU에서 접근할 경우, Race condition 가능성이 있다.
(여러 CPU가 아니더라도, 커널에서도 발생할 수 있다. 뒤에 나온다.)
어떻게 해결할 수 있을지 직관적으로, 인간적으로 생각해보자.
존나 쉽다. 한 놈이 쓰고 있을 때 다른 놈이 못 들어오게 막으면 된다.
커널과 커널이 부딪히는 경우다.
한 프로세스가 요청해서 Kernel 모드로 count를 증가시키고 있는데, 도중에 인터럽트가 걸려온다.
동작 멈추고 해당 요청을 들어주는데, 얘도 같은 count를 만지는 거다. 이러면 동기화가 깨질 수 있는 것이다.
어떻게 해결하냐고?
이런 요청을 할때는 인터럽트를 못 받게 막아놓으면 된다.
1번 예시와 매우 비슷한데, 1번은 인터럽트가 발생해서 ㅈ된거고, 2번은 컨텍스트 스위칭 해서 ㅈ된 경우다.
PA에서 파일을 읽어와서 수정하려고 했는데 타이머가 울린다. 야 꺼져.
PB가 CPU 잡고 똑같은 파일 읽어와서 수정해버린다.
PA가 다시 CPU 잡았을 땐 이미 파일이 달라져 있다. 오우쉣
어떻게 해결할까? => '커널 모드에서 수행 중일 땐 CPU preempt하지 않음'
이제 CPU가 여러 개인데 동시에 같은 자원을 건드리는 경우다.
인터럽트 enalbe/disable로 해결이 안된다. 아예 CPU를 다르게 잡고 있으니 서로를 모른다.
이럴 땐
1번 방법은 ㅈㄴ 비효율이다. 커널 입장을 아예 막는다니. 그럼 뭣하러 여러 CPU 쓰겠냐?
2번 방법이 좀 더 현실적이다. 커널에 입장은 두되, 디테일한 공유 데이터 마다 열쇠를 둬서 여기서 입장을 막는 것이다.
개발자로써, 프로그램을 만들 때 위 그림과 같이 공유 데이터를 만지는 부분을 임계구역이라고 한다.
그럼 저기에 들어갈 때, 누가 들어오면, 다른 프로세스들은 접근 못하게 프로그램을 짜야 한다는 것이다.