Interview/OS
Multiprocess 간 IPC 중 Message Queue MQ 통신
김 정출
2024. 9. 27. 17:59
Multiprocess 간의 통신(IPC, Inter-Process Communication)은 서로 다른 프로세스가 데이터를 주고받거나 리소스를 공유하는 방법입니다. 운영체제에서 프로세스는 독립된 메모리 공간을 가지기 때문에 직접적으로 데이터를 공유할 수 없습니다. 따라서 IPC 기법을 사용하여 프로세스 간의 데이터를 전달하거나 동기화해야 합니다.
Linux 및 Unix에서 사용하는 다양한 IPC 방법들을 아래에 설명합니다.
2. 메시지 큐 (Message Queue)
- 메시지 큐는
커널이 관리하는 큐에 데이터를 메시지 단위로 보내고 받을 수 있는 방법
입니다. FIFO 방식으로 동작하며, 각 메시지에는 타입이 지정되므로, 수신자는 메시지 타입에 따라 특정 메시지만 받을 수 있습니다. 단방향 통신이나 양방향 통신 모두 가능하며, 동기화와 순서 보장
이 가능합니다.- 커널에 의해 큐가 관리되므로, 중앙 집중식 데이터 전달이 가능하다.
메시지 큐 동작
- msgget(): 메시지 큐를 생성하거나 가져옵니다.
- msgsnd(): 큐에 메시지를 보냅니다.
- msgrcv(): 큐에서 메시지를 읽습니다.
- msgctl(): 큐를 삭제하거나 속성을 제어합니다.
메시지 큐는 직렬화가 필요한 데이터를 처리할 때 유용합니다.
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define KEY 1234 // 메시지 큐를 구분하는 키값
struct msgbuf {
long mtype; // 메시지 타입
char mtext[100]; // 메시지 내용
};
int main() {
int msgid;
struct msgbuf message;
// 1. 메시지 큐 생성 또는 가져오기
msgid = msgget(KEY, IPC_CREAT | 0666); // 메시지 큐 생성 및 읽기/쓰기 권한
if (msgid == -1) {
perror("msgget failed");
return 1;
}
// 2. 메시지 전송
message.mtype = 1; // 메시지 타입 지정
strcpy(message.mtext, "Hello from sender!");
if (msgsnd(msgid, &message, sizeof(message.mtext), 0) == -1) {
perror("msgsnd failed");
return 1;
}
printf("Message sent: %s\n", message.mtext);
// 2. 메시지 큐 삭제
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl failed");
return 1;
}
printf("Message queue deleted successfully.\n");
return 0;
}
// 다른 프로세스
int main() {
int msgid;
struct msgbuf message;
// 1. 메시지 큐 가져오기
msgid = msgget(KEY, 0666); // 메시지 큐 가져오기 (생성하지 않고 기존 큐 사용)
if (msgid == -1) {
perror("msgget failed");
return 1;
}
// 2. 메시지 수신
if (msgrcv(msgid, &message, sizeof(message.mtext), 1, 0) == -1) {
perror("msgrcv failed");
return 1;
}
printf("Message received: %s\n", message.mtext);
return 0;
}
장점
- 비동기 통신
비동기적으로 메시지를 주고받을 수 있습니다. 즉, 송신자는 메시지를 큐에 넣고 즉시 다른 작업을 계속할 수 있으며, 수신자는 필요할 때 메시지를 읽으면 됩니다. 이 덕분에 송신자와 수신자가 동시에 실행될 필요가 없습니다.
- 영속성
메시지 큐는 커널에서 관리되기 때문에 송신자가 메시지를 큐에 넣은 후, 수신자가 그 메시지를 처리하기 전까지 메시지가 큐에 유지됩니다. 따라서 송신자와 수신자가 동시에 실행되지 않아도 안전하게 메시지를 전달할 수 있습니다. - 우선순위 처리 가능
메시지에 우선순위를 부여할 수 있어, 수신자가 메시지를 읽을 때 우선순위에 따라 처리 순서를 조정할 수 있습니다. 이를 통해 중요한 메시지를 먼저 처리할 수 있습니다. - 다수 프로세스 간 통신
하나의 메시지 큐를 여러 프로세스가 공유할 수 있기 때문에, 여러 프로세스 간에 메시지 큐를 이용하여 데이터를 주고받는 다대다 통신이 가능합니다. 이는 단방향 통신을 제공하는pipe()
와 차별되는 중요한 장점입니다. - 메모리 공유가 아닌 안전한 통신
메시지 큐는 공유 메모리를 사용하지 않기 때문에 메모리 충돌이나 동기화 문제를 신경 쓸 필요가 없습니다. 데이터는 메시지 큐를 통해 복사되어 전달되므로 데이터 충돌 문제가 발생하지 않습니다. - 유연성
메시지 큐는 임의의 길이의 데이터를 주고받을 수 있으므로, 고정된 길이를 가진 데이터를 처리해야 하는pipe
나 다른 IPC 기법보다 더 유연한 데이터 전송이 가능합니다. - 제한된 자원 관리
커널에서 메시지 큐에 대한 자원을 관리하므로, 시스템 리소스 사용이 명확하게 제한되고 관리됩니다. 이는 직접적인 메모리 접근이나 파일 기반 통신보다 안전합니다. - 프로세스 간의 독립성 보장
메시지 큐를 사용하면 프로세스들이 서로의 존재를 몰라도 통신이 가능합니다. 송신자와 수신자는 서로의 프로세스 ID나 메모리 주소 등을 알 필요가 없으며, 메시지를 큐에 넣고 큐에서 읽기만 하면 됩니다. 이는 모듈화된 설계에 도움이 됩니다.