Interview/OS
Multiprocess 간 IPC 중 Pipe 통신
김 정출
2024. 9. 27. 17:51
Multiprocess 간의 통신(IPC, Inter-Process Communication)은 서로 다른 프로세스가 데이터를 주고받거나 리소스를 공유하는 방법입니다. 운영체제에서 프로세스는 독립된 메모리 공간을 가지기 때문에 직접적으로 데이터를 공유할 수 없습니다. 따라서 IPC 기법을 사용하여 프로세스 간의 데이터를 전달하거나 동기화해야 합니다.
Linux 및 Unix에서 사용하는 다양한 IPC 방법들을 아래에 설명합니다.
1. 파이프 (Pipe)
- 파이프는 두 프로세스 간에
단방향 통신
을 위한 방법입니다. 일반적으로 한 프로세스는 데이터를 쓰고, 다른 프로세스는 해당 데이터를 읽습니다. - _익명 파이프(Anonymous Pipe)*_와 이름 있는 파이프(Named Pipe, FIFO) 두 가지 종류가 있습니다.
익명 파이프 (Anonymous Pipe)
부모 프로세스와 자식 프로세스 간에 통신
할 때 주로 사용됩니다.pipe()
시스템 호출을 통해 읽기/쓰기용 파일 디스크립터를 생성합니다.- 단방향이므로 양방향 통신이 필요하면 두 개의 파이프를 사용해야 합니다.
- int pipefd[2];
- pipe(pipefd); // pipefd[0]은 읽기, pipefd[1]은 쓰기
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
int fd[2]; // 파이프용 파일 디스크립터 배열: fd[0] = 읽기, fd[1] = 쓰기
pid_t pid;
char write_msg[] = "Hello from parent!";
char read_msg[100];
// 파이프 생성
if (pipe(fd) == -1) {
perror("pipe failed");
return 1;
}
// 자식 프로세스 생성
pid = fork();
if (pid < 0) {
perror("fork failed");
return 1;
}
if (pid > 0) { // 부모 프로세스
close(fd[0]); // 읽기 끝을 닫음
// 자식 프로세스에 메시지 전송
write(fd[1], write_msg, strlen(write_msg) + 1);
close(fd[1]); // 쓰기 끝을 닫음
} else { // 자식 프로세스
close(fd[1]); // 쓰기 끝을 닫음
// 부모로부터 메시지 읽기
read(fd[0], read_msg, sizeof(read_msg));
printf("Received from parent: %s\n", read_msg);
close(fd[0]); // 읽기 끝을 닫음
}
return 0;
}
코드 설명
pipe(fd)
는 두 개의 파일 디스크립터를 생성합니다.fd[0]
은 읽기 전용,fd[1]
은 쓰기 전용입니다.fork()
를 사용하여 프로세스를 생성합니다. 자식 프로세스와 부모 프로세스가 생성된 후, 두 프로세스는 서로 독립적으로 실행됩니다.- 부모 프로세스는
fd[1]
을 사용하여 데이터를 자식 프로세스로 보냅니다. - 자식 프로세스는
fd[0]
을 통해 부모로부터 데이터를 읽고 출력합니다. - 양쪽에서 사용하지 않는 파이프의 읽기 또는 쓰기 끝은 닫습니다.
이름 있는 파이프 (Named Pipe, FIFO)
- FIFO는 파이프에 이름을 붙여
서로 다른 관계의 프로세스 간에도 통신
을 가능하게 한 방식입니다. mkfifo()
시스템 호출을 사용하여 파이프 파일을 생성하고, 서로 다른 프로세스들이 해당 파이프를 열어 읽기/쓰기 작업을 할 수 있습니다.
mkfifo()
동작 방식
- 파일 시스템에 이름 있는 파이프 생성:
mkfifo()
호출 시, 지정된 경로에 FIFO 특수 파일이 생성됩니다.- 이 파일은 일반적인 파일처럼 파일 시스템에 존재하지만, 실제로는
파이프 통신을 위한 특수한 파일
입니다. - 프로세스는 이 파이프 파일을 열어 읽기/쓰기 작업을 통해 통신할 수 있습니다.
- 읽기/쓰기 동작:
- 이름 있는 파이프는 일반적인 파일처럼
open()
,read()
,write()
등을 사용하여 접근합니다. - 하나의 프로세스는 파이프에 데이터를 쓰고, 다른 프로세스는 해당 파이프에서 데이터를 읽습니다.
- `FIFO는 단방향 통신이므로, 양방향 통신을 하려면 두 개의 FIFO 파일을 만들어 각각의 방향에서 읽고 쓰는 식`으로 구현해야 합니다.
- 이름 있는 파이프는 일반적인 파일처럼
- 블로킹 동작:
- 읽기 프로세스가 없을 때 쓰기 프로세스는 블로킹 상태가 됩니다. 즉, 쓰는 프로세스는 읽을 프로세스가 준비될 때까지 대기합니다.
- 마찬가지로, 쓰기 프로세스가 없을 때 읽기 프로세스는 블로킹됩니다. 이는 파이프가 서로 다른 프로세스 간에 동기화된 통신을 보장하도록 도와줍니다.
읽기와 쓰기 프로세스가 양방향으로 블로킹됨
- 메시지 순서 유지:
- 파이프에서 데이터는 순차적으로 전달됩니다. 즉, FIFO 구조(First In, First Out)에 따라 먼저 입력된 데이터가 먼저 출력됩니다.
- 파이프를 통한 데이터는 스트림으로 다뤄지며, 메시지의 경계를 따로 구분하지 않기 때문에 연속된 바이트로 읽고 써야 합니다.
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
mkfifo("/tmp/myfifo", 0666);
// 쓰기 모드로 FIFO 열기
int fd = open(fifo_path, O_WRONLY);
// 데이터 쓰기
write(fd, "Hello from writer!", 18);
close(fd);
---
// 다른 프로세스
char buffer[100];
// 읽기 모드로 FIFO 열기
int fd = open(fifo_path, O_RDONLY);
// 데이터 읽기
read(fd, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);