[Socket] 프로세스간 통신

프로세스간 통신이 가능하다는 것은 서로 다른 두 프로세스가 데이터를 주고 받을 수 있다는 것을 의미한다. 이것이 가능하려면, 함께 공유하는 메모리가 존재해야 한다.

아래 그림은 프로세스간 통신의 방법으로 사용되는 파이프 기법의 구조적 모델이다.

Untitled

파이프는 프로세스에 속하는 자원이 아닌, OS에 속하는 자원이다. 따라서, fork에 의한 복사 대상이 아니다.

파이프 생성에 사용되는 함수는 다음과 같다.

#include <unistd.h>

int pipe(int filedes[2]);
  • filedes[0] : 데이터를 수신하는데 사용
  • filedes[1] : 데이터를 송신하는데 사용

이 함수가 호출되면, OS는 서로 다른 프로세스가 함께 접근할 수 있는 메모리 공간을 만들고, 이 공간의 접근에 사용되는 fd를 반환한다.

int main(...)
{
    int fds[2];
    ...
    pipe(fds);
    pid_t pid = fork();
    if(pid==0)
    {
        write(fds[1], str, sizeof(str));
    }
    else
    {
        read(fds[0], buf, sizeof(buf));
        puts(buf);
    }
    return 0;
}

위 코드는 다음과 같이 된다.

Untitled

부모, 자식 프로세스 모두 파이프의 입출력 경로에 접근이 가능하지만, 자식은 입력 경로에만, 부모는 출력 경로에만 접근해서 통신했다는 것을 볼 수 있다.


그런데 만약, 하나의 파이프를 통해 두 프로세스가 양방향으로 데이터를 주고 받는다면 아래와 같은 그림으로 표현할 수 있다.

Untitled

이와 같이 하나의 파이프를 대상으로 양방향으로 통신을 하는 것이 가능은 하다. 하지만 이 경우, 데이터를 읽고 쓰는 타이밍이 매우 중요해진다. 파이프에 데이터가 들어가면, 이는 임자가 없는 데이터가 된다. 즉, read 함수 호출을 통해서 먼저 데이터를 읽어 들이는 프로세스에게 데이터가 전달되기 때문에 파이프에 데이터를 전달한 프로세스가 다시 가져가버리는 상황이 발생할 수 있다.

따라서, 양방향 통신을 위해서는 아래와 같이 두 개의 파이프를 생성해야 한다. 그래야 입출력의 타이밍에 따라 데이터의 흐름이 영향을 받지 않는다.

Untitled