4️⃣

[운영체제론] Chapter 2.3 IPC(프로세스간 통신)

작성일자
Oct 10, 2022
태그
SUB PAGE
프로젝트
운영체제론
책 종류
본 게시글은 하단 책을 읽고 학습한 내용을 제 생각으로 요약, 정리한 글입니다.
 
목차

1. 프로세스 간 통신(InterProcessCoummunication)이란?

1) 프로세스 간 통신의 세 가지 이슈

  1. 한 프로세스가 다른 프로세스에게 정보 어떻게 넘겨줄래
      • 프로세스들이 완전히 다른 주소공간에서 동작한다면 공유메모리를 어떻게 공유할것인가
        • 1) 세마포어 같은 공유자료구조를 커널에 저장하고 시스템호출로만 접근
          2) 프로세스의 주소 공간 일부분을 다른 프로세스와 공유
          3) 위 두 가지 다 안되는 경우 공유 파일을 사용
  1. 두 개 이상의 프로세스가 임계구역에 참여하고 있을 때, 상대방 방해하지 않도록 어떻게 할래
      • 상호배제 적용
  1. 프로세스 간에 종속성 존재할 때 순서 어떻게 매길래
    1. ex) 서연이가 데이터 생성하고 기우는 생성된 데이터 출력한다면 기우는 서연이 기다려야함

2. 경쟁조건(Race Conditions)

1) 경쟁조건(Race Conditions)

  • 정의) 둘 이상의 프로세스가 동시에 공유데이터를 읽거나 기록할 때 최종 결과가 누가 언제 수행되느냐에 따라 달라지는 상황
  • 예시) 프린트 스풀러
    • notion image
    • 스풀러 디렉터리: 프로세스가 프린트하고 싶은 파일 이름 기입한 곳
    • out: 프린트할 다음 파일 가리키는 공유 변수
    • in: 다음 빈 슬롯 가리키는 공유 변수. in, out은 보통 한 파일에 존재
    • 프린터 데몬 프로세스: 주기적으로 스풀러 디렉터리 살펴서 프린트할 파일 있나 검사하고, 있으면 파일 프린트하고 이름을 디렉터리에서 지우는 프로세스. out을 하나 증가시킴.
    • 경쟁조건 발생 과정)
      • 서연이가 파일 출력하고 싶어서 print 루틴 콜함.
      • 서연이가 in 값 7을 읽어서 서연이의 지역변수에 저장해둠.
      • 서연이가 다음 단계(파일이름쓰기) 가려는데 CPU가 할당된 시간 다됐다고 ready로 보내버림. 그리곤 기우를 running으로 올림.
        • context switch 발생
      • 기우도 파일 출력하고 싶어서 print 루틴 콜함.
      • 기우가 in 값 7을 읽어서 본인 로컬변수에 저장함.
      • 기우가 7 자리에 기우가 출력하고 싶은 파일 이름 씀
        • [7]=기우짱.c
      • 기우가 8로 증가시킨 로컬변수 값으로 in을 덮어쓰기함
        • in = 8
      • CPU가 시간 다 됐다고 기우를 끌어내리고 언젠가 다시 서연이 차례가 됨
        • context switch 발생
      • 서연이는 전에 읽어둔 in 값이 7이라서 7자리에 파일 이름 씀
        • [7]=서연최고.c → 기우짱.c 덮어씀
      • 서연이는 8로 증가시킨 로컬변수 값으로 in을 덮어쓰기함
        • in = 8 → 8을 덮어씀
      • 서연최고.c만 출력됨
        • 프린터 데몬 프로세스는 스풀러 디렉터리의 일관성 홰손 안돼서 잘못된 사실 인지 못함
        • 만일 서연이가 in 증가까지 다 끝낸다음 기우가 수행됐으면 둘다 잘 출력됐겠지 → 경쟁조건

3. 임계구역(Critical Regions)

1) 상호배제(Mutual Exclusion)

  • 정의) 한 프로세스가 공유데이터를 읽거나 쓰고 있으면 다른 프로세스들은 똑같은 일을 수행하지 못하도록 하는 것(배제)
    • 공유데이터: 공유 변수나 파일
    • 둘 이상의 프로세스가 동시에 공유 데이터에 읽기나 쓰기 수행 못하도록 금지하는 것

