Inter-Process Communication (IPC)
독립된 주소 공간을 가진 프로세스들이 물리적 경계를 넘어 데이터를 안전하게 주고받는 다양한 통신 채널과 동기화 기법을 다루는 학습 노드입니다.
Article
M
Me
hyunyoun's Blog
operating-systems-system-mechanicsoperating-systemssystem-mechanicsprocessconcurrency-mechanicsinter-process-communication-ipcos-processconcurrency10 min read
1. Overview
프로세스 간 통신(Inter-Process Communication, IPC)은 독립된 주소 공간을 가진 프로세스들이 서로의 메모리를 직접 읽고 쓸 수 없을 때, 커널(Kernel)의 중재 아래 파일, 파이프, 공유 메모리, 소켓 같은 채널로 데이터를 주고받는 통신 구조입니다.
학습자는 A | B 명령어 한 줄로 텍스트가 흐르는 유닉스(UNIX)의 기본 통신 방식인 파이프(Pipe)와 FIFO를 살펴봅니다. 나아가 메시지 패싱의 복사·문맥 전환 오버헤드를 줄이기 위해 두 프로세스의 가상 주소 테이블을 같은 물리 메모리에 연결하는 공유 메모리(Shared Memory), 그리고 네트워크를 넘어 다른 대륙의 프로세스와 통신하는 소켓(Socket) 역학까지 이해해 멀티 프로세스 분산 시스템을 엮어내는 아키텍트 역량을 갖춥니다.
2. Scope & Boundaries
In-Scope
- 데이터 스트림 배관 (Byte Streams): 익명 파이프(Anonymous Pipe, 부모-자식 간), 네임드 파이프(Named Pipe / FIFO, 무관한 프로세스 간).
- 메시지 경계 배달 (Message Passing): 메시지 큐(Message Queue, POSIX/System V), 메일박스 구조, 생산자-소비자 패턴.
- 제로 카피 통신 (Zero-Copy Comm): 공유 메모리(Shared Memory),
mmap()파일 메모리 매핑, 동기화(Mutex/Semaphore 필수). - 네트워크 이기종 통신 (Sockets): 로컬 소켓(UNIX Domain Socket), TCP/UDP 소켓 기반 IPC.
Out-of-Scope
- 커널 내부의 레지스터 스핀락 동기화: 공유 메모리를 쓸 때 커널 내부 데이터(
task_struct)를 보호하는 락 자체 03-01-04. Kernel Synchronization Primitives 영역. - 분산 서버 MSA 큐 메커니즘: 웹 서버 백엔드에서의 RabbitMQ나 Kafka 같은 엔터프라이즈급 메시지 브로커 04-03-03. Microservices & Orchestration 영역.
Boundaries
- Thread Comm vs. IPC (03-02-02): 스레드 간 통신(03-02-02)은 같은 힙(Heap) 메모리를 공유하므로 전역 변수나 포인터를 통해 바로 데이터를 주고받을 수 있습니다. 반면 IPC는 가상 메모리 장벽(MMU) 때문에 다른 프로세스의 주소 공간에 직접 접근할 수 없어, 보통 시스템 콜(Syscall)과 커널 버퍼를 거치며 복사 비용과 문맥 전환 오버헤드가 발생합니다. 공유 메모리는 이 비용을 줄이는 예외적인 방식이지만, 별도 동기화가 반드시 필요합니다.
3. Counterexample
- 파이프 블로킹의 무덤 (Pipe Deadlock): 파이프 크기가 기본 64KB인 환경에서 A 프로세스가 B에게 1GB 데이터를
write()로 계속 밀어 넣고 B가 읽지 않으면, 파이프 버퍼가 가득 차는 순간 커널은 A를 블로킹 큐(Blocked Queue)에 넣습니다. 만약 A와 B가 서로에게 동시에 쓰는 양방향 파이프 구조라면, 둘 다 가득 찬 파이프 앞에서 대기(Sleep)하며 교착 상태(Deadlock)에 빠질 수 있습니다. - 공유 메모리와 레이스 컨디션 위험 (Naked Shared Memory): 메모리 복사 비용을 줄이기 위해 공유 메모리(Shared Memory)를 쓰더라도, 락(Lock) 없이 포인터만 공유하면 데이터 일관성이 쉽게 깨집니다. A가 공유 메모리에 "Hello"를 쓰는 도중 스케줄러가 B로 넘어가면, B가 반쯤 쓰인 데이터를 읽어(Read) 데이터베이스에 기록할 수 있습니다. 공유 메모리는 빠르지만, 반드시 세마포어(Semaphore)나 뮤텍스 같은 동기화 도구와 함께 사용해야 합니다.
4. Prerequisites
- 가상 메모리의 독립성 (Basic): 왜 프로세스 A의
0x100번지와 프로세스 B의0x100번지가 물리적으로 아예 다른 곳을 가리키는지 샌드박스 개념을 알아야 합니다. (03-03-01 Virtual Memory) - 부모-자식 프로세스 복제 (Basic): 익명 파이프는 부모 프로세스가
fork()로 자식을 만들고 파일 디스크립터(FD)를 함께 물려줄 때 주로 사용되므로, Fork의 이해가 선행되어야 합니다. (03-02-01 Process Lifecycle)
5. Learning Map
6. Learning Topics
Basic
Core Topic 01: 단방향 바이트 스트림, 익명 파이프와 FIFO (Anonymous Pipes)
- Why to Learn: 터미널에서
ls -l | grep txt한 줄을 쳤을 때,ls의 표준 출력이 커널 버퍼를 거쳐grep의 표준 입력으로 연결되는 유닉스(UNIX)의 기본 통신 철학을 이해하기 위함입니다. - What to Learn:
- Concepts: 익명 파이프(Anonymous Pipe), 네임드 파이프(Named Pipe/FIFO), 단방향(Half-duplex) 통신, 바이트 스트림(Byte Stream).
- Skills: 파일 디스크립터(FD) 상속 복제,
dup2()리다이렉션. - Tools: 터미널
|연산자,mkfifo. - Trade-offs: 익명 파이프는 만들기 쉽고 데이터를 쓰는 순서대로(FIFO) 전달할 수 있지만, 보통 부모-자식 관계(
fork)에서 파일 디스크립터를 상속해 사용하고 기본적으로 한쪽 방향으로만 흐릅니다(양방향 통신에는 파이프 2개 필요). 또한 메시지의 '끝과 시작(경계)'이 없는 단순 바이트 스트림이므로 수신자가\n같은 구분자를 기준으로 직접 파싱해야 합니다.
- How to Learn:
- 1단계: 커널 공간(Ring 0)에 64KB짜리 메모리 버퍼를 만들고, 부모는 데이터를 쓰는 파이프(
fd[1])를 갖고,fork()로 태어난 자식은 데이터를 읽는 파이프(fd[0])를 물려받아 연결되는 구조를 분석합니다. - 2단계: 직접적인 부모-자식 관계가 없는 프로세스끼리 통신하기 위해, 파일 시스템에 이름을 가진 특수 파일(Named Pipe,
my_fifo)을 만들어 A가 쓰고 B가 읽는 접점을 살펴봅니다.
- 1단계: 커널 공간(Ring 0)에 64KB짜리 메모리 버퍼를 만들고, 부모는 데이터를 쓰는 파이프(
- Implement: 파이썬
os.pipe()구현. 부모 프로세스가os.write(w, "Hello Child")를 호출하고 즉시w를 닫은(Close) 뒤wait()함. 자식 프로세스는os.read(r, 1024)로 데이터를 읽고, 부모가 쓰기 끝을 닫으면(Close) 반대쪽(Read)도EOF(Empty)신호를 감지하고 종료되는 스트림 흐름 콘솔 출력.
Recommended
Core Topic 02: 택배 상자의 경계선, 메시지 큐 (Message Queue)
- Why to Learn: 파이프에 "사과포도딸기"처럼 연속 바이트를 흘려보내면 수신자가 어디서 잘라 읽어야 할지(Parsing) 직접 판단해야 합니다. 메시지 큐는 이 문제를 줄이고, 정확히 '구조체 단위(상자)'로 포장해 배달하는 메시지 경계를 이해하기 위해 배웁니다.
- What to Learn:
- Concepts: POSIX 메시지 큐, System V 메시지 큐, 메시지 경계(Message Boundary), 우선순위(Priority), 비동기 통지(Notification).
- Skills: 생산자-소비자 패턴(Producer-Consumer), 메시지 타입 캐스팅(
struct msgbuf). - Tools: 리눅스
ipcs -q,ipcrm. - Trade-offs: 파이프와 달리 큐에 메시지 단위가 차곡차곡 쌓이므로 "2번 타입 메시지"처럼 타입을 골라 읽을 수 있는 편의가 있지만, 이 메시지들은 결국 커널 메모리 안에 쌓이므로 큐 용량(기본 수 MB)을 초과하면 송신자가 블로킹될 수 있습니다. 또한 매번 유저 메모리 커널 메모리로 복사(Copy)해야 하는 병목 비용이 있습니다.
- How to Learn:
- 1단계: 파이프의 연속된 흐름을 끊고, {수신자 ID: 2, 내용: "Kill Command"} 형태의 규격화된 메시지 구조체(C struct)를 커널 램(Queue)에 링크드 리스트로 적재하는 방식을 분석합니다.
- 2단계: 수신자가 큐에서 1번 메시지는 건너뛰고 "긴급(Priority 1) 타입 메시지만 받기"처럼 선택적 수신(Selective Receive)을 수행하는 필터링 구조를 살펴봅니다.
- Implement: 파이썬
multiprocessing.Queue데모 구축.Producer프로세스가 딕셔너리 객체{'cmd': 'jump', 'val': 10}를 큐에put()하면, 파이프 스트림 파싱 없이Consumer가get()한 번에 딕셔너리 객체를 역직렬화(Pickling)해 활용하는 객체 경계 보장(Boundary Preserving) 통신 증명.
Practical
Core Topic 03: 복사 비용을 줄이는 공유 메모리 (Shared Memory & Synchronization)
- Why to Learn: 1GB짜리 4K 영상 프레임을 프로세스 간 넘길 때, 파이프나 큐를 쓰면 [A 커널 B]로 메모리 복사가 여러 번 발생합니다. 공유 메모리는 이 비용을 줄이기 위해 두 프로세스가 같은 물리 메모리 영역을 각자의 주소 공간에 매핑하는 방식을 이해하기 위해 배웁니다.
- What to Learn:
- Concepts: POSIX 공유 메모리(
shm_open), 가상 주소 매핑(mmap), 페이지 테이블(Page Table) 조작. - Skills: 제로 카피(Zero-Copy), 멀티프로세스 뮤텍스/세마포어 동기화.
- Tools: 리눅스
ipcs -m,/dev/shm(램 디스크). - Trade-offs: 공유 메모리는 데이터 복사를 줄여 높은 처리량(Zero-copy에 가까운 효과)을 얻을 수 있지만, A가 쓰는 도중 B가 읽는 레이스 컨디션(Race Condition)을 막기 위해 세마포어(Semaphore)나 뮤텍스 같은 동기화 락을 프로그래머가 명시적으로 설계해야 합니다.
- Concepts: POSIX 공유 메모리(
- How to Learn:
- 1단계: A 프로세스의 가상 주소
0x1000과 B 프로세스의 가상 주소0x5000이 커널 MMU(메모리 관리 장치)에 의해 같은 물리 메모리 프레임(Frame0x9999)을 가리키도록 페이지 테이블이 매핑되는 구조를 분석합니다. - 2단계: 락(Lock) 없이 A와 B가 동시에 그 메모리 조각에 데이터를 쓰면 문자가 깨질 수 있으므로, 공유 메모리 앞단에 세마포어(Semaphore) 같은 동기화 상태를 두고 접근 순서를 강제하는 방식을 살펴봅니다.
- 1단계: A 프로세스의 가상 주소
- Implement: 파이썬
multiprocessing.shared_memory할당 실습. A 프로세스가SharedMemory(size=10)공간을 열어 바이트 배열bytearray(b'HELLO')를 기록하자마자, B 프로세스가 동일 버퍼 이름으로 붙어(Attach)print(buf[0:5])를 호출했을 때 "HELLO"가 별도 메시지 복사 없이 출력되는 공유 버퍼 시연.
Advanced
Core Topic 04: 로컬과 네트워크를 잇는 소켓 기하학 (Unix Domain & TCP/IP Sockets)
- Why to Learn: 로컬 CPU 한 대 안의 프로그램도, 원격 서버의 프로세스도 리눅스의 "모든 것은 파일이다(VFS)" 모델 아래 유사한 파일 디스크립터 인터페이스로 통신할 수 있습니다. 소켓은 이 로컬·네트워크 통신의 공통 인터페이스를 이해하기 위해 배웁니다.
- What to Learn:
- Concepts: 로컬 소켓(Unix Domain Socket,
.sock파일), 네트워크 소켓(AF_INET, TCP/UDP), 바인딩(Bind)과 리슨(Listen). - Skills: 포트 번호(Port Number) 라우팅, 파일 디스크립터(FD) Select/Epoll 다중화 처리.
- Tools: 리눅스
netstat -anp,ss,nc(Netcat). - Trade-offs: TCP 소켓을 쓰면 같은 컴퓨터 안이든 원격 서버든 비슷한 인터페이스로 통신할 수 있는 위치 투명성(Location Transparency)을 얻지만, 로컬에서 데이터를 넘길 때도 OSI 계층(IP 포장, TCP 체크섬)과 커널 네트워크 스택을 거치므로 로컬 파이프나 Unix Domain Socket보다 오버헤드가 커질 수 있습니다.
- Concepts: 로컬 소켓(Unix Domain Socket,
- How to Learn:
- 1단계: 로컬 소켓 (UDS): 같은 컴퓨터 안에 있는 프로세스들끼리는 IP 주소 대신
/tmp/mysql.sock같은 파일 이름을 소켓 주소로 사용해, TCP 패킷 조립 과정을 생략(Bypass)하고 커널 내부에서 더 짧은 경로로 데이터를 전달하는 방식을 분석합니다. - 2단계: 네트워크 소켓: A가
write(fd, "Hi")를 호출하는 순간, 이 파일 쓰기 인터페이스가 VFS(가상 파일 시스템)를 거쳐 네트워크 카드 드라이버와 전송 계층으로 이어지는 매핑을 살펴봅니다.
- 1단계: 로컬 소켓 (UDS): 같은 컴퓨터 안에 있는 프로세스들끼리는 IP 주소 대신
- Implement: 파이썬
socket라이브러리로AF_UNIX(로컬 파일 기반) 소켓 서버와 클라이언트 핑퐁 스크립트 작성. 이후 주소 패밀리를AF_INET과 포트(127.0.0.1:8080) 매핑으로 바꾸어, 로컬 통신 코드가 TCP 통신망에서도 작동하는 인터페이스 다형성(Polymorphism) 덤프.
7. Terminology
8. References
Primary
- [P2] SWEBOK v4.0 - Software Construction / Runtime Efficiency (Comm) — Performance context.
- [P1] CS2023 - OS/Operating System Principles (Concurrency/IPC) — Core requirements.
Secondary
- [Unix Network Programming, Vol 2: Interprocess Communications] W. Richard Stevens — The IPC bible.
- [Advanced Programming in the UNIX Environment] Stevens & Rago — Implementation details.
Industry
- [The Open Group: POSIX.1-2017 IPC Specifications] — API standards.
- [Linux Kernel: IPC Overview] — Implementation of System V and POSIX IPC.
9. Final Checklist
Primary
- '메시지 패싱'과 '공유 메모리'의 물리적 데이터 전달 방식(복사 vs 직접 참조)의 차이를 설명 가능한가? (P1)
- '시그널'을 통해 실행 중인 프로세스를 강제 종료시킬 때 커널이 PCB의 상태를 어떻게 물리적으로 바꾸는지 입증할 수 있는가? (P1)
Secondary
- 대용량 이미지 처리 협업 시, '메시지 큐'보다 '공유 메모리'가 왜 물리적 대역폭 낭비를 크게 줄여주는지 설명할 수 있는가?
- 파이프의 '버퍼 크기'가 가득 찼을 때, 데이터를 쓰는(Write) 프로세스가 왜 물리적으로 멈춰야(Block) 하는지 원리를 도출할 수 있는가?
Industry
- 마이크로서비스 아키텍처(MSA)를 한 서버 내에서 구현할 때, 왜 TCP 소켓보다 'Unix Domain Socket'이 물리적 성능 측면에서 유리한지 제안할 수 있는가? (SFIA)
- 공유 메모리를 사용할 때 발생하는 '교착 상태(Deadlock)'를 방지하기 위해 세마포어를 하드웨어 친화적으로 배치하는 최우선 순위 기법을 기술할 수 있는가?