콘텐츠로 바로가기

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)를 보호하는 락 자체 \rightarrow 03-01-04. Kernel Synchronization Primitives 영역.
  • 분산 서버 MSA 큐 메커니즘: 웹 서버 백엔드에서의 RabbitMQ나 Kafka 같은 엔터프라이즈급 메시지 브로커 \rightarrow 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

Sequence Core Cluster Objective & Description Evidence (BoK)
1 The Wall & The Pipe 프로세스 격리를 유지하면서 데이터를 흘려보내는 유닉스의 단방향 통로, 64KB 커널 버퍼 파이프(Pipe)의 스트림 구조를 이해합니다. P1
2 Message Queues 연속 바이트 스트림 대신 메시지 단위(Message)로 데이터를 큐(Queue)에 넣고 꺼내는 패턴을 분석합니다. P5
3 Zero-Copy Shared Memory 복사(Copy) 오버헤드를 줄이기 위해 두 프로세스의 가상 주소를 하나의 물리 메모리 영역에 연결하는 방식을 살펴봅니다. Industry
4 Sockets & Everything is File 로컬을 넘어 원격 프로세스와도 리눅스의 '모든 것은 파일이다(VFS)' 철학 아래 통신하는 소켓 구조를 이해합니다. Industry

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가 읽는 접점을 살펴봅니다.
  • Implement: 파이썬 os.pipe() 구현. 부모 프로세스가 os.write(w, "Hello Child")를 호출하고 즉시 w를 닫은(Close) 뒤 wait()함. 자식 프로세스는 os.read(r, 1024)로 데이터를 읽고, 부모가 쓰기 끝을 닫으면(Close) 반대쪽(Read)도 EOF(Empty) 신호를 감지하고 종료되는 스트림 흐름 콘솔 출력.

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)을 초과하면 송신자가 블로킹될 수 있습니다. 또한 매번 유저 메모리 \rightarrow 커널 메모리로 복사(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() 하면, 파이프 스트림 파싱 없이 Consumerget() 한 번에 딕셔너리 객체를 역직렬화(Pickling)해 활용하는 객체 경계 보장(Boundary Preserving) 통신 증명.

Practical

Core Topic 03: 복사 비용을 줄이는 공유 메모리 (Shared Memory & Synchronization)

  • Why to Learn: 1GB짜리 4K 영상 프레임을 프로세스 간 넘길 때, 파이프나 큐를 쓰면 [A \rightarrow 커널 \rightarrow 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)나 뮤텍스 같은 동기화 락을 프로그래머가 명시적으로 설계해야 합니다.
  • How to Learn:
    • 1단계: A 프로세스의 가상 주소 0x1000과 B 프로세스의 가상 주소 0x5000이 커널 MMU(메모리 관리 장치)에 의해 같은 물리 메모리 프레임(Frame 0x9999)을 가리키도록 페이지 테이블이 매핑되는 구조를 분석합니다.
    • 2단계: 락(Lock) 없이 A와 B가 동시에 그 메모리 조각에 데이터를 쓰면 문자가 깨질 수 있으므로, 공유 메모리 앞단에 세마포어(Semaphore) 같은 동기화 상태를 두고 접근 순서를 강제하는 방식을 살펴봅니다.
  • 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보다 오버헤드가 커질 수 있습니다.
  • How to Learn:
    • 1단계: 로컬 소켓 (UDS): 같은 컴퓨터 안에 있는 프로세스들끼리는 IP 주소 대신 /tmp/mysql.sock 같은 파일 이름을 소켓 주소로 사용해, TCP 패킷 조립 과정을 생략(Bypass)하고 커널 내부에서 더 짧은 경로로 데이터를 전달하는 방식을 분석합니다.
    • 2단계: 네트워크 소켓: A가 write(fd, "Hi")를 호출하는 순간, 이 파일 쓰기 인터페이스가 VFS(가상 파일 시스템)를 거쳐 네트워크 카드 드라이버와 전송 계층으로 이어지는 매핑을 살펴봅니다.
  • Implement: 파이썬 socket 라이브러리로 AF_UNIX(로컬 파일 기반) 소켓 서버와 클라이언트 핑퐁 스크립트 작성. 이후 주소 패밀리를 AF_INET과 포트(127.0.0.1:8080) 매핑으로 바꾸어, 로컬 통신 코드가 TCP 통신망에서도 작동하는 인터페이스 다형성(Polymorphism) 덤프.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
IPC 서로 다른 프로세스가 데이터를 물리적으로 교환하거나 공동 작업을 수행하는 커널 중재 메커니즘입니다. 기본 통신 기초 Channel / Buffer RPC '단순한 파일 읽기'와는 구분해야 함 P1:CS2023 core
Shared Memory 두 개 이상의 프로세스가 동일한 물리 메모리 영역을 자신의 주소 공간에 사상하여 공유하는 기법입니다. 추천 고속 전송 Page Mapping / Zero-copy Message Queue 동기화 없으면 데이터 오염 P1:CS2023 core
Pipe 한 프로세스의 출력을 다른 프로세스의 입력으로 직접 연결하는 선입선출(FIFO) 기반의 물리 통로입니다. 추천 스트림 통신 Buffer / Descriptor Socket 단방향이 기본임 Industry Phil core
Signal 프로세스에게 비동기적으로 이벤트를 알리는 소프트웨어적 인터럽트 기법입니다. 실무 상태 제어 Handler / Async Interrupt 데이터 전달용보다는 상태 전이용 P1:CS2023 core

8. References

Primary

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)'를 방지하기 위해 세마포어를 하드웨어 친화적으로 배치하는 최우선 순위 기법을 기술할 수 있는가?

OS Process & Concurrency

6 / 6