[Daily morning study] IPC (Inter-Process Communication) 방법듀

#daily morning study

Image


IPCλž€?

ν”„λ‘œμ„ΈμŠ€λŠ” 기본적으둜 λ…λ¦½λœ λ©”λͺ¨λ¦¬ 곡간을 κ°€μ§€κΈ° λ•Œλ¬Έμ— μ„œλ‘œμ˜ 데이터에 직접 μ ‘κ·Όν•  수 μ—†λ‹€. IPC(Inter-Process Communication)λŠ” μ΄λ ‡κ²Œ 격리된 ν”„λ‘œμ„ΈμŠ€λ“€μ΄ 데이터λ₯Ό μ£Όκ³ λ°›κ±°λ‚˜ λ™μž‘μ„ μ‘°μœ¨ν•  수 μžˆλ„λ‘ OSκ°€ μ œκ³΅ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μ΄λ‹€.

IPCκ°€ ν•„μš”ν•œ 상황:

  • μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€κ°€ ν˜‘λ ₯ν•΄μ„œ ν•˜λ‚˜μ˜ μž‘μ—…μ„ μ²˜λ¦¬ν•  λ•Œ
  • μƒμ‚°μž-μ†ŒλΉ„μž(Producer-Consumer) ꡬ쑰처럼 데이터λ₯Ό λ„˜κ²¨μ•Ό ν•  λ•Œ
  • ν”„λ‘œμ„ΈμŠ€ κ°„ μ΄λ²€νŠΈλ‚˜ μ‹œκ·Έλ„μ„ 전달해야 ν•  λ•Œ

μ£Όμš” IPC 방식

1. νŒŒμ΄ν”„ (Pipe)

단방ν–₯ 데이터 슀트림. λΆ€λͺ¨-μžμ‹ ν”„λ‘œμ„ΈμŠ€μ²˜λŸΌ κ΄€λ ¨λœ ν”„λ‘œμ„ΈμŠ€ μ‚¬μ΄μ—μ„œ 주둜 μ‚¬μš©ν•œλ‹€.

# μ…Έμ—μ„œ μ“°λŠ” νŒŒμ΄ν”„λ„ λ™μΌν•œ 원리
ls -l | grep ".md"
int fd[2];
pipe(fd);  // fd[0]: 읽기 끝, fd[1]: μ“°κΈ° 끝

if (fork() == 0) {
    // μžμ‹: μ“°κΈ°
    close(fd[0]);
    write(fd[1], "hello", 5);
} else {
    // λΆ€λͺ¨: 읽기
    close(fd[1]);
    char buf[10];
    read(fd[0], buf, 5);
}

νŠΉμ§•:

  • 단방ν–₯ (μ–‘λ°©ν–₯이 ν•„μš”ν•˜λ©΄ νŒŒμ΄ν”„ 2개 μ‚¬μš©)
  • κ΄€λ ¨ μ—†λŠ” ν”„λ‘œμ„ΈμŠ€ κ°„μ—λŠ” μ‚¬μš© λΆˆκ°€ β†’ 이 경우 Named Pipe(FIFO) μ‚¬μš©

2. Named Pipe (FIFO)

일반 νŒŒμ΄ν”„μ™€ 달리 파일 μ‹œμŠ€ν…œμ— 이름이 μžˆλŠ” νŒŒμ΄ν”„. κ΄€κ³„μ—†λŠ” ν”„λ‘œμ„ΈμŠ€λΌλ¦¬λ„ μ΄λ¦„μœΌλ‘œ μ°Ύμ•„μ„œ 톡신 κ°€λŠ₯ν•˜λ‹€.

mkfifo /tmp/my_pipe

# ν”„λ‘œμ„ΈμŠ€ A: μ“°κΈ°
echo "data" > /tmp/my_pipe

# ν”„λ‘œμ„ΈμŠ€ B: 읽기
cat /tmp/my_pipe

3. λ©”μ‹œμ§€ 큐 (Message Queue)

