건국 대학교 연구소 - #include

Download Report

Transcript 건국 대학교 연구소 - #include

Synchronization
Synchronization
목차
Concurrency
Critical Section
Race Condition, Mutual Exclusion
Software Solution
Hardware Solution
Test-And-Set (TS), Swap
OS Solution
Event, Signal
Semaphores, Monitors, Message Passing
UNIX Pipe
2
Definition of Monitors
Monitors
Monitor란?
Language에서 동기화를 제공하는 추상화 데이터 타입(ADT)
개념적으로 동기적인 접근이 필요한 데이터와 데이터에 접근하
는 Critical Section을 포함한 함수로 구성.
한번에 단지 하나의 프로세스만이 Monitor에서 함수를 수행
monitor anADT {
semaphore mutex = 1; // Implicit
...
public:
proc_i(…) {
P(mutex); // Implicit
<processing for proc_i>;
V(mutex); // Implicit
};
...
};
3
Monitors
(Cont’d)
모니터 동작 특징:
지역 변수는 모니터 내의 함수(프로시저)에 의해서만 접근 가능
프로세스는 모니터의 프로시저 호출을 통해 모니터에 진입 가능
언제나 단지 하나의 프로세스만이 모니터 내부에 존재
상호배제(Mutual exclusion)를 보장
상호배제를 위하여 별도의 프로그램을 작성할 필요 없음
운영체제에서 제공
공유 데이터 또는 자원을 모니터 안에 둠으로써 보호
공유 자원을 Monitor 내부에 지역 변수로 정의
4
Concept of Monitors
Monitors
(Cont’d)
Process Waiting Queue
shared data
High-Level Language Support
...
operations
Monitor 자원 사용은 상위 언어에서만
지원 가능
Queue에 대기하고 있는 Process 만이
모니터 객체의 data, operation에 차례
대로 접근가능
공유 자원의 동시 접근을 완전히 해결
initialization
code
Instance of Monitor Class
5
Monitor Solution of Shared Value
Monitors
(Cont’d)
Monitor 예제
balance변수를 조작하는 함수는 monitor 내에 있으므로 하나
의 프로세스만이 balance변수 조작 가능.
monitor sharedBalance {
double balance;
public:
credit(double amount) {balance += amount;};
debit(double amount) {balance -= amount;};
...
};
6
Monitor Solution of Readers-Writers Case 1
Monitors
Monitor의 선언과 수행
(Cont’d)
(Reader/Writer에 Monitor 적용 예제)
보통의 객체 지향 언어의 사용과 동일한 형태.
협력하는 프로세스의 기본 조건을 만족.
Monitor 선언 코드
monitor readerWriter_1 {
int numberOfReaders = 0;
int numberOfWriters = 0;
boolean busy = FALSE;
public:
startRead() {
};
finishRead() {
};
startWrite() {
};
finishWrite() {
};
};
Monitor 실행 코드
reader(){
while(TRUE) {
...
startRead();
read the resource;
finishRead();
...
}
fork(reader, 0);
...
fork(reader, 0):
fork(writer, 0);
...
fork(writer, 0);
writer(){
while(TRUE) {
...
startWriter();
write the resource;
}
finishWriter();
...
7
Monitor Problem of Readers-Writers
Monitors
(Cont’d)
모니터에서 발생 가능한 문제점
시나리오
1. Reader가 대기 큐에 도착
2. Writer가 대기 큐에 도착
문제점: finishRead()를 수행하지 못함
(startWrite가 수행하면서 Monitor을 점유하고 있기 때문이다.)
monitor readerWriter_1 {
int numberOfReaders = 0; // 현재 도착한 Reader의 개수
int numberOfWriters = 0; // 현재 도착한 Writer의 개수
boolean busy = FALSE; // 현재 쓰고 있는 Writer
public:
startRead() {
while(numberOfWriters != 0) ;
numberOfReaders++; };
finishRead() {
numberOfReaders--;
};
startWrite() {
numberOfWriters++;
while( busy || (numberOfReaders > 0) ) ;
busy = TRUE;
finishWrite() {
numberOfWriters--;
busy = FALSE;
};
한번에 하나의 process/threads만 동작 가능한 Monitor
내부에 조건을 만족하지 못하는 while();이 수행되면, 하
나의 process/threads가 지속적인 수행을 하게 되어 다
른 Process의 진행이 불가능 함.
};
};
8
Problem of Monitor
Monitors
(Cont’d)
모니터에서 빠져 나오기 위해 잠시 멈추는(Suspend)
방법이 필요
프로세스/스레드는 condition이 바뀔 때까지 대기
numberOfReader가 0이 될때까지 대기
Condition Variable
condition이 바뀔 때 재 시작할 수 있는 특별한 메커니즘
필요
프로세스는 condition이 만족하지 않을 때, Monitor를 빠져나가
suspend 됨
다른 프로세스가 condition을 변경할 때 Suspend된 프로세스가
깨어나고 Monitor에 진입
9
Solution of Monitor Problem
Monitors
(Cont’d)
Condition Variables을 이용하여 해결.
일종의 OS 제공 event임
모니터 내부에서만 발생(event는 모든 프로세스/스레드에 영향을 주지만 Condition
Variables은 모니터 내부에만 영향을 준다.)
Condition Variable을 다루는 Operations
wait: Suspend (다른 프로세스가 signal을 수행하기 전까지 일
시적으로 중지된 프로세스)
signal: 하나라도 일시 중지된 프로세스가 있으면 이를 재개하
도록 한다. 없으면 아무것도 하지 않음.
queue: 적어도 하나의 일시 중지된 프로세스가 존재하면 TRUE
를 반환.
10
Monitor Solution of Readers-Writers Case 2
Monitors
(Cont’d)
Reader/Writer 예제 ex) R→W→R
monitor readerWriter_2 {
int numberOfReaders = 0; boolean busy = FALSE; condition okToRead, okToWrite;
// numberOfReaders == 기다리는 reader의 수, busy == 현재 writer중임을 밝힘, okToRead ==
public:
startRead()
{
if(busy || (okToWrite.queue())
okToRead.wait();
numberOfReaders++;
okToRead.signal();
finishRead()
{
numberOfReaders--;
if(numberOfReaders == 0)
okToWrite.signal();
signal
signal
};
};
startWrite()
{
if((numberOfReaders != 0) || busy)
okToWrite.wait();
busy = TRUE;
};
finishWrite()
{
busy = FALSE;
if(okToRead.queue())
okToRead.signal();
else
okToWrite.signal();
};
signal
};
StartRead는 대기하고 있는 모든
Reader에게 시그널 전송
(Reader는 동시에 여러 개 수행가능)
Ex의 첫 reader는 okToReader에서 대기
FinishRead는 모든 Reader가 작업
종료 시, Writer에게 시그널 전송
Ex의 writer은 okToWrite에서 대기
signal
FinishWrite는 대기하고 있는
Reader와 Writer에게 시그널 전송
(Reader에게 우선순위 부여)
11
Two Types of Monitor Semantics
Signal Semantics
Hoare semantics
suspend(P1)
...
if(resourceNotAvailable()) resourceCondition.wait();
/* now available … continue … */
...
signal(P0):
Signal이 발생하면 P0는 멈추고 P1이 if문 다음부터 실행
resourceCondition.signal();
Hansen semantics(Mesa 언어에서 구현)
suspend(P1)
while(resourceNotAvailable()) resourceCondition.wait();
/* now available … continue … */
signal(P0):
P0는 Signal을 발생만 시키고, 실행을 계속하고 끝낸 후에
P1의 조건을 다시 검사
resourceCondition.signal();
12
Monitor Example of Traffic Problem
Monitors의 예
문제정의
한 방향(One way) 터널이 존재
반대편에 차량이 없는 경우에만 터널 사용 가능
현재 진행중인 방향에 도착하면 터널을 바로 사용 가능
North
N
N
터널을 지나갈 수 없음
S
N
차량: Process
Condition Queue: 1개
S
S
One-way tunnel
S
터널을 지나갈 수 있음
X
South
터널을 지나갈 수 있음
S
터널을 지나갈 수 없음
13
Monitors의 예(Cont’d)
편도 터널 해결 방법
차량이 도착하면 반대 방향 차량이 있는가로 진행 여부 판단
현재 이동 가능한 방향은 모든 차량이 지날 때까지 계속 유지됨.
편도 터널 선언 코드
monitor tunnel {
int northbound = 0;
int southbound = 0;
trafficSignal nbSignal = RED;
trafficSignal sbSignal = GREEN;
condition busy;
public:
northboundArrival() {
};
southboundArrival() {
};
depart(Direction exit) {
};
};
편도 터널 실행 코드
NorthCar(){
while(TRUE) {
...
northboundArrival();
depart(NORTH);
...
}
SouthCar(){
while(TRUE) {
...
southboundArrival();
depart(SOUTH);
...
}
fork(NorthCar, 0);
...
fork(SouthCar, 0):
fork(NorthCar, 0);
...
fork(SouthCar, 0);
14
Monitor Solution of Traffic Problem
Monitors의 예(Cont’d)
편도 터널의 해결 방법
monitor tunnel {
int northbound = 0, southbound = 0;
trafficSignal nbSignal = RED, sbSignal = GREEN;
condition busy;
public:
northboundArrival()
{
1 if(southbound > 0) busy.wait();
northbound++;
nbSignal = GREEN; sbSignal = RED;
southboundArrival()
{
2 if(northbound > 0) busy.wait();
southbound++;
nbSignal = RED; sbSignal = GREEN;
{
}
수행 내용
};
Signal
depart(Direction exit)
Signal
3 if(exit = NORTH)
{
northbound--;
if(northbound == 0)
while(busy.queue()) busy.signal();
4 else if(exit == SOUTH)
{
southbound--;
if(southbound == 0)
while(busy.queue()) busy.signal();
1
-
북쪽터널 입구에 도착한 경우
남쪽에 차량이 있다면 대기.
차량이 없다면 Shared Value 변경
신호등 변경.
2
-
남쪽터널 입구에 도착한 경우
북쪽에 차량이 있다면 대기.
차량이 없다면 Shared Value 변경
신호등 변경.
};
3 북쪽에서 출발하여 남쪽에 도착한 경우
- Shared Value 변경
- 북쪽에 남아있는 차량 수를 확인.
: 남아있다면 현재 신호등 유지
: 없다면 남쪽에 대기하는 차량에 signal 전송
};
4 남쪽에서 출발하여 북쪽에 도착한 경우
- Shared Value 변경
- 남쪽에 남아있는 차량 수를 확인.
: 남아있다면 현재 신호등 유지
: 없다면 북쪽에 대기하는 차량에 signal 전송
} };
15
Monitors의 예(Cont’d)
생각하는 철학자 문제
5명의 철학자와 5개의 포크
철학자들은 오직 먹거나 생각만 함
먹기 위해서는 좌/우 양쪽의 포크가 반드시 필요
아무도 먹지 못하여 굶어 죽지 않아야 함
서로 아무것도 못하는 상태가 되지 않아야 함
16
Monitor Solution of Dining Philosophers
Monitors의 예(Cont’d)
Thinking
i
먹으려고 할때
test((i-1) mod n)
test((i+1) mod n)
If i = 0: test p4, p1
(0 – 1) mod 5 = 4
(0 + 1) mod 5 = 1
If i = 1: test p0, p2
(1 – 1) mod 5 = 0
(1 + 1) mod 5 = 2
p2
Thinking
or Eating
Thinking
or Eating
p1
p3
If i = 2: test p1, p3
(2 - 1) mod 5 = 1
(2 + 1) mod 5 = 3
 p2, p3을 test함.
If i =3: test p2, p4
(3 - 1) mod 5 = 2
(3 + 1) mod 5 = 4
If i = 4: test p3, p0
(4 – 1) mod 5 = 3
(4 + 1) mod 5 = 0
p0
p4
n : 철학자의 수
i : 식사를 하려는 철학자
Test한 철학자가 EATING이
아니면 fork를 사용할 수 있음.
17
Monitors의 예(Cont’d)
생각하는 철학자 해결 방법
식사하려는 철학자 좌우 철학자가 생각 중이면 식사 가능
식사가 끝나면 좌우 철학자가 식사할 수 있도록 해준다.
생각하는 철학자 선언 코드
monitor diningPhilosophers {
status state[N];
condition self[N];
test(int i)
public:
diningPhilosophers() {
};
pickUpForks(int i) {
};
putDownForks(int i) {
};
};
생각하는 철학자 실행 코드
Philosophers(){
while(TRUE) {
...
pickUpForks(i);
...
putDownForks(i);
...
}
fork(Philosophers,
...
fork(Philosophers,
fork(Philosophers,
...
fork(Philosophers,
0);
0):
0);
0);
18
Monitor Solution of Dining Philosophers
Monitors의 예(Cont’d)
생각하는 철학자 해결 방법
#define N ___
enum status(EATING, HUNGRY, THINKING};
monitor diningPhilosophers {
status state[N]; condition self[N];
test(int i)
{ if((state[(i-1) mod N] != EATING) && (state[i] == HUNGRY) &&
(state[(i+1) mod N] != EATING))
식사하려는 철학자 좌우의 철학자
{
state[i] = EATING;
상태를 점검하고, 식사가 가능하면
self[i].signal();
} };
시그널을 전송한다.
public:
Signal
diningPhilosophers() { // Initilization
for(int i = 0; i < N; i++) state[i] = THINKING;
}; 철학자 초기화. 모두 생각하는 상태.
pickUpForks(int i)
{
state[i] = HUNGRY; test(i);
if(state[i] != EATING) self[i].wait();
PickUpForks: 상태 변경.
좌우 철학자 확인.
}; 현재 식사 중이 아니면 대기
putDownForks(int i)
{
state[i] = THINKING;
test((i-1) mod N); test((i+1) mod N);
}
putDownForks: 상태 변경.
좌우 철학자가 식사하려고
};
하면 식사할 수 있도록 한다.
19
Event Mechanism Supported by OS
Events
Event란?
Windows OS가 발생시키는 소프트웨어적인 condition
세마포어 추상화 -> 신호 주고(V) 받기(P)에 유용
Event Descriptor: Blocked Process List를 저장하고 있음
세마포어와의 차이점: Signal이 “no effect”일 때도 있음
Event의 처리 방법
하나의 프로세스는 다른 프로세스가 시그널을 보낼 때까지 대기
할 수 있음( 예, ① )
시그널이 발생할 때, 대기 중인 프로세스는 unblock됨( 예, ③ )
시그널을 기다리지 않는 프로세스는 그 시그널을 무시함
queue function이 시그널을 기다리는 프로세스의 개수를
return함( 예, ④ )
20
Flow of Events
Events
(Cont’d)
Events 예제
class Event {
shared Event topOfHour;
public:
void signal();
void wait()
int queue();
}
Process i
정각이 될때(Event)까지 대기
...
// Wait until the top of the hour before proceeding
topOfHour.wait();
// It’s the top of the hour ...
1
wait()
Process j
3
Resume
topOfHour
2
signal()
정각이 되면 Event를 대기(큐에 저장되어 있는)
하는 프로세스가 없을 때까지 Event를 발생한다.
...
while(TRUE)
if(isTopOfHour())
while(topOfHour.queue() > 0)
topOfHour.signal();
}
...
4
21
Signal Mechanism Supported by OS
UNIX Signals
Signal은 일종의 event임
UNIX OS가 발생시키는 소프트웨어적인 condition
특징
Signal은 인터럽트 스타일의 handler를 쉽게 작성할 수 있게
해줌
UNIX 시그널의 예
사용자의 “Control + C” 입력
0으로 숫자를 나누려는 연산
존재하지 않는 파이프에 입력하려는 시도
etc.
22
Characteristic of Signal
UNIX Signals
(cont’d)
UNIX는 버전에 따라 고정된 개수의 Signal 집합을 가짐
signal.h 에 OS가 사용할 수 있는 Signal이 정의됨
사용자 정의 시그널 정의
SIGUSR1 & SIGUSR2 사용
kill(pid, signal); 시스템호출을 이용하여 시그널 발생
pid : Signal을 전송하려는 프로세스 ID
signal : 전송하려는 정의된 Signal 혹은 사용자 정의 Signal
23
UNIX Signals
(cont’d)
시그널 처리의 세가지 방법
Kernel의 default handler가 Signal 처리
signal(SIG#, SIG_DFL)
프로그래머가 정의한 handler가 Signal 처리
signal(SIG#, myHandler)
Signal 무시
signal(SIG#, SIG_IGN)
24
Process Flow of Signal and Handler
UNIX Signals
(cont’d)
Signal Handling
/* code for process p */
...
signal(SIG#, sig_hndlr);
...
void sig_hndlr(...) {
...
/* ARBITRARY CODE */
...
/* ARBITRARY CODE */
}
실행 중인 프로세스, p
시그널 “SIG#” 발생
p 는 block
시그널 handler
“sig_hndlr” 를 p의
address space에서 실행
프로세스 p 실행 재개
25
Example Code of Signal - 1
UNIX Signals
(cont’d)
#include <signal.h>
static void sig_handler(int);
int main () {
int parent_pid, child_pid, status;
if(signal(SIGUSR1, sig_handler) == SIG_ERR)
printf(“Parent: Unable to create handler for SIGUSR1\n”);
if(signal(SIGUSR2, sig_handler) == SIG_ERR)
printf(“Parent: Unable to create handler for SIGUSR2\n”);
parent_pid = getpid();
if((child_pid = fork()) == 0) {
child_pid = getpid();
printf(“Child pid: %d\n”, child_pid);
kill(parent_pid, SIGUSR1);
for (;;) pause();
}
else
{
printf(“Parent pid: %d\n”, parent_pid);
kill(child_pid, SIGUSR2); pause();
printf(“Parent: Terminating child … \n”);
kill(child_pid, SIGTERM);
}
}
wait(&status);
printf(“done\n”);
▶ 자식 프로세스 루틴
1. 부모 프로세스 에게 SIGUSR1시그널을 보
냄
2. 시그널이 발생할 때 까지 대기
▶ 부모 프로세스 루틴
1. 자식 프로세스에게 SIGUSR2시그널을 보
냄
2. 자식에게 종료시그널(SIGTERM)을 보냄
3. 자식이 종료할 때까지 대기함
26
Example Code of Signal - 2
Unix Signal
(cont’d)
static void sig_handler(int signo) {
switch(signo) {
int cur_pid = getpid();
case SIGUSR1: /* Incoming SIGUSR1 */
printf(“Parent: Received SIGUSER1 (pid: %d)\n”, cur_pid);
break;
case SIGUSR2: /* Incoming SIGUSR2 */
printf(“Child: Received SIGUSER2\n” (pid: %d)\n”, cur_pid);
break;
시그널 handler
default: break;
}
}
return;
수행 결과화면
27
Definition of IPC
IPC
(Inter-Process Communication)
IPC 란?
프로세스간 정보전달을 위해서 Message를 사용하는 메커니즘
IPC의 필요성
각각의 쓰레드나 프로세스는 동기적인(또는 비동기적인) 공동
작업을 하기 위해 상호간에 정보전달을 할 필요가 있음
Signal, semaphore 등은 하나의 프로세스에서 다른 프로세스
로 정보를 전달할 수 없음
Monitor는 정보를 공유하나, Monitor 내의 shared memory를
통해서만 가능.
Shared Memory로 프로세스간 의사소통을 할 수 없는 경우 방
법은 IPC 밖에 없다.
OS가 Shared Memory를 지원하지 않을 경우
프로세스가 네트워크 상의 서로 다른 Machine에 존재할 경우
28
Basic Mechanism of IPC
IPC
(Cont’d)
Basic Mechanism
p0가 p1에게 정보를 복사하려면 Memory protection을 우회할
필요가 있음
원격지에 정보를 복사하기 위해 네트워크를 사용해야 함
다양한 IPC 방법들이 존재.
Mailbox, Message Queue, Shared Memory ETC..
공유될
정보
Address Space for p0
Message
복사된
정보
OS IPC
Mechanism
Address Space for p1
29
Message Format
Message Header와 Body로 구성
Control information:
버퍼 용량을 벗어날 경우(Overflow) 처리.
메시지 순서 번호
우선순위 등.
Message Type
Destination ID
Header
Source ID
Message Length
Control Information
Body
Message Contents
30
Needs of Message Protocols
Message Protocols
필요성
Message를 주고 받는 각 Process가 서로에 대해 알아야 전송 및
수신이 가능.
Sender는 receiver가 ready상태인지 또는 sender가 보낸 정보
를 receiver가 수신했는지를 알아야 함
Message system은 protocol을 명세함
Message의 전송과 수신 시에 공통된 형태가 필요하고, receiver
는 sender가 보낸 정보를 해석할 수 있어야 함
Standard header가 필요.
Message Queue
<sys/msg.h>
Semaphore
<sys/sem.h>
Shared Memory
<sys/shm.h>
31
Two Message Transmit Methods
Message Protocols
(Cont’d)
Transmit Operations
각각의 전송방법은 receiver에게 Message를 전달함
Asynchronous Send
Message 전송 후, 코드를 계속 실행.
Receiver로부터 정보가 전달되었다는 feedback이 없음
장점: 전송 후에 다른 작업 처리 가능.
단점: 정상 전송이 되었는지 알 수 없음.
Synchronous send
Message 전송 후, 메시지를 받을 때까지 sender는 block됨
장점: Message의 정상처리와 오류제어를 할 수 있음.
단점: Message를 받을 때까지 불특정 시간을 대기해야 함.
Message를 mailbox에 전달하고, sender는 실행을 재개
실제로 receiver가 mailbox에서 꺼낼 때 실행을 재개
동기화
32
Two Message Receive Methods
Message Protocols
(Cont’d)
Receive Operation
각각의 수신 방법은 Message를 가져 옴.
Blocking receive:
Mailbox에 Message가 없다면, receiver는 Message가 도착할
때가지 block
장점: 정확한 Message의 수신가능. (오류제어)
단점: 전송 수단의 문제 발생시 불특정 시간 동안 대기해야 함.
Nonblocking receive:
Mailbox에 Message가 없다면, 이 상황에 대한 error값 반환
Blocking가 없다.
장점: Process는 지속적으로 작업 가능.
단점: Message가 도착하지 못한 경우 처리 불가능 상태가 됨.
33
Message Send Using Synchronized Transmit and Block Receive
Message Protocols
(Cont’d)
Synchronized IPC(프로세스 전체를 동기화)
Code for p1
Code for p2
/* signal p2 */
syncSend(message1, p2);
<waiting …>;
/* wait for signal from p2 */
blockReceive(msgBuff, &from);
p1
syncSend(…)
/* wait for signal from p1 */
blockReceive(msgBuff, &from);
<process message>;
/* signal p1 */
syncSend(message2, p1);
p2
blockReceive(…)
waiting
blockReceive(…)
syncSend(…)
34
Message Send Using Asynchronized Transmit and Nonblock Receive
Message Protocols
(Cont’d)
Asynchronous IPC
Code for p1
Code for p2
/* signal p2 */
asyncSend(message1, p2);
<other processing>;
/* wait for signal from p2 */
while(!nbReceive(&msg, &from));
p1
/* test for signal from p1 */
if(nbReceive(&msg, &from)) {
<process message>;
asyncSend(message2, p1);
}else{
<other processing>;
}
p2
nonblockReceive(…)
asyncSend(…)
nonblockReceive(…)
nonblockReceive(…)
nonblockReceive(…)
asyncSend(…)
35
Mailbox Mechanism in Process
Mailbox
Mailbox in Process
Mailbox는 일종의 Message Queue로 IPC의 하나임.
p1’s address space는 compiler나 loader에 의해 할당됨
부주의한 Mailbox영역사용을 피해야 함
Address Space for p0
Address Space for p1
Mailbox for p1
Info to be
shared
Message
Message
Message
send(… p1, …);
Info copy
receive(…);
OS Interface
send function
receive function
36
Mailbox Mechanism in OS
Mailbox
(cont’d)
Mailbox in OS
OS가 Mailbox를 관리하여 더 안전한 메시지 전송이 가능.
정보의 복사를 위해 Memory protection을 우회할 필요가 없음
Address Space for p0
Address Space for p1
복사된
정보
공유될
정보
send(… p1, …);
receive(…);
OS Interface
Mailbox for p1
send function
Message
Message
Message
receive function
37
Definition of Pipe
UNIX Pipe
Pipe란
OS가 제공하는 단 방향 통로를 이용하여 Message를 전송하는
IPC의 하나임.
방향성이 있어 한번에 한 방향으로만 데이터 전송이 가능.
Address Space for p1
공유될
정보
복사된
정보
write(pipe[1], …);
read(pipe[0]);
System Call Interface
pipe for p1 and p2
write function
read function
38
Interface and Execution of Pipe
UNIX Pipe
(cont’d)
파이프 인터페이스는 파일 인터페이스와 유사함
open과 유사한 pipe 시스템 콜을 사용해서 파이프를 생성.
File read/write 시스템 콜을 사용하여 정보를 받거나 보냄
파이프를 사용할 때 일어나는 일
파이프가 생성될 때 커널은 하나의 버퍼 생성
프로세스들은 read/write 시스템 콜을 사용해서 버퍼에서 정보
를 읽어오거나 자신의 주소영역에서 버퍼로 정보를 쓸 수 있음
39
Read/Write Method of Pipe
UNIX Pipe
(Cont’d)
Read/Write Method of Pipe
fork()시스템 콜에 의해서 생성된 자식 프로세스는 부모 프로세
스와 파일 handler를 공유함
pipeID[0]은 파이프에서 읽기 위한 handler
pipeID[1]은 파이프에 쓰기 위한 handler
int pipeID[2]; //파이프 버퍼
...
pipe(pipeID); //파이프 선언
...
if(fork() == 0) { /* the child */
...
read(pipeID[0], childBuf, len);
<process the message>;
...
} else { /* the parent */
...
write(pipeID[1], msgToChild, len);
...
}
40
Non-blocking Read Method of Pipe
UNIX Pipe
(Cont’d)
Non-blocking Read
write()는 비동기적인 operation임
write할 수 없을 경우 error값을 돌려줌
일반적으로 read는 blocking read
read operation은 non-blocking read일 수 있음
#include <sys/ioctl.h>
...
int pipeID[2];
...
pipe(pipeID);
ioctl(pipeID[0], FIONBIO, &on);
...
read(pipeID[0], buffer, len);
if(errno != EWOULDBLOCK) {
/* no data */
} else { /* have data */
41