본문 바로가기
개발

생산자-소비자 패턴

by jonnwon 2025. 10. 17.
728x90
반응형

 

System V MQ 시나리오

 

[생산자 프로세스] -> [OS 커널 속 메시지 큐] -> [소비자 프로세스]

 

여기서 메시지큐(Message Queue)는 커널이 관리하는 메모리 공간이고, 양쪽 프로세스는 시스템 콜(system call)을 통해서만 접근

 

1. 생산자가 하는 일

 

1) msgsnd() 호출

 -> 유저 프로세스 -> 커널 진입 (시스템콜)

 

2) 커널이 메시지큐(커널 메모리)에 공간이 있는지 확인

 - 큐가 가득 차면(blocking 모드) -> 생산자 프로세스는 슬립(block)

 - 공간이 있으면 메시지를 복사(copy) 해서 커널 큐에 저장

 

3) 메시지 큐에 들어오면

 - 그 큐를 기다리던 소비자 프로세스가 있다면, 커널이 깨워줌(wake up)

 - 커널 입장에서 이건 이벤트 트리거에 가깝지만 사용자에게 직접 이벤트가 전달되진 않음

 

 

즉, 생산자는 데이터를 OS에게 “여기 넣어줘요” 하고 맡기고, 커널이 큐 상태를 관리하며, 대기 중인 소비자를 깨워줌.

 

 

2. 소비자가 하는 일

 

1) msgcrv() 호출

 - 큐가 비어 있다면, 소비자는 커널에서 block 상태로 대기

 - 메시지가 들어올 때까지 CPU 자원을 거의 안 씀 (sleep 상태)

 

2) 생산자가 메시지를 보내면

 - 커널이 그 소비자를 깨워서(run queue에 올림)

 - 소비자가 깨어나면 커널이 메시지를 유저 프로세스 메모리로 복사

 

3) 소비자는 받은 데이터를 처리하고 다시 msgrcv() 호출해 다음 메시지를 기다림

 

 즉, 이벤트처럼 보이지만 실제로는 “슬립 & 웨이크업”으로 구현된 이벤트 흐름

 

 

3. OS 내부에서 일어나는 일 (커널 시점)

 

msgsnd() 호출 : 생산자의 데이터를 커널 큐에 복사

큐가 가득 차면 : 생산자 프로세스 block 상태로 큐 공간이 날 때까지 대기

msgrcv() 호출 : 큐가 비면 소비자 프로세스 block

메시지 도착 : 커널이 block 상태의 소비자를 깨움(wakeup)

메시지 전달 : 커널이 데이터 복사 후 소비자에게 리턴

 

 

4. '이벤트'의 본질

 

생산자가 메시지를 보낼 때 커널이 내부적으로 대기 중인 소비자에게 wake-up 신호를 줌

즉, 진짜 “이벤트 객체”가 아니라 스케줄러 레벨에서 깨어나는 일

 

커널 입장에서 보면

  -> 이벤트를 명시적으로 push하는 게 아니라, “데이터가 큐에 들어옴 → wait queue에 있던 프로세스를 깨움” 이 전부

 

 

5. POSIX MQ(mq_*)

 

POSIX 메시지큐(mq_send, mq_receive)는 System V보다 한 단계 발전

 

- 메시지큐 자체가 파일 디스크립터로 표현됨 (→ epoll로 감시 가능)

- mq_notify()커널이 시그널이나 스레드 콜백으로 이벤트 통지 가능

 

즉, 진짜 “이벤트 발생”을 하고 싶다면, POSIX 메시지큐 쪽이 적합

 

struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
mq_notify(mq, &sev);

-> 메시지 도착 시 커널이 SIGUSR1 신호 발생

 

 

 


 

System V 메시지큐 느림

 - 매번 유저 공간 ↔ 커널 공간 복사(copy) 발생

 - 시스템콜 오버헤드 있음

 - 스케줄러 wake-up 지연 존재

 

참고 (커널 안거침)

 - Shared Memory Ring Buffer (Lock-Free Queue)

 - mmap + spin/poll 기반 이벤트링

 - user-space networking (DPDK, io_uring)

 

System V MQ 와 POSIX MQ 모두 '메시지 1건 도착' 단위로 깨워짐

따라서 소비자는 보통 하나만 읽고 다시 블록(block) 하거나 루프를 돌며 계속 읽는 구조로 작성됨

 

큐가 완전히 빌 때 까지 계속 읽지 않음.

728x90