2) 임계구역(Critical Region)

  • 정의) 공유메모리에 접근하는 프로그램의 코드 부분
    • 공유메모리 그 자체가 아님.

3) 경쟁조건(Race Conditions) 방지하는 조건

  1. 상호배제 제공 → 어느 두 개의 프로세스도 동시에 임계구역에 있지 못하게 함
    1. 임계구역 사용한 상호배제 그림
      notion image
      • 서연이가 임계구역에 있는 동안 기우가 임계구역 들어가려 시도하는 상황
      • 상호배제를 제공하면 기우가 차단됨.
      • 서연이가 임계구역 떠나야(공유 데이터 사용하는 코드 수행 완료해야) 들어갈 수 있음.
  1. CPU의 개수나 속도에 대한 가정 x
  1. 임계구역 밖에서 수행 중인 프로세스는 다른 프로세스를 block 시키면 안됨
      • 임계구역에 들어가려는 다른 프로세스를 막으면 안됨
  1. 임계구역 들어가려고 무한히 기다리는 프로세스 없어야 함

4. 바쁜 대기를 이용한 상호배제(Mutual Exclusion with Busy Waiting)

  • 바쁜 대기 이용해 상호배제 제공(구현)하는 방법들 4가지

1) 인터럽트 끄기(Disabling Interrupts) → 비추(권한 남용)

  • 정의) 임계구역에 진입한 직후 모든 인터럽트를 비활성화하고, 떠나기 직전 다시 활성화함
  • 장점) 한 프로세스가 임계구역에 있는 동안 CPU가 clock interrupt에 반응하지 않아 process switch가 일어나지 않게 함으로써 상호배제를 제공함
  • 단점) 사용자 프로세스에게 인터럽트 껐다 켤 수 있는 권한 주는 거라 현명 x
    • 프로그래머가 인터럽트 활성화 명령 까먹으면 해당 시스템은 인터럽트에 영원히 반응하지 못해 process switch가 안 일어나서 더 이상 동작하지 않음.
  • process switch(=context switch):한 프로세스 수행하다 다른 프로세스 수행하는 것
    • 프로세스에 할당된 시간 끝나서 clock interrupt 걸리면 running 상태 프로세스를 ready로 보내고 다른 프로세스를 running하는 process switch일어남
  • interrupt disable 명령어
    • interrupt CPU가 interrupt pin으로 받은 interrupt signal에 대해 반응하는 것인데,
    • CPU가 interrupt disable 명령어 수행하면 해당 CPU는 인터럽트에 반응하지 않게 됨.
  • 인터럽트 비활성화 사용하는 다른 예
    • 커널이 변수나 리스트 변경하는 단 몇 개의 명령만을 수행하는 동안 인터럽트 비활성화시킴
    •  

2) 락 변수 사용(Lock Variables) → 실패(상호배제 x)

  • Lock 변수: 임계구역에 프로세스가 있고 없고를 나타내는 공유변수. 초기값은 0.
    • 0 → 임계구역에 어떤 프로세스도 없음
    • 1 → 임계구역에 어떤 프로세스가 있음
  • 정의) 임계구역 들어가기 전에 락 변수를 살펴봄.
    • 0 → 1로 변경하고 임계 영역으로 들어감
    • 1 → 0이 될 때까지 대기함
  • 단점) 스풀러 디렉터리와 동일한 문제점 가짐: 상호배제 제공 못해 경젱조건 못피함.
    • 서연이가 락 검사 끝내고 락을 1로 변경하는 사이에 기우가 락을 1로 변경하면 기우랑 서연이랑 동시에 임계구역에 들어가면서(상호배제 깨짐) 경쟁조건 발생함.
  • 특징) 소프트웨어 솔루션임
 

