msgget() function in C language
메시지 큐를 생성합니다.
- 헤더: sys/types.h, sys/ipc.h, sys/msg.h
- 형태: int msgget ( key_t key, int msgflg )
- 인수: key_t key 시스템에서 다른 큐와 구별되는 번호
int msgflg 옵션 - 반환: -1 == 실패, 이외는 메시지 큐 식별자
메시지 큐는 IPC 방법 중에 하나로 자료를 다른 프로세스로 전송할 수 있습니다. 전송되는 자료도 큐의 용량이 허용하는 한, 상대편이 가져가지 않는다고 하더라도 계속 전송할 수 있으며, 나중에 다른 프로세스가 큐가 비워질 때까지 계속 읽어 들일 수 있습니다.
또한 메시지 큐는 전송한는 자료를 커널이 간직하기 때문에 전송한 프로세스가 종료되었다고 하더라고 자료가 사라지지 않습니다. 즉, 전송 프로세스가 데이터를 전송한 후 종료해도, 나중에 다른 프로세스가 메시지 큐의 데이터를 가져 올 수 있습니다.
또한 전송되는 큐의 자료는 순자적으로 가져 갈 수도 있지만 데이터 타입에 따라 원하는 자료만 가져 갈 수 있습니다. 즉, 메시지 큐에 전송되는 데이터 구조는 아래와 같습니다.
struct {
long data_type;
char data_buff[BUFF_SIZE];
}
또는
struct {
long data_type;
int data_num;
char data_buff[BUFF_SIZE];
}
또는
struct {
long data_type;
int data_num;
}
이런 식으로 구성할 수 있습니다. 즉, 데이터 타입을 나타내는 long 값을 첫번째로 놓는다면 이후의 구조는 자유롭게 구성할 수 있다는 것입니다.
그리고 나중에 자료를 수신하는 쪽은 data_type 값 중에 특정 값으로 설정된 자료만 뽑아서 가져갈 수 있으면, 가져간 자료는 당연이 메시지 큐에서 제거됩니다.
예제에서는 data_type 2 인 것만 뽑아 가다가 나중에는 모든 데이터를 가져가는 방법을 보여 주고 있습니다.
msgget()은 이와 같은 메시지 큐를 생성합니다.
int msgget ( key_t key, int msgflg )
key_t key는 다른 큐와 구별하기 위한 번호입니다. 큐에 대한 번호를 알고 있다면 알고 있는 프로세스끼리 같은 번호의 큐를 사용할 수 있습니다.
int msgflg는 메시지 큐를 만들기 위한 옵션으로 아래와 같은 값을 사용할 수 있습니다.
msgflg | 의미 |
IPC_CREAT | key에 해당하는 큐가 있다면 큐의 식별자를 반환하며, 없으면 생성합니다. |
IPC_EXCL | key에 해당하는 큐가 없다면 생성하지만 있다면 -1을 반환하고 복귀합니다. |
C언어 msgget() 함수 예제
////////////////////////// main_receiver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define BUFF_SIZE 1024
typedef struct {
long data_type;
int data_num;
char data_buff[BUFF_SIZE];
} t_data;
int main( void)
{
int msqid;
t_data data;
if ( -1 == ( msqid = msgget( (key_t)1234, IPC_CREAT ¦ 0666))){
perror( "msgget() 실패");
exit( 1);
}
while( 1 ){
// 메시지 큐 중에 data_type 이 2 인 자료만 수신
if ( -1 == msgrcv( msqid, &data, sizeof( t_data) - sizeof( long), 2, 0)){
perror( "msgrcv() 실패");
exit( 1);
}
printf( "%d - %s\n", data.data_num, data.data_buff);
}
}
////////////////////////// main_sender.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define BUFF_SIZE 1024
typedef struct {
long data_type;
int data_num;
char data_buff[BUFF_SIZE];
} t_data;
int main( void)
{
int msqid;
int ndx = 0;
t_data data;
if ( -1 == ( msqid = msgget( (key_t)1234, IPC_CREAT ¦ 0666))){
perror( "msgget() 실패");
exit( 1);
}
while( 1 ){
data.data_type = ( ndx++ % 3) +1; // data_type 는 1, 2, 3
data.data_num = ndx;
sprintf( data.data_buff, "type=%ld, ndx=%d, http://badayak.com", data.data_type, ndx);
if ( -1 == msgsnd( msqid, &data, sizeof( t_data) - sizeof( long), 0)){
perror( "msgsnd() 실패");
exit( 1);
}
sleep( 1);
}
}
receiver | sender |
]$ gcc receiver.c -o receiver.out ]$ ./receiver.out 2 - type=2, ndx=2, http://badayak.com 5 - type=2, ndx=5, http://badayak.com 8 - type=2, ndx=8, http://badayak.com 11 - type=2, ndx=11, http://badayak.com 14 - type=2, ndx=14, http://badayak.com 여기서 멈춤이 일어 납니다. 왜냐하면 receiver 가 data_type 이 2 인 것만 가져 갔기 때문에 메시지 큐가 포화되었기 때문입니다. Ctrl-C 키로 receiver를 종료한 후에 main_reciever.c의 msgrcv() 인수 중 data_type를 0으로 변경한 후 실행하면 큐에 쌓인 자료를 읽어 들여서 큐를 비우게 되면 sender에서 다시 전송할 수 있게 되고 receiver도 수신을 계속할 수 있습니다. |
]$ gcc sender.c -o sender.out ]$ ./sender.out |
main_reciever.c의 msgrcv()의 인수 중 data_type 를 0 으로 변경한 후 다시 실행해 보겠습니다.
////////////////////////// main_receiver.c
:
while( 1 ){
// 메시지 큐 중에 data_type이 0 인 자료만 수신
if ( -1 == msgrcv( msqid, &data, sizeof( t_data) - sizeof( long), 0, 0)){
perror( "msgrcv() 실패");
exit( 1);
}
receiver | sender |
]$ gcc receiver.c -o receiver.out ]$ ./receiver.out 1 - type=1, ndx=1, http://badayak.com 2 - type=2, ndx=2, http://badayak.com 3 - type=3, ndx=3, http://badayak.com 4 - type=1, ndx=4, http://badayak.com 5 - type=2, ndx=5, http://badayak.com 6 - type=3, ndx=6, http://badayak.com 7 - type=1, ndx=7, http://badayak.com 8 - type=2, ndx=8, http://badayak.com 9 - type=3, ndx=9, http://badayak.com 10 - type=1, ndx=10, http://badayak.com 11 - type=2, ndx=11, http://badayak.com 12 - type=3, ndx=12, http://badayak.com 13 - type=1, ndx=13, http://badayak.com : |
]$ gcc sender.c -o sender.out ]$ ./sender.out |
'컴퓨터 > 프로그래밍' 카테고리의 다른 글
C언어 메시지 큐로 데이터 전송 함수 msgsnd() (0) | 2020.03.16 |
---|---|
C언어 FIFO 파이프 만들기 함수 mkfifo() (0) | 2020.03.16 |
C언어 파이프를 이용한 IPC 함수 pipe() (0) | 2020.03.16 |