- 프로세스는 독립적으로 실행된다. 이는 다른 프로세스에게 영향을 받지 않는다는 뜻이기도 하다. (스레드는 프로세스 안에서 자원을 공유하므로 영향을 받는다.)
- 이처럼 독립적인 공간을 가진 프로세스간 통신에 사용되는 기법이 IPC 통신이다.
- 프로세스는 커널이 제공하는 IPC 설비를 이용해 프로세스간 통신을 할 수 있게 된다
<IPC 종류와 특징>
1) PIPE (익명 PIPE)
- 위 그림은 PIPE의 작동원리를 보여줍니다. 파이프는 두 개의 프로세스를 연결하게 되고, 하나의 프로세스는 데이터를 쓰기만, 다른 하나는 데이터를 읽기만 할 수 있습니다. 한쪽 방향으로만 통신이 가능한 파이프의 특징 때문에 Half-Duplex(반이중) 통신이라고 부르기도 합니다.
PIPE와 같은 반이중 통신의 경우 하나의 통신선로는 읽기나 쓰기 중 하나만 가능하므로 만약 읽기와 쓰기, 즉 송/수신을 모두 하기 원한다면 두개의 파이프를 만들어야만 가능해집니다.
PIPE는 매우 간단하게 사용할 수 있다는 장점이 있습니다. 만약 한쪽 프로세스가 단지 읽기만 하고 다른 쪽 프로세스는 단지 쓰기만 하는, 단순한 데이터 흐름을 가진다면 고민 없이 PIPE를 사용하면 됩니다. 단점은 반이중 통신이라는 점으로 만약 프로세스가 읽기와 쓰기 통신 모두를 해야 한다면 PIPE를 두개 만들어야 하는데, 구현이 꽤나 복잡해 질 수 있습니다. 만약 전이중 통신을 고려해야될 상황이라면 PIPE는 좋은 선택이 아니라고 보여집니다.
2) Named PIPE(FIFO)
- 익명 파이프(Pipe)는 통신을 할 프로세스가 명확하게 알 수 있는 경우 사용합니다. 예를 들어 자식과 부모 프로세스간 통신의 경우에 사용할 수 있으며, Named PIPE는 전혀 모르는 상태의 프로세스들 사이의 통신의 경우 사용합니다. Named PIPE는 PIPE의 단점 중 같은 PPID(같은 부모 프로세스)를 가지는 프로세스들 사이에서만 통신이 가능하지만, Named PIPE는 그 부분을 해결한, PIPE의 확장이라고 할 수 있을 것입니다. Named PIPE는 부모 프로세스와 무관하게 전혀 다른 모든 프로세스들 사이에서 통신이 가능한데 그 이유는 프로세스 통신을 위해 이름이 있는 파일을 사용하기 때문입니다. Named PIPE의 생성은 mkfifo를 통해 이뤄지는데, mkfifo가 성공하면 명명된 파일이 생성됩니다.
단점으로는, Named PIPE도 PIPE의 또 다른 단점인 읽기/쓰기가 동시에 가능하지 않으며, read-only, write-only만 가능합니다. 하지만 통신선로가 파일로 존재하므로 하나를 읽기 전용으로 열고 다른 하나를 쓰기전용으로 영어서 이러한 read/write문제를 해결 할 수 있습니다. 호스트 영역의 서버 클라이언트 간에 전이중 통신을 위해서는 결국 PIPE와 같이 두개의 FIFO파일이 필요하게 됩니다.
3)Message Queue
- Queue(큐)는 선입선출의 자료구조를 가지는 통신설비로 커널에서 관리합니다. 입출력 방식으로 보자면 위의 Named PIPE와 동일하다고 볼 수 있을 것입니다. Named PIPE와 다른 점이라면 Name PIPE가 데이터의 흐름이라면 메시지 큐는 메모리 공간이라는 점입니다. 파이프가 아닌, 어디에서나 물건을 꺼낼 수 있는 컨테이너 벨트라고 보면 될 것입니다.
메시지 큐의 장점은 컨테이너 벨트가 가지는 장점을 그대로 가지게 됩니다. 컨테이너 벨트에 올라올 물건에 라벨을 붙이면 동시에 다양한 물건을 다룰 수 있는 것과 같이, 메시지 큐에 쓸 데이터에 번호를 붙임으로써 여러 개의 프로세스가 동시에 데이터를 쉽게 다룰 수 있습니다.
4)Shared Memory(공유 메모리)
- 데이터를 공유하는 방법에는 크게 두 가지가 있습니다. 하나는 통신을 이용해서 데이터를 주고 받는 것이고 다른 하나는 데이터를 아예 공유, 즉 함께 사용하는 것입니다. PIPE, Named PIPE, Message Queue가 통신을 이용한 설비라면, Shared Memory는 공유메모리가 데이터 자체를 공유하도록 지원하는 설비입니다.
프로세스는 자신만의 메모리 영역을 가지고 있습니다. 이 메모리 영역은 다른 프로세스가 접근해서 함부로 데이터를 읽거나 쓰지 못하도록 커널에 의해서 보호가 되는데, 만약 다른 다른 프로세스의 메모리 영역을 침범하려고 하면 커널은 침범 프로세스에 SIGSEGV(경고 시그널 - 할당된 메모리의 범위를 벗어나는곳에서 읽거나, 쓰기를 시도할 때 발생) 을 보내게 됩니다.
다수의 프로세스가 동시에 작동하는 Linux 운영체제의 특성상 프로세스의 메모리 영역은 반드시 보호되어져야 합니다. 그렇지만 메모리 영역에 있는 데이터를 다른 프로세스도 사용할 수 있도록 해야할 경우도 필요할 것입니다. PIPE 등을 이용해서 데이터 통신을 이용하여 데이터를 전달하는 방법도 있겠지만, Thread에서 처럼 메모리 영역을 공유한다면 더 편하게 데이터를 함께 사용할 수 있을 것입니다.
Shared Memory(공유 메모리)는 프로세스간 메모리 영역을 공유해서 사용할 수 있도록 허용합니다. 프로세스가 공유 메모리 할당을 커널에 요청하면 커널은 해당 프로세스에 메모리 공간을 할당해줍니다. 이후 어떤 프로세스건 해당 메모리영역에 접근할 수 있습니다.
공유메모리는 중개자가 없이 곧바로 메모리에 접근할 수 있기 때문에 다른 모든 IPC들 중에서 가장 빠르게 작동할 수 있습니다.
5) Memory Map
- Memory Map도 Shared Memory(공유메모리)공간과 마찬가지로 메모리를 공유한다는 측면에 있어서는 서로 비슷한 측면이 있습니다. 차이점은 Memory Map의 경우 열린파일을 메모리에 맵핑시켜서, 공유한다는 점일 것입니다. 파일은 시스템의 전역적인(모두 공유할 수 있는) 자원이므로 서로 다른 프로세스들끼리 데이터를 공유하는데 문제가 없을 것임을 예상할 수 있습니다.
6) Socket
- Socket은 프로세스와 시스템의 기초적인 부분이며, 프로세스 들 사이의 통신을 가능하게 합니다. sys/socket.h>라는 헤더를 이용하여 사용할 수 있으며, 같은 도메인에서의 경우에서 연결 될 수 있습니다. 소켓을 사용하기 위해서는 생성해주고, 이름을 지정해주어야 합니다. 또한 domain과 type, Protocol을 지정해 주어야 합니다. 서버 단에서는 bind, listen, accept를 해주어 소켓 연결을 위한 준비를 해주어야 하고 , 클라이언트 단에서는 connect를 통해 서버에 요청하며, 연결이 수립 된 이후에는 Socket을 send함으로써 데이터를 주고 받게 됩니다. 연결이 끝난 후에는 반드시 Socket 을 close()해주어야 하며, Socket과 관련해서는 이후 네트워크 부분에서 자세히 다루도록 하겠습니다.
7) Semaphore
- Semaphore는 Named PIPE, PIPE, Message Queue와 같은 다른 IPC설비들이 대부분 프로세스간 메시지 전송을 목적으로 하는데 반해, Semaphore는 프로세스 간 데이터를 동기화 하고 보호하는데 그 목적을 두게 됩니다. 프로세스간 메시지 전송을 하거나, 혹은 Shared Memory를 통해서 특정 데이타를 공유하게 될 경우 발생하는 문제가 공유된 자원에 여러개의 프로세스가 동시에 접근하면 안되며, 단지 한번에 하나의 프로세스만 접근 가능하도록 만들어줘야 할 것이며, 이 때 사용되는 것이 Semaphore입니다. 자세한 부분은 이전에 포스팅했던 Semaphore와 Mutex 부분에서 다루고 있으므로 생략하도록 하겠습니다.
출처: https://jwprogramming.tistory.com/54 [개발자를 꿈꾸는 프로그래머]