티스토리 뷰
12. 프로세스 동기화
- 줌으로 회의를 하다 보면 좀 불편할 때가 있다.
- 두 명 이상이 동시에 말할 때다.
- 그래서 손을 먼저 들고 말할 순서를 정하면 된다.
- 하지만 사실 그것도 불편하다.
- 프로세스도 동시에 실행되고 싶을 때가 있다.
- 하지만 동시에 실행할 프로세스들이 같은 자원을 쓴다면 문제가 된다.
- 줌 회의로 비유하자면, 공간과 시간(자원)을 같이 쓰고 싶은 두 사람이 있을 때의 문제이다.
12.1 동기화란
- 아주 간단한 예시로, 같은 파일을 두 프로세스가 동시에 수정하는 경우 문제가 생길 수 있다.
- 얼핏 생각하면 그게 왜 문제인지 와닿지 않을 수 있다.
- 사람 기준이 아니라 컴퓨터의 기준으로 생각해야 한다.
- 예를 들어, 파일의 값을 읽어서 1 증가시켜서 저장하려면 아래의 과정이 필요할 것이다. (틀릴 수 있음)
- 프로세스가 OS를 통해 파일을 열어주기를 요청한다.
- OS가 HDD 또는 SSD의 장치 컨트롤러에게 파일을 열어주기를 요청한다.
- 장치 컨트롤러가 반응한다. 통로를 열어준다.
- 프로세스가 적절한 명령을 만들어서 메모리에 올린다.
- CPU가 메모리에서 명령을 가져간다. "파일의 값을 1 증가시켜주세요."라고 써있다.
- 앞에서 만든 통로를 통해서 값을 가져온다. 이 값은 (아마도) 데이터 레지스터에 들어간다.
- ALU가 값을 1 증가시킨다.
- 이 값은 CPU 내의 제어 장치를 통해 다시 메모리에 기록된다.
- 프로세스가 다시 OS에게 파일을 열어달라고 요청한다.
- 파일과의 통로가 열리면 프로세스는 메모리에서 값을 가져와서 저장한다.
- 이렇게 생각하면 왜 문제가 생기는지 바로 보인다.
- 결국 모든 것은 어셈블리어나 기계어 등의 저급 언어로 변환되어 실행된다.
- 저급 언어에서는 읽기 -> 증가시키기 -> 쓰기의 과정으로 실행된다.
- 두 프로세스가 동시에 하나의 파일에 접근하면?
- 하나가 작업을 완료하기 전에 다른 하나가 파일을 열어버리면?
- 한 프로세스는 자신이 마지막으로 읽은 값을 기준으로 1을 증가시킨다.
- 다른 프로세스가 같은 파일을 열어서 값을 가져갔는지 알 길이 없다!
- 그래서 실제로는 하나의 파일은 하나의 프로세스만 접근 가능하게 만들기도 한다.
출처: https://www.scaler.com/topics/operating-system/process-synchronization-in-os/
- 그래서 프로세스 동기화는 아래의 두 가지 원칙이 필요하다.
- 실행 순서 제어: 프로세스를 옳은 순서대로 실행시키기
- 상호 배제: 동시에 접근하면 위험한 자원에는 한번에 하나의 프로세스만 접근 허용하기
- 동시에 접근하면 안되는 자원을 공유 자원(shared resource)이라고 부른다.
- 동시에 실행하면 문제가 생기는 자원에 접근하는 코드 영역을 임계 구역(critical section)이라고 부른다.
- 앞으로 이 용어는 중요하게 다룰 것이다.
출처: https://www.scaler.com/topics/operating-system/mutex-in-os/
12.1.1 개념 정리
- 임계 구역(critical section)
- 동시에 실행하면 문제가 생기는 공유 자원에 접근하는 코드 영역
- 상호 배제(mutual exclusion)
- 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 임계 구역에 들어가지 못하게 하는 원칙
12.2 동기화 기법
- 문제점을 알았으니, 해결할 방법이 필요하다.
- 책에 나온 대로, 탈의실에 비유해서 설명해보겠다. 화장실은 이제 그만~
- 탈의실 대기줄은 대기 큐로 생각할 수 있다.
- 사람(프로세스)은 대기 줄(대기 큐)에서 자기 순서를 기다리고 있다.
- 탈의실은 임계 구역이다.
- 탈의실(임계 구역)에는 한 번에 한 사람만 들어갈 수 있다.
- 심지어 부모도 못 들어가게 하더라. 그래서 부모 프로세스도 못 들어간다. (맞나?)
12.2.1 뮤텍스 락
- 뮤텍스 락(Mutex Lock)의 개념은 간단하다.
- 한 프로세스가 임계 구역에 들어가면, 자물쇠로 걸어잠근다.
- 임계구역에서 빠져나오면, 자물쇠를 푼다.
- 자물쇠는 전역 변수
lock
으로 만들고true/false
를 가질 수 있다. - 프로세스가 임계 구역에 들어갈 때는
acquire()
함수를 실행한다.
acquire() {
while (lock == true) // lock이 풀릴 때까지
; // 기다린다.
lock = true; // lock을 걸고 자신이 들어간다.
}
- 프로세스가 수행을 마치고 나올 때에는
release()
함수를 실행한다.
release() {
lock = false; // lock을 풀고 나온다.
}
- 이제 각 프로세스는 아래와 같이 실행된다.
acquire();
// 자기 할 일 하기
release();
- 다만 이 경우 lock이 풀릴 때까지 계속 확인하며 기다린다.
- 이것을 바쁜 대기(busy wait)라고 부른다.
출처: https://www.scaler.com/topics/operating-system/mutex-in-os/
12.2.2 세마포
- 세마포(semaphore)는 깃발 또는 빛을 이용한 신호 체계라는 뜻이다.
출처:
- 동기화 얘기 하다가 갑자기 웬 깃발이냐고?
- 프로세스에게 "들어가도 좋다!"라는 신호를 바로 깃발(flag)로 보내기 때문이다!
- 실제로 많은 경우 true/false 또는 1/0만을 갖는 변수를 flag라고 쓰기도 한다.
- CPU에 플래그 레지스터가 무엇이었는지 생각해봐도 좋겠다.
- 프로세스 동기화에서 세마포란 여러 프로세스가 여러 자원에 접근해야 할 때 사용하는 기법이다.
- 이때 깃발은 현재 비어 있는 자원의 개수를 말한다. 이 값은 전역 변수에 저장해둔다.
- 이제 프로세스는 자기 순서가 오면 이 변수의 값을 확인한다.
- 변수의 값이 0보다 커야 자원에 접근할 수 있다.
출처: https://os.mbed.com/docs/mbed-os/v5.15/apis/semaphore.html
- 비어 있는 자원 개수를 전역 변수
S
에 저장한다고 가정하자. - 자리가 나기를 기다리는 함수
wait()
는 아래와 같다.
wait() {
while (S <= 0) // 자리가 하나라도 날 때까지
; // 기다린다
S--; // 자리가 났다! 들어가면서 S를 1 줄인다
}
- 실행을 마치면 자리가 났다는 신호를 보낸다.
signal() {
S--; // 여기 자리 났어요!
}
- 프로세스는 아래 과정으로 실행된다.
wait()
// 내 할 일 합니다.
signal()
- 세마포는 한 가지 더 좋은 기능을 제공한다.
- 뮤텍스 락에서는 프로세스가 자리가 날 때까지 계속 노크를 했다.
- 화가 난다.
- 세마포에서는 자리가 없으면 프로세스를 대기 상태로 만들고 PCB를 대기 큐에 넣어버린다.
- 그리고 자리가 나면
signal()
을 통해 프로세스를 깨운다. - 아래는 대기를 위한 함수이다.
wait() {
S--;
if ( S < 0 ) {
// 대기 큐에 프로세스 삽입
// 대기 상태로 전환
}
}
- 아래는 자원을 할당받는 함수이다.
signal() {
S++;
if ( S <= 0 ) {
// 대기 큐에서 프로세스 꺼내기
// 프로세스 깨움
}
}
12.2.3 모니터
- 모니터는 아예 공유 자원과 프로세스를 위한 인터페이스를 만들어버리는 기법이다.
출처: https://velog.io/@gabie0208/OS-Semaphores-Deadlock-Starvation-Monitors
- 이제 프로세스는 반드시 이 인터페이스를 통해서만 공유 자원에 접근할 수 있다.
- 공유 자원에 접근하려는 프로세스는 모니터의 큐에 집어넣는다.
- 모니터는 자체적으로 상호 배제 원칙을 지키며 프로세스와 자원을 관리한다.
- 조건 변수는 무슨 말인지 이해를 못해서 패스한다. 아 쿨하다.
12.2.4 확인 문제
- 뮤텍스 락과 세마포에 대한 설명에 대해 틀린 것은?
- 뮤텍스 락은 임계 구역을 잠근 뒤 임계 구역에 진입함으로써 상호 배제를 위한 동기화를 이룬다?
- 맞다. 그걸 위해 자물쇠 변수를 이용한다.
- 세마포는 공유 자원이 여러 개 있는 상황에서도 이용할 수 있다?
- 그거 하려고 세마포 만든 거다.
- 세마포를 이용해 프로세스 실행 순서 제어를 위한 동기화도 할 수 있다?
- 가능하다. 프로세스 실행 앞뒤로
wait()
나signal()
을 넣느냐 마느냐를 통해서 구현한다.
- 가능하다. 프로세스 실행 앞뒤로
- 세마포를 이용하면 반드시 바쁜 대기를 해야 한다?
- 아니다. 대기 큐에 넣어놓고
signal()
로 다시 불러올 수 있다.
- 아니다. 대기 큐에 넣어놓고
- 뮤텍스 락은 임계 구역을 잠근 뒤 임계 구역에 진입함으로써 상호 배제를 위한 동기화를 이룬다?
'혼공컴운' 카테고리의 다른 글
[혼공컴운] 14장. 가상 메모리 (0) | 2024.08.02 |
---|---|
[혼공컴운] 13장. 교착 상태 (0) | 2024.08.02 |
[혼공컴운] 11장. CPU 스케줄링 (0) | 2024.07.29 |
[혼공컴운] 10장. 프로세스와 스레드 (0) | 2024.07.29 |
[혼공컴운] 9장. 운영체제 시작하기 (0) | 2024.07.29 |
댓글