3) 엄격한 교대(Turn) → 비추(조건3 x)

  • 정의) 두 프로세스가 엄격하게 교대로 임계구역에 진입하게 함
    • turn: 임계구역에 진입할 순번 나타내는 공유변수. 초기값은 0
      • 0 → 서연 차례
      • 1 → 기우 차례
    • 임계영역 들어가기 전에 turn 변수를 살펴봄
      • 서연
        • 0 → 1로 변경하고 임계 영역에 들어감.
        • 1 → 0이 될 때까지 기다림
      • 기우
        • 1 → 0으로 변경하고 임계 영역에 들어감.
        • 0 → 1이 될 때까지 기다림
      서연 코드 → turn이 0이면 임계구역에 들어감.
      기우 코드 → turn이 1이면 임계구역에 들어감.
  • 장점) 상호배제 제공해(조건1) 경쟁조건 피할 순 있음
    • 서연이가 임계구역에 들어가있는동안 기우는 turn이 0이라서 임계구역에 들어갈 수 없음. → 상호배제 제공
    • 서연이가 임계구역에서 나오고 turn을 1로 설정하는 순간 기우는 while문 빠져나오면서 임계구역에 들어감
  • 단점)
    • 상호배제 제공(조건1)해도 조건3을 위반해서 완벽한 알고리즘 아님.
      • 임계영역에 있지 않은 프로세스가 다른 프로세스를 차단함
      • 기우 임계구역 실행 후 turn=0으로 변경 → 서연 임계구역 실행 후 turn=1로 변경, 기우는 비임계구역 실행 중 → 기우가 임계구역 실행할 차례인데 기우는 아직 비임계구역 실행 중이고 서연이가 임계구역 실행 원함. 허나 turn=1이라서 기우가 임계구역 실행하고 turn=0으로 바꿔줄 때까지 서연이는 블락됨.
      • 비임계구역의 기우가 임계구역 들어가고 싶은 서연이를 막는 상황.
      • ex) 스풀러 디렉터리
        • 서연이가 파일 프린트하고, 기우가 파일 프린트해야 서연이는 다음 자기 파일을 프린트 가능한 답답한 상황 발생. 번갈아가면서 할 때만 제대로 작동함.
    • 기우가 서연이보다 훨씬 느릴 때 교대로 진행하는 것은 좋지 않음
  • 바쁜 대기(Busy Waiting)
    • 정의) 변수가 특정값이 될 때까지 계속해서 검사하는 것
    • 단점) CPU 시간을 단순한 루프 도는데에 낭비해서 피하는 게 좋음
      • 루프 도는 대기 시간 짧을 게 예상되는 경우에만 사용
    • 스핀 락(Spin Lock) : 바쁜 대기를 사용하는 락 → turn
    •  

