[운영체제] IPC(Inter-Process Communication)란? | pipes
IPC란?
IPC는 Inter-Process Communication 의 줄임말로 프로세스간의 통신을 위한 메커니즘을 의미한다. 즉 IPC는 프로세스간의 통신을 돕는다. IPC는 다음과 같이 두 가지 모델이 존재한다.
- Shared Memory
- Message Passing
프로세스에 대해 자세히 알고 싶다면 다음을 참고하자.
Shared Memory
Shared Memory 방식은 말 그대로 프로세스들이 공유하는 메모리를 이용해 통신하는 것이다. 이때 공유할 item을 생성하는 생산자(producer) 프로세스와 생성한 item을 소비하는 소비자(consumer) 프로세스가 나뉘게 된다. 즉, 생산자가 공유 메모리(buffer)에 item을 생산하고 저장하면, 소비자가 이를 읽고 소비하게 된다.
이때 중요한 것은 동기화(synchronize)가 필요하다는 것이다. 이에 대해서는 따로 자세히 알아보도록 하자.
Message Passing System
Message Passing 방식은 공유되는 주소 공간 없이 프로세스간 통신할 수 있다. 이 때 message passing 방식은 send(전송), receive(수신) 연산을 통해 통신하게 된다. 만약 프로세스 P와 Q가 통신하고 싶다면, 둘은 communication link를 둘 사이에 만들어야 한다. message passing system을 설계할 때 고려해야 할 3가지에 대해 알아보자.
Naming
- Direct Communication(직접 통신) : 프로세스간 서로의 이름을 명확히(explicitly) 알고, 직접 통신한다.
- send(P, Message) : 프로세스 P에게 메시지를 전송
- receive(Q, Message) : 프로세스 Q로부터 메시지 수신
- Indirect Communication(간접 통신) : 메시지가 mailBox를 통해 송수신 된다.
- 모든 mailBox 는 고유한 id를 가진다.
- mailBox를 공유해야지만 프로세스간에 통신할 수 있다.
- send(A, Message) : mailBox A에게 메시지를 전송
- receive(A, Message) : mailBox A로부터 메시지 수신
Synchronization
- Blocking : synchronous 하다고 생각 할 수 있다.
- Blocking send : 메시지를 송신한 프로세스는 수신 측 프로세스가 메시지를 받을 때까지 기다린다.
- Blocking receive : 수신 측 프로세스는 메시지를 받을 때까지 기다린다.
- Non-Blocking : asynchronous 하다고 생각 할 수 있다.
- Non-Blocking send : 메시지를 송신한 프로세스는 다시 자기 할 일(operation)을 한다.
- Non-Blocking receive : 수신 측 프로세스는 valid(유효한) 메시지나 NULL 메시지를 받는다.
Buffering
- Zero capacity : 0개의 메시지
- 송신 측은 무조건 수신자를 기다려야 한다.
- Bounded capacity : n개의 메시지
- 송신 측은 link 가 꽉차면 기다려야 한다.
- Unbounded capacity : 무한한 길이
- 송신 측은 절대 기다리지 않는다.
IPC in Unix
Unix 에서 IPC의 종류는 다음과 같다.
- Traditional Unix IPCs : signal, pipe, socket
- System V IPCs : message queue, semaphore, shared memory
Pipe
pipe는 한 쪽 프로세스에서 다른 프로세스로 연결되는 통로의 역할이라고 보면 된다. 한쪽에서 데이터를 write 하면 다른 쪽에서 read 하는 식으로 통신한다. pipes 에 접근하는 것은 File Descriptors를 읽거나 쓰는 것으로 가능하다.
가끔 Shell 명령어로 다음과 같은 명령을 실행할 때가 있다.
> ps -aux | grep root | tail
위와 같이 '|' 를 이용한 pipelined 명령은 pipes를 이용한 것이다. ps -aux의 출력결과를 grep root 의 입력으로 사용하고, 또 그것의 결과를 tail의 입력으로 사용하는 식이다.