테마
프로세스 간 통신 2
프로세스 간 통신에서 본 파이프(pipe), 이름 있는 파이프(named pipe)인 FIFO(First In First Out, 선입선출), 메시지 큐(message queue)에 이어 소켓(socket)과 시그널(signal)을 다룬다. 소켓은 같은 컴퓨터 안은 물론 네트워크 너머의 프로세스(process)와도 양방향으로 주고받는 통로이고, 시그널은 데이터 없이 사건만 알리는 알림이다. 마지막으로 공유 메모리(shared memory)까지 포함한 여러 방식을 한 표로 비교하고 상황별로 무엇을 고를지 정리한다.
소켓
소켓은 통신의 양 끝점을 나타내는 인터페이스다. 파이프와 달리 양방향이다.
- 유닉스 도메인 소켓(Unix domain socket): 같은 컴퓨터 안의 프로세스끼리 쓴다. 파일 경로 같은 이름으로 찾고, 데이터가 네트워크 처리를 거치지 않고 커널(kernel) 안에서 곧바로 상대 프로세스로 복사돼 효율적이다. 데이터를 끊김 없는 바이트 흐름으로 보내는 흐름 방식(stream)과, 보낸 단위 그대로 한 덩어리씩 받는 메시지 방식(datagram)을 모두 지원한다. 파일 디스크립터(file descriptor) 자체를 다른 프로세스에 넘길 수도 있어서, 한 프로세스가 연 파일이나 연결을 다른 프로세스가 이어받아 처리할 수 있다. 로컬 DB 접속이나 Docker 데몬(daemon, 화면 없이 뒤에서 계속 실행되며 요청을 기다리는 프로그램) 제어처럼 같은 기계 안의 클라이언트-서버 통신에 흔히 쓴다.
- 네트워크 소켓: TCP(Transmission Control Protocol, 전송 제어 프로토콜)나 UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜) 위에서 IP(Internet Protocol, 인터넷 프로토콜) 주소와 포트(port) 번호로 상대를 찾는다. 다른 컴퓨터와도 통신할 수 있어, 여러 컴퓨터가 네트워크로 일을 나눠 처리하는 분산 시스템(distributed system)의 기본 수단이다. 자세한 차이는 TCP와 UDP에서 다룬다.
파이프·FIFO·소켓은 모두 파일 디스크립터로 다루므로 같은 read·write로 읽고 쓴다.
시그널
시그널은 프로세스에게 "이런 일이 생겼다"는 사실만 알리는 짧은 비동기 알림이다. 기본적으로 데이터를 담지 않고 어떤 사건인지를 나타내는 번호만 전한다. 터미널에서 Ctrl+C를 누르면 SIGINT가, kill <PID>를 치면 기본으로 SIGTERM이 간다. 여기서 PID(Process ID, 프로세스 식별 번호)는 커널이 프로세스마다 붙인 번호다. 자식이 끝나면 부모에게 SIGCHLD가 간다. 부모는 이 알림을 받고 자식의 종료 상태를 거둬 가서, 끝난 자식이 좀비 프로세스(zombie process)로 남지 않게 한다.
프로세스는 시그널을 받았을 때 실행할 함수인 핸들러(handler)를 등록해 종료 전 정리 작업을 할 수 있다. 단 SIGKILL과 SIGSTOP은 핸들러로 가로채거나, 전달을 잠시 보류(block)하거나, 무시하도록 설정할 수 없다. 운영자가 어떤 프로세스든 반드시 멈출 수 있게 하기 위해서다. 그래서 서버를 끌 때는 먼저 SIGTERM으로 정리할 기회를 주고, 응답이 없을 때만 SIGKILL을 쓴다.
방식 비교와 선택
표의 익명 파이프(anonymous pipe)는 이름 없는 파이프이고, FIFO는 경로로 찾는 이름 있는 파이프다. '경계'는 보낸 메시지 단위가 받는 쪽에서도 그대로 나뉘어 보이는지를 뜻한다. '없음'이면 바이트가 이어 붙은 흐름으로 도착해 받는 쪽이 직접 잘라야 하고, '선택'은 흐름 방식과 메시지 방식 중 고를 수 있다는 뜻이다.
| 방식 | 방향 | 범위 | 경계 | 속도·특징 |
|---|---|---|---|---|
| 익명 파이프 | 한 방향 | 공통 조상 프로세스 사이 | 없음 | 간단, 셸 연결 |
| FIFO | 한 방향 | 같은 컴퓨터 | 없음 | 경로로 찾음 |
| 메시지 큐 | 양쪽 가능 | 같은 컴퓨터 | 있음 | 우선순위 |
| 공유 메모리 | 양쪽 | 같은 컴퓨터 | 없음 | 가장 빠름, 동기화 직접 |
| 유닉스 도메인 소켓 | 양방향 | 같은 컴퓨터 | 선택 | 클라이언트-서버 |
| 네트워크 소켓 | 양방향 | 다른 컴퓨터까지 | 선택 | 가장 범용 |
| 시그널 | 한 방향 | 같은 컴퓨터 | - | 알림만, 데이터 없음 |
- 부모가 자식의 출력을 받기만 하면 파이프면 충분하다.
- 큰 데이터를 자주 주고받아 복사 비용이 문제라면 공유 메모리를 쓰고 동기화를 직접 설계한다.
- 나중에 다른 서버로 옮길 가능성이 있으면 처음부터 소켓으로 짠다. 두 소켓은 같은 소켓 API를 쓰고 주소 형식만 달라서, 유닉스 도메인 소켓으로 짠 코드는 주소만 바꾸면 네트워크 소켓으로 옮길 수 있다.
- 종료 요청처럼 "무엇이 일어났다"만 알리면 시그널을 쓴다.
면접 포인트
- "파이프와 소켓의 차이는?" → 파이프는 한 방향·같은 컴퓨터, 소켓은 양방향·네트워크까지.
- "유닉스 도메인 소켓은 언제 쓰나요?" → 같은 기계 안의 클라이언트-서버 통신. 네트워크 계층(network layer)을 안 거쳐 효율적이고, 나중에 네트워크 소켓으로 바꾸기 쉽다.
SIGKILL은 잡을 수 없으므로 정리 작업은SIGTERM핸들러에서 한다.