4) Peterson의 해법 → 성공(Turn 변형)

  • 코드
    • 임계구역 들어가기 전에 서연이랑 기우는 자기번호를 인자로 해서 enter_region을 호출함
    • 임계구역에 들어가서 공유변수 사용을 마친 서연이는 leave_region을 호출해서 서연이가 임계구역 수행 종료하고 관심 없다고 밝혀서 임계구역 진입 원하는 기우가 진입할 수 있음을 알려줌 (상호배제 제공)
    ex) 서연, 기우가 동시에 call
    • 서연 : interested[서연]=true, turn=서연
    • 기우 : interested[기우]=true, turn=기우
    • 서연 : while (자기차례아님, 상대는 관심있음) -> 임계구역 들어감
    • 기우 : while (자기차례임, 상대는 관심있음) -> 임계구역 못들어감(기우가 서연이 turn 덮어써서 차례가 기우인것뿐, 서연이가 관심없어질때까지 못들어감)
      • 현재 자기차례고 상대가 관심있단건 내가 나쁜놈인거임. 기다려.
      • 자기차례인데 상대관심없어지거나
      • 자기차례아닐때까지 기다려야함. (상대가 다 쓰고서 한번 더 쓸려 하는 거임. 나쁜 놈
    • 서연 : interested[서연]=false -> 임계구역 나감
    • case 1)
      • 서연: interested[서연]=true, turn=서연
      • 기우 : while (자기차례아님, 상대는 관심있음) -> 임계구역 들어감
    • case 2)
      • 기우: 드디어 while (자기차례임, 상대는 관심없음) -> 임계구역 들어감
      • 기우 : interested[기우]=false -> 임계구역 나감
      • 기우 : interested[기우]=true, turn=기우
      • 기우 : while (자기차례임, 상대는 관심없음) -> 임계구역 들어감
    • 장점) 엄격한 교대 요구하지 않으면서 상호 배제 제공함
     

    5) TSL 명령 → 성공(Lock 변형)

    • 정의) Lock 변수 값을 register에 복사해두고 lock 변수값을 무조건 1로 세팅한 후, register에 복사해둔 이전 Lock값을 살펴봄
      • 0 → 1로 변경하고 임계 영역으로 들어감
      • 1 → 0이 될 때까지 대기함
      • Lock: 임계구역에 프로세스가 있고 없고를 나타냄. 초기값 0(프로세스 없음)
    • 어셈블리 코드
      • 서연이가 임계구역 들어가고 싶어서 lock을 1로 설정함
      • 서연이가 봤을 때 설정 전 락은 0이었기에 서연이는 임계구역에 들어감
      • 기우가 임계구역 들어가고 싶어서 락을 1로 설정함
      • 기우가 봤을 때 설정 전 락은 1이었기에 기우는 임계구역에 못들어가고 락이 0이 될 때까지 락을 1로 계속해서 설정하며 루프 돔.
      • 서연이가 임계구역 나와서 락을 0으로 바꿈
      • 기우가 락을 1로 설정하지만 이번엔 설정 전 락이 0이었기에 임계구역 들어감
    • TSL 명령
      • test and set lock
      • lock 값 읽어서 레지스터에 저장하고 lock에 0이 아닌 값을 저장함
        • → 하나의 연산. 분할 불가능. 연산 중간에 process switch 일어날 수없음
      • TSL 명령 수행 끝날 때까지 메모리 버스 잠겨서 다른 어떤 CPU도 메모리 접근 불가함
      • vs. 인터럽트 비활성화 → 인터럽트 끄는 것은 다른 CPU 못막음
    • 특징)
      • 하드웨어 도움 받음
      • 분할 불가능함(indivisible)
    • 단점)
      • 프로세스가 enter_region, leave_region을 제때 호출안하면 상호배제 실패함

    5. Sleep and Wakeup

    1) 바쁜 대기의 단점

    • 임계구역 진입이 허용되지 않을 때 루프를 돌며 CPU 시간 낭비
    • 우선 순위 역전 문제 [참고로만 알기]

    2) Sleep과 Wakeup

    • 임계구역 진입이 허용되지 않을 때 바쁜 대기 안하고, block함
    • Sleep
      • 호출자를 block 상태로 만드는 시스템 호출
      • 다른 프로세스가 Wakeup 시스템 호출로 깨워줄 때까지 block 상태에 머물게 됨
    • Wakeup
      • 깨울 프로세스를 인자로 가져 깨워서 ready 상태로 보내주는 시스템 호출

    3) Sleep과 Wakeup 사용 예시: 생산자-소비자 문제(Producer-consumer problem) 해결 → 실패 (경쟁조건 발생)

    • 생산자-소비자 문제
      • 정의) 생산자는 공유버퍼에 아이템 계속 생산하고, 소비자는 아이템 계속 소비하는 개념
        • 두 프로세스가 고정된 크기의 버퍼를 공유함
        • 생산자(서연이)가 정보를 버퍼에 넣고, 소비자(기우)는 정보를 버퍼에서 꺼내옴
    • Sleep, Wakeup 사용한 생산자-소비자 문제 해결
      • 서연이가 새로운 아이템을 버퍼에 넣고 싶은데 버퍼가 이미 꽉 찬 경우 기우가 버퍼에서 아이템 꺼내갈 때까지 sleep 상태가 됨
      • 기우가 아이템 버퍼에서 꺼내오고 싶은데 버퍼에 아무것도 없는 경우 서연이가 버퍼에 아이템 넣어줄 때까지 sleep 상태가 됨
      • 따라서, 서연이는 아이템 넣었을 때 기우를 wakeup 해줘야하고, 기우는 아이템 꺼내 제거했을 때 서연이를 wakeup 해줘야함.
      • 코드
        • 단점) 스풀러 디렉터리에서 봤던 경쟁조건 일어남
          • 정의) 아직 sleep 상태가 아닌 프로세스에게 wakeup 전송하는 경우 wakeup이 소실되어 둘다 영원히 잠들게 되는 결과 초래됨
          • 원인) sleep() 콜하기 직전에 process switch 일어나면(교묘하게 스케줄링 되면) sleep() 안된 상태로 wakeup() 받는 상황 발생함
          • 경쟁조건 발생 과정
            • 기우가 count 값 읽어서 0인걸 알게 됨
            • 기우가 다음 동작 수행 하려는데, 스케줄러가 기우 수행 중지시키고 서연이를 수행하기 시작함
              • 기우가 sleep() 콜하기 전에 process switch가 발생함
            • 서연이가 아이템을 버퍼에 추가하고 count를 증가시켜 count 값이 이제 1이 됨
            • count가 이전에 0이었으므로 기우가 잠들어있을것이라 생각한 서연이는 기우를 깨우기 위해 wakeup을 호출함
            • 불행하게도 기우는 아직 잠든 상태가 아니라서 서연이의 wakeup 시그널은 허무하게 사라짐
            • 기우가 다시 실행 재개할 때 기우 입장에선 예전에 읽었던 count값이 0이기에 sleep()을 콜함.
            • 조만간 서연이는 버퍼를 다 채우고 잠들게 됨
            • 기우랑 서연이 둘다 영원히 잠듦

      6. 세마포어(Semaphores)

      1) 세마포어

      • 정의) 미래를 위해 미리 호출한 wakeup 회수를 저장해주는 변수 타입
        • 다익스트라가 제안한 새로운 변수 타입
        • 정수 변수
          • 0 → wakeup이 저장 안됨
          • 양수값 → 하나 이상의 wakeup이 대기 중
      • 장점) 경쟁조건 방지, 동기화 문제 해결
        • 세마포어 연산의 원자성이 보장되어 연산 시작하면 연산 완료되거나 프로세스가 잠들 때까지 다른 프로세스가 세마포어에 접근 불가
      • 연산
        • down(P)
          • up(V)
            • mutual exclusion 제공하는 법: down 연산 → critical region → up 연산
            • up, down연산은 원자성 보장되어 실행 중 중단되지 않음.
              • 일반적으로 인터럽트 비활성화하는 시스템호출로 구현됨
              • 따라서 down에서 세마포어 값 검사한 후 감소시키는 중간에 process switch가 일어나지 않음.

          2) 세마포어를 이용한 생산자-소비자 문제 해결 → 성공

          • 세마포어는 wakeup이 소실되는 문제를 해결함
          • 상호배제용 세마포어: mutex
            • 서연이랑 기우가 동시에 버퍼에 접근하지 못하게 함
            • 이진 세마포어임
              • 이진 세마포어: 1로 초기화되고 둘 이상의 프로세스에서 사용될 때 오직 하나의 프로세스만 critical region에 들어갈 수 있게 함
            • 1이면 임계지역 들어갈 수 있음. 임계지역 아무도 사용 x.
            • 0이면 임계지역 못들어감. 임계지역 사용 중.
          • 동기화용 세마포어: full, empty
            • 버퍼가 가득 차거나 비었을 때 서연이나 기우가 중지되는걸 보장함
          • down(&sema)
            • 서연이가 down(empty) 호출해서 empty(빈 슬롯 개수, 초기:N)가 0이면(버퍼가 꽉 차있다면) 잠들어. empty가 0보다 크면 empty 1 감소시켜(아이템을 하나 넣을 예정)
            • 혹은 기우가 down(full) 호출해서 full(찬 슬롯 개수, 초기:0)이 0이면(버퍼가 텅 비어있다면) 잠들어. full이 0보다 크면 full 1 감소시켜(아이템을 하나 뺄 예정)
            • 임계지역 들어가려는 누군가가 down(mutex) 호출해서 mutex가 0이면 잠들어. mutex가 1이면 mutex 1 감소시켜서 0으로 만들어(임계지역 들어가서 버퍼 건들 예정)
          • up(&sema)
            • 기우가 up(empty) 호출해서 서연이가 잠들어있으면 서연이를 깨워줘. 서연이가 잠들어있지 않다면 empty하나 늘려서 1로 만들어.
            • 혹은 서연이가 up(full) 호출해서 기우가 잠들어있으면 기우를 깨워줘. 기우가 잠들어있지 않다면 full 하나 늘려서 1로 만들어.
            • 임계지역에서 나오는 누군가가 up(mutex) 호출해서 임계지역 못들어온채 잠들어있는 애 있다면 걜 깨워줘. 잠든 애 없다면 mutex 1 증가시켜서 1로 만듬(사용가능상태로 만듬).
          • 코드
            •  

          7. 뮤텍스(Mutexes)

          1) 뮤텍스 [개념적인 것만 알기]

          • 정의) 세마포어의 개수 세는 능력이 빠진 단순화된 버전
            • 언락: 임게구역 사용 가능 → 0
            • 락: 임계구역 사용 안됨 → 1
          • 특징)
            • 상호배제용으로 씀
              • mutex_lock, critical region, mutex_unlock 순으로 사용
            • 뮤텍스는 세마포어가 아님
            • 스레드 패키지에 유용
            • 프로시저 레벨이 아닌 스레드 레벨에서 부르는 코드

          2) TSL로 mutex 구현한 코드

          • 스레드가 임계구역 접근시 mutex_lock (뮤텍스가 잠겨있닝? 나 걔 써서 잠그고 시퍼) 호출함.
            • 안잠겨있어! 너 써! mutex가 언락이면 임계구역을 사용할 수 있단 뜻으로 return되고, 스레드는 임계구역에 진입할 수 있음
            • 응~잠겨있어~ mutex가 락이면 스레드는 thread_yield해서 ready로 감. 현재 임계구역에 있는 애가 수행 다 마치고 mutex_unlock (뮤텍스 풀어줘~ 나 다썼어) 호출하고 나서, 언젠가 running으로 다시 올라가면 mutex_lock 다시 수행하고 그땐 mutex 안잠겨있어서 return되고 임계구역 진입할 수 있음

          3) mutex_lock vs. enter_region

          • enter_region은 임계구역 진입 못하면 락을 반복적으로 검사함.
            • 바쁜대기(락 반환될 때까지)
          • mutex_lock은 락 획득 못해서 바쁜대기를 수행하는 스레드가 다른 프로세스가 수행될 기회조차 안줘서 영원히 락 획득 못하는 무한루프에 빠지는 걸 막기 위해, 락 획득 못할 시 thread_yield를 호출해 다른 스레드에게 cpu를 양보함
            • 바쁜 대기 존재 안함
            • 스레드 다시 수행하게 되면 락 다시 검사함
            • thread_yield는 사용자 공간의 스레드 스케줄러를 호출해 매우 빠름
            • 커널 호출하지 않음. 사용자 레벨 스레드들은 mutex_lock 이용하면 전적으로 사용자공간에서 동기화 수행 가능함.
            •  

          8. 모니터(Monitors)

          1) 세마포어의 문제점

          • 사용이 어려움.
            • 예시) 프로그래머가 실수로 기우의 down(full)이랑 down(mutex) 순서 바꾼 상황
              • 기우는 down(mutex)해서 mutex값을 1에서 0으로 바꿈.
                • 0이면 서연인 임계지역 못들어옴
              • 기우가 down(full)했더니 버퍼가 비어있어서 full이 0이라 잠듦
              • 서연이가 버퍼 넣어주려고 down(empty) 후에 down(mutex)했더니 mutex가 0이라 잠듦
              • 둘다 영원히 잠듦

          2) 모니터

          • 정의) 모듈 또는 패키지에 모아진 프로시듀어, 변수, 자료구조의 모음
          • 특징)
            • 높은 수준의 동기화 프리미티브
            • 상호배제 제공
              • 단 하나의 프로세스만 한 순간에 모니터에서 활동 가능
                • 모니터의 자료구조는 모니터 내부의 프로시듀어만 직접 접근 가능하고,
                • 프로세스는 모니터의 프로시듀어를 호출함
                • 모니터 프로시듀어 호출 시 다른 프로세스가 모니터에서 활동 중인지 검사함
                  • 활동 중인 프로세스 O → 다른 프로세스가 모니터에서 나올 때까지 중단됨
                  • 활동 중인 프로세스 X → 모니터에 진입함
              • 상호배제 구현은 이진 세마포어나 뮤텍스 사용해 컴파일러가 함. (잘못될 가능성↓)
          • 단점
            • 컴파일러에서 지원해야 함
            • 분산 환경에서 적용할 수 없음
          • 코드

            3) 조건 변수(Condition Variables)와 관련 연산 wait, signal

            • 프로세스가 진행 불가할 때 대기할 수 있는 방법 (버퍼가 가득 차면 서연이는 어떻게 블록시켜?)
              • 조건변수와 조건변수에 대한 연산 wait, signal 도입해서 해결
            • wait
              • 서연이가 호출한 모니터 procedure가 버퍼가 가득 차 있어서 더 이상 진행할 수 없음을 알게 된 경우,
              • 조건 변수(full)에 대해 wait를 수행해 호출한 프로세스 서연이를 대기하게 만듦.(block)
              • 다른 프로세스(기우)가 모니터에 들어갈 수 있게 함.
            • signal
              • 기우가 조건 변수(full)에 대해 signal을 수행해 대기 중인 서연이를 깨움.
              • signal 이후 서연이랑 기우가 동시에 모니터에서 활동하는걸 막을 규칙
                • signal 수행한 프로세스인 기우가 즉시 모니터에서 나가고
                • full에 대해 대기 중인 프로세스 중 스케줄러가 택한 프로세스(ex. 서연이) 하나가 깨어나 수행됨
                • 기우가 즉시 나가야하기에 signal은 모니터 procedure의 맨 마지막에서 사용되어야함
            • 조건변수
              • 세마포어처럼 카운터가 아니라서 signal을 누적시킬 수 없음
              • 아무도 대기하고 있지 않은 조건변수에 대해 수행된 signla은 사라짐
              • 따라서 signal 전엔 무조건 wait가 수행되었어야 함

            4) 모니터를 사용한 생산자-소비자 문제 해결

            • 코드
              • wait, signal vs. sleep, wakeup
                • sleep, wakeup
                  • 버퍼 찬 거 확인하고, sleep 하려는 사이에 process switch일어나서 다른 프로세스가 이 프로세스를 wakeup 하려하면 wakeup이 소실되고 문제 발생함
                • wait, signal
                  • 모니터 프로시듀어에 대해 자동으로 상호배제 이뤄짐
                  • 모니터의 생산자 프로시듀어가 버퍼 찬 거 확인하고, wait 하려는 사이에 소비자로 process switch될 일 없이 wait 완료할 수 있음.
                  • 소비자는 생산자가 wait 완료하고 더 이상 실행 중이지 않다고 표시할 때까지 모니터 진입 불가함.
               

              9. 메시지 패싱(Message Passing)

              1) 메시지 패싱

              • 정의) 프로세스들이 네트워크로 연결된 각기 다른 컴퓨터에서 수행되어 메모리를 공유하고 있지 않아 공유변수 사용이 불가능한 상황에서 사용하는 ipc(프로세스 간 통신) 방식
              • 특징) 시스템 호출 send와 receivce 사용
                • send(destination, &message)
                  • 지정된 목적지(프로세스)로 메시지 보냄
                • receive(source, &message)
                  • 지정된 소스(프로세스)로부터 메시지 받음
                  • 메시지가 available하지 않으면 receive 시스템콜 호출한 프로세스는 메시지가 도착할 때까지 block되거나(아래 코드가 채택) receive 시스템콜이 오류 코드와 함께 즉시 return됨

              2) N개 메시지에 대한 생산자-소비자 문제

              • 코드 → 공유버퍼를 구현한 셈
                • 서연이가 아직 아이템 넣은 메시지 안보냈다면 기우는 while루프에서 receive system call했을 때 block이 됨
                  • 동기화를 잘 구현한 것임
                  • 서연이는 버퍼 꽉 찼으면 더 진행 못하고 기우는 버퍼 텅 비어있으면 더 이상 진행 못한다는 생산자-소비자 문제의 컨셉이 잘 구현됨.

              10. 장벽(Barriers)

              1) 장벽

              • 정의) 다른 모든 프로세스가 장벽에 도착할 때까지 이미 도착한 프로세스들은 대기. 모든 프로세스가 장벽에 도착하면 다같이 장벽을 통과함.
                • notion image
                • a,b,d가 barrier primitive를 call함. 아직 c가 call하지 않아서 a,b,d는 block
                • c가 barrier primitive를 call하면 a,b,c,d가 barrier primitive로부터 return함
              • 특징) 여러 프로세스 동기화할 때 사용