λ©”μ‹œμ§€λ₯Ό 큐에 μ €μž₯ν•˜κ³ , μˆ˜μ‹ μžκ°€ κΊΌλ‚΄κ°€λŠ” 방식. μ†‘μ‹ μžμ™€ μˆ˜μ‹ μžκ°€ λ™μ‹œμ— μ‹€ν–‰ 쀑일 ν•„μš”κ°€ μ—†λ‹€λŠ” 점이 νŒŒμ΄ν”„μ™€ λ‹€λ₯΄λ‹€.

ν•­λͺ©νŒŒμ΄ν”„λ©”μ‹œμ§€ 큐
λ°©ν–₯단방ν–₯μ–‘λ°©ν–₯ κ°€λŠ₯
동기화동기비동기
λ©”μ‹œμ§€ λ‹¨μœ„λ°”μ΄νŠΈ μŠ€νŠΈλ¦Όνƒ€μž… μžˆλŠ” λ©”μ‹œμ§€
// λ©”μ‹œμ§€ 큐 생성/μ ‘κ·Ό
int msgid = msgget(key, IPC_CREAT | 0666);

// 솑신
msgsnd(msgid, &msg, sizeof(msg.text), 0);

// μˆ˜μ‹ 
msgrcv(msgid, &msg, sizeof(msg.text), 1, 0);

4. 곡유 λ©”λͺ¨λ¦¬ (Shared Memory)

μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€κ°€ λ™μΌν•œ λ©”λͺ¨λ¦¬ μ˜μ—­μ„ 직접 읽고 μ“°λŠ” 방식. IPC 방법 쀑 κ°€μž₯ λΉ λ₯΄λ‹€.

ν”„λ‘œμ„ΈμŠ€ A의 가상 μ£Όμ†Œ 곡간     ν”„λ‘œμ„ΈμŠ€ B의 가상 μ£Όμ†Œ 곡간
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      μ½”λ“œ        β”‚           β”‚      μ½”λ“œ        β”‚
β”‚      μŠ€νƒ        β”‚           β”‚      μŠ€νƒ        β”‚
β”‚   곡유 λ©”λͺ¨λ¦¬  ──┼───────────┼── 곡유 λ©”λͺ¨λ¦¬    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             ↓                         ↓
             └─────── 물리 λ©”λͺ¨λ¦¬ β”€β”€β”€β”€β”€β”˜

속도가 λΉ λ₯Έ λŒ€μ‹  동기화 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμ–΄μ„œ Semaphoreλ‚˜ Mutex와 ν•¨κ»˜ 써야 ν•œλ‹€.

// 곡유 λ©”λͺ¨λ¦¬ 생성
int shmid = shmget(key, 1024, IPC_CREAT | 0666);

// ν”„λ‘œμ„ΈμŠ€ μ£Όμ†Œ 곡간에 μ—°κ²°
char *data = (char *)shmat(shmid, NULL, 0);

// 읽기/μ“°κΈ°
sprintf(data, "shared data");

// μ—°κ²° ν•΄μ œ
shmdt(data);

5. μ†ŒμΌ“ (Socket)

λ„€νŠΈμ›Œν¬ 톡신에 μ“°μ΄λŠ” μ†ŒμΌ“μ„ 같은 λ¨Έμ‹  λ‚΄ ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신에도 μ‚¬μš©ν•  수 μžˆλ‹€. Unix Domain Socket을 μ“°λ©΄ λ„€νŠΈμ›Œν¬ μŠ€νƒμ„ κ±°μΉ˜μ§€ μ•Šμ•„ λΉ λ₯΄λ‹€.

# Unix Domain Socket μ˜ˆμ‹œ (Python)
import socket

# μ„œλ²„
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server.bind("/tmp/my.sock")
server.listen(1)
conn, _ = server.accept()
data = conn.recv(1024)

# ν΄λΌμ΄μ–ΈνŠΈ
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect("/tmp/my.sock")
client.send(b"hello")

TCP/UDP μ†ŒμΌ“κ³Ό 달리 파일 μ‹œμŠ€ν…œ 경둜둜 μ—°κ²°ν•˜κΈ° λ•Œλ¬Έμ— 같은 호슀트 μ•ˆμ—μ„œλ§Œ λ™μž‘ν•œλ‹€.

6. μ‹œκ·Έλ„ (Signal)

