공유 메모리(shared memory)가 이미 있는데도 굳이 메시지 큐(message queue)가 필요할까요? 그 이유는 여러 가지가 있습니다. 이해하기 쉽도록 몇 가지 항목으로 나누어 살펴보겠습니다.
공유 메모리 대신 메시지 큐를 사용하는 이유
메시지 큐에서는 한 프로세스가 메시지를 수신하면 해당 메시지는 다른 어떤 프로세스에게도 더 이상 제공되지 않습니다. 반면 공유 메모리의 데이터는 여러 프로세스가 동시에 접근할 수 있습니다.
작은 크기의 메시지 형식으로 통신하고자 할 때 적합합니다.
공유 메모리는 여러 프로세스가 동시에 통신할 경우 데이터 보호를 위한 동기화(synchronization) 처리가 반드시 필요합니다.
공유 메모리를 이용한 읽기·쓰기 빈도가 매우 높다면 기능 구현이 상당히 복잡해집니다. 이런 경우에는 효율성 측면에서 메시지 큐를 사용하는 것이 바람직하지 않습니다.
모든 프로세스가 아닌 극소수의 프로세스만 데이터에 접근하면 되는 상황이라면 메시지 큐로 구현하는 것이 더 효과적입니다.
서로 다른 데이터 패킷으로 통신해야 할 때, 예컨대 프로세스 A가 프로세스 B에는 1번 타입, C에는 10번 타입, D에는 20번 타입의 메시지를 보내야 한다면 메시지 큐로 구현하는 편이 훨씬 간단합니다. 참고로 메시지 타입은 아래에서 설명하듯 0, 양수, 음수 중 어느 것이든 될 수 있습니다.
메시지 큐는 당연히 FIFO(First In First Out, 선입선출) 방식으로 동작합니다. 큐에 가장 먼저 삽입된 메시지가 가장 먼저 인출됩니다.
결국 공유 메모리를 사용할 것인지 메시지 큐를 사용할 것인지는 애플리케이션의 요구 사항과 활용 효율에 따라 결정해야 합니다.
메시지 큐를 이용한 통신 방식
메시지 큐를 사용한 통신은 다음과 같은 방식으로 이루어질 수 있습니다.
한 프로세스가 메시지 큐에 데이터를 쓰고, 다른 프로세스가 그 데이터를 읽는 방식입니다. 참고로 읽기 작업은 여러 프로세스에서 동시에 수행할 수도 있습니다.

또한 한 프로세스가 서로 다른 데이터 패킷, 즉 메시지 타입별로 구분된 메시지를 큐에 쓰고, 여러 프로세스가 자신에게 해당하는 메시지 타입별로 읽어 가는 방식도 있습니다.

메시지 큐 지원 시스템 호출(System V)
메시지 큐에 대한 개념을 살펴보았으니 이제 메시지 큐를 지원하는 시스템 호출(System V)을 확인할 차례입니다. 메시지 큐를 이용해 통신을 수행하려면 다음 단계를 따릅니다.
1단계 − 메시지 큐를 생성하거나 이미 존재하는 메시지 큐에 연결합니다 (msgget())
2단계 − 메시지 큐에 데이터를 씁니다 (msgsnd())
3단계 − 메시지 큐에서 데이터를 읽습니다 (msgrcv())
4단계 − 메시지 큐에 대한 제어 작업을 수행합니다 (msgctl())
여기서는 두 개의 프로세스를 만들어 하나는 쓰기, 다른 하나는 읽기를 담당하도록 구성하겠습니다. 쓰기(writer) 프로세스와 읽기(reader) 프로세스가 실제로 어떻게 동작하는지 예제 코드를 통해 살펴보겠습니다.
쓰기 프로세스 예제 코드
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// 메시지 큐 구조체 정의
struct msg_buffer {
long msg_type;
char msg[100];
} message;
main() {
key_t my_key;
int msg_id;
my_key = ftok("progfile", 65); // 고유 키 생성
msg_id = msgget(my_key, 0666 | IPC_CREAT); // 메시지 큐 생성 후 ID 반환
message.msg_type = 1;
printf("Write Message : ");
fgets(message.msg, 100, stdin);
msgsnd(msg_id, &message, sizeof(message), 0); // 메시지 전송
printf("Sent message is : %s \n", message.msg);
}읽기 프로세스 예제 코드
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// 메시지 큐 구조체 정의
struct msg_buffer {
long msg_type;
char msg[100];
} message;
main() {
key_t my_key;
int msg_id;
my_key = ftok("progfile", 65); // 고유 키 생성
msg_id = msgget(my_key, 0666 | IPC_CREAT); // 메시지 큐 생성 후 ID 반환
msgrcv(msg_id, &message, sizeof(message), 1, 0); // 메시지 수신
// 메시지 출력
printf("Received Message is : %s \n", message.msg);
msgctl(msg_id, IPC_RMID, NULL); // 메시지 큐 삭제
return 0;
}실행 결과
