이야기박스
운영체제) 프로세스간 통신 본문
▣ IPC ( Interprocess Communication )
● 프로세스간 통신 쟁점
- 프로세스간 정보를 어떻게 전달할 것인가?
- 다수의 프로세스에서 critical activity에서 다른 프로세스를 어떻게 방해하지 않을 것인가?
- 서로 의존성이 있는 경우, 어떤식으로 순서화하는가?
==> 스레드들 간에도 동등한 수준으로 적용
▣ 경쟁 조건 ( Race Conditions)
● 둘 이상의 프로세스가 공유 메모리를 읽고 기록할 때, 마지막 결과는 어느 프로세스가 수행되었는가에 의존한다.
- 해결 : 상호배제 --> 둘 이상의 프로세스가 동시에 공유 데이터의 읽기와 쓰기가 불가능하게 하는 방법
▣ 임계 구역 (Critical Regions)
; 공유 메모리에 접근하는 프로그램 부분
; 어떤 두 프로세스도 동시에 임계 구역에 들 수 없도록 설정
● 상호 배제 (mutual exclusion)
- 어떤 두 프로세스도 동시에 임계 구역 안으로 들어갈 수 없다.
- CPU 속도나 수에 대한 어떤 가정도 없다.
- 임계 구역 밖에서 수행되는 어떤 프로세스도 다른 프로세스를 블록시킬 수 없다.
- 어떤 프로세스도 임계구역에 들어가기 위하여 영원히 기다리지 않는다.
▣ 상호 배제 구현 방법
; 인터럽트 끄기, 락(lock) 변수, 엄격한 교대, Peterson 해법, TLS 명령
● 인터럽트 끄기
- 클록 인터럽트 끔 --> CPU간의 문맥교환이 일어나지 않도록 한다.
- 문제점 : 프로세스가 임계 구역을 떠나면서 인터럽트를 불가능하게 하는 경우,
CPU가 다수 -> 하나가 인터럽트가 금지되어도 다른 하나는 가능
● 락 (lock) 변수
- 소프트웨어적 해법
- 초기값 0, 들어갈 때 1, 떠날 때 0
- 문제점 : 한 프로세스가 잠금 변수를 1로 set하려는 찰나, 다른 프로세스가 임계 구역에 진입하면?
● 엄격한 교대
- busy waiting
- spin lock : 바쁜 대기를 사용하는 락
- 문제점 : 두 프로세스는 반드시 교대로 수행하여야 한다.
● Peterson 해법
- 엄격한 교대 문제점 해결
#define FALSE 0 #define TRUE 1 #define N 2 int turn; int interested[N]; void enter_region(int process) { int other; other = 1 - process; interested[process] = TRUE; turn = process; while (turn == process && interested[other] == TRUE); } void leave_region(int process) { interested[process] = FALSE; }
- 자신의 프로세스 번호를 인자로 제공하며 임계 구역 진입
● TSL (Test and Set Lock ) 명령
- 하드웨어적 해결책
- 몇몇 시스템 명령 ( TSL REGISTER, LOCK )
- 메모리 워드의 LOCK을 읽어 register에 저장 -> LOCK에 0이 아닌 값을 입력
- 워드를 읽고 쓰는 연산은 분할이 불가능.
- TSL 명령을 수행하는 CPU는 수행이 끝날 때까지, 메모리 버스를 잠금 -> 다른 어떤 CPU도 메모리에 접근 불가능
=> 공유 변수 lock을 사용
- lock이 0이면 어떤 프로세스도 TSL을 사용하여 이를 1로 설정 후, 공유 메모리에 읽기와 쓰기를 수행 가능
- 작업후 lock을 다시 0으로 설정
▣ 슬립과 깨움 ( Sleep and Wakeup )
● 바쁜 대기 -> 임계 구역 진입이 허용되지 않을 때, CPU 시간을 낭비하는 대신 블록하는 프로세스간 통신 고려
- sleep : 호출자를 block, --> 다른 프로세스가 깨울 때 (wakeup)까지 보류
- wakeup
● 생산자 - 소비자 문제 (한정된 버퍼 문제)
- 생산자 (producer) : 버퍼에 정보를 삽입
- 소비자 (consumer) : 버퍼에서 정보를 제거
- 버퍼가 가득 차 있다면? 생산자를 sleep --> 소비자 수행 후, wakeup
#define N 100 #define TRUE 1 #define FALSE 0 int count = 0; void producer(void) { int item; while (TRUE) { item = produce_item(); if (count == N) sleep(); insert_item(item); count = count + 1; if (count == 1) wakeup(consumer); } } void consumer(void) { int item; while (TRUE) { if (count == 0) sleep(); item = remove_item(); count = count - 1; if (count == N - 1) wakeup(producer); consume_item(item); } }
< 문제점 >
- count에 대한 접근 -> 경쟁 조건
- wakeup signal 분실
< 해결책 >
- wakeup waiting bit 추가 --> wakeup signal 저장
▣ 세마포어 ( Semaphore )
- 생산자 소비자 문제의 근본적 해결을 위함 ( Dijkstra )
- 새로운 공유변수 도입
a. 필수적인 단위 동작
b. down, up 두 개의 연산 제안 ; 원자적 동작( atomic action )
- mutex ; 세마포어 변수의 한 종류 --> 임계구역의 진입여부를 결정 ( 생산자와 소비자가 동시에 버퍼에 접근하지 못하도록 )
full ; 차있는 슬롯 수
empty ; 비어 있는 슬롯 수
#define N 100 #define TRUE 1 #define FALSE 0 typedef int semaphore; semaphore mutex = 1; semaphore empty = N; semaphore full = 0; void producer(void) { int item; while (TRUE) { item = produce_item(); down(&empty); // <-- if (count == N) sleep(); down(&mutex); insert_item(item); up(&mutex); // <-- count = count + 1; up(&full); // if (count == 1) wakeup(consumer); } } void consumer(void) { int item; while (TRUE) { down(&full); // <-- if (count == 0) sleep(); down(&mutex); item = remove_item(); up(&mutex); // <-- count = count - 1; up(&empty); // if (count == N - 1) wakeup(producer); consume_item(item); } }
- 위 생산자 소비자 문제와 비교하기 count 하나로 표현되던 부분들이 up, down을 이용하여 mutex, empty, full로 표현
● 뮤텍스 (mutexes)
- 세마포어의 count가 없는 간단한 버전
- lock / unlock 중 하나의 상태를 갖는다.
▣ 모니터 ( Monitors )
- 특수한 형태의 모듈이나 패키지에서 서로 그룹핑된 프로시저, 변수, 자료구조들의 집합
- 상호배제가 low - level 단에서 지원됨 -> " 단 하나의 프로세스만 한 순간에 모닡터에서 활동할 수 있다. "
● 생산자-소비자 문제 해결
- 조건 변수 wait, signal 도입
- sleep, wakeup과 달리 모니터에서는 자동적으로 상호배제가 됨
-> wait, signal은 상호배제가 아님
-> 문맥교환 될 걱정하지않고 연산 완료 가능
▣ 메시지 패싱 ( Message Passing )
- send / recive ; 시스템 호출 일종
- acknowledgement 분실 문제 -> 메시지 구별 필요
- 인증 --> 프로세스의 유일성 보장
● 생산자 - 소비자 문제
- 공유 메모리가 아닌, 메시지 전달로 해결
- 가정
a. 모든 메시지는 동일한 크기
b. 메시지는 운영체제에 의해 자동 버퍼링
- 방법
a. 소비자는 시작할 때, N개의 빈 메시지를 생산자에게 보냄
b. 생산자는 소비자에게 전달할 아이템을 생산하면, 빈 메시지 수신 --> 아이템이 들어 있는 메시지 전송
#define N 100 #define TRUE 1 #define FALSE 0 typedef char* message; void producer(void) { int item; message m; while (TRUE) { item = produce_item(); receive(consumer, &m); build_message(&m, item); send(consumer, &m); } } void consumer(void) { int item; message m; for (int i = 0; i < N; i++) send(producer, &m); while (TRUE) { receive(producer, &m); item = extract_item(&m); send(producer, &m); consume_item(item); } }
▣ 장벽 ( Barriers )
; 동기화 매커니즘
● 다음 단계로 진행전 모든 프로세스들이 전부 모일때까지 블록
- ex/응용이 단계별로 구성
-> 모든 프로세스가 다같이 다음 단계로 진행할 준비가 되어야만 다음 단계로 진행한다는 규칙이 있는 경우
-> 각 단계의 끝에 장벽 설치
'Computer & Data > Operating System' 카테고리의 다른 글
운영체제) 고전적인 프로세스간 통신 문제들 (0) | 2017.05.14 |
---|---|
운영체제) 스케줄링 (0) | 2017.05.14 |
운영체제란, (복습) (1) | 2017.04.03 |
운영체제) 스레드 2 (0) | 2017.04.03 |
운영체제) 스레드 (0) | 2017.04.01 |