데이터λ₯Ό μ „λ‹¬ν•˜λŠ” 게 μ•„λ‹ˆλΌ 이벀트 λ°œμƒμ„ μ•Œλ¦¬λŠ” μš©λ„. λΉ„λ™κΈ°μ μœΌλ‘œ μ „λ‹¬λœλ‹€.

kill -9 1234   # PID 1234 ν”„λ‘œμ„ΈμŠ€μ— SIGKILL 전솑
kill -15 1234  # SIGTERM (정상 μ’…λ£Œ μš”μ²­)
#include <signal.h>

void handler(int sig) {
    printf("Received signal: %d\n", sig);
}

signal(SIGINT, handler);  // Ctrl+C μž…λ ₯ μ‹œ handler μ‹€ν–‰

자주 μ“°λŠ” μ‹œκ·Έλ„:

μ‹œκ·Έλ„λ²ˆν˜Έμ˜λ―Έ
SIGINT2μΈν„°λŸ½νŠΈ (Ctrl+C)
SIGKILL9κ°•μ œ μ’…λ£Œ (λ¬΄μ‹œ λΆˆκ°€)
SIGTERM15정상 μ’…λ£Œ μš”μ²­
SIGSEGV11μ„Έκ·Έλ©˜ν…Œμ΄μ…˜ 폴트
SIGCHLD17μžμ‹ ν”„λ‘œμ„ΈμŠ€ μƒνƒœ λ³€ν™”

IPC 방식 비ꡐ 정리

방식속도방ν–₯κ΄€κ³„μ—†λŠ” ν”„λ‘œμ„ΈμŠ€λΉ„κ³ 
Pipe쀑간단방ν–₯λΆˆκ°€λΆ€λͺ¨-μžμ‹ μ „μš©
Named Pipe쀑간단방ν–₯κ°€λŠ₯파일 μ‹œμŠ€ν…œ 경둜
Message Queue쀑간양방ν–₯κ°€λŠ₯비동기, νƒ€μž… ꡬ뢄
Shared Memory빠름양방ν–₯κ°€λŠ₯동기화 별도 ν•„μš”
SocketλŠλ¦Όμ–‘λ°©ν–₯κ°€λŠ₯λ„€νŠΈμ›Œν¬λ„ κ°€λŠ₯
Signal-단방ν–₯κ°€λŠ₯데이터 전달 λΆˆκ°€

선택 κΈ°μ€€

  • 속도가 μ΅œμš°μ„ μ΄κ³  같은 λ¨Έμ‹  β†’ 곡유 λ©”λͺ¨λ¦¬
  • λ‹¨μˆœν•œ 데이터 흐름, λΆ€λͺ¨-μžμ‹ 관계 β†’ νŒŒμ΄ν”„
  • 비동기 λ©”μ‹œμ§€ 전달 β†’ λ©”μ‹œμ§€ 큐
  • λΆ„μ‚° ν™˜κ²½ ν™•μž₯μ„± κ³ λ € β†’ μ†ŒμΌ“
  • 이벀트 μ•Œλ¦Όλ§Œ ν•„μš” β†’ μ‹œκ·Έλ„

λ¦¬λˆ…μŠ€ 컀널 λ‚΄λΆ€μ—μ„œλ„ ν”„λ‘œμ„ΈμŠ€ κ°„ ν˜‘λ ₯이 ν•„μš”ν•œ 경우 μœ„ λ©”μ»€λ‹ˆμ¦˜λ“€μ„ μ‘°ν•©ν•΄μ„œ μ‚¬μš©ν•œλ‹€. μ‹€μ œ μ‹œμŠ€ν…œ ν”„λ‘œκ·Έλž˜λ°μ—μ„œλŠ” 곡유 λ©”λͺ¨λ¦¬ + μ„Έλ§ˆν¬μ–΄ 쑰합이 μ„±λŠ₯상 자주 μ„ νƒλ˜κ³ , λΆ„μ‚° μ‹œμŠ€ν…œμœΌλ‘œ ν™•μž₯을 κ³ λ €ν•œλ‹€λ©΄ μ²˜μŒλΆ€ν„° μ†ŒμΌ“(λ˜λŠ” λ©”μ‹œμ§€ 브둜컀) 기반으둜 μ„€κ³„ν•˜λŠ” 편이 λ‚«λ‹€.