C함수 메시지 큐로 데이터 전송 msgsnd()
메시지 큐를 전송합니다.
- 헤더: sys/types.h, sys/ipc.h, sys/msg.h
- 형태: int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
- 인수: int msqid 메시지 큐 식별자
void *msgp 전송할 자료
size_t msgsz 전송할 자료의 크기
int msgflg 동작 옵션, 위의 설명 글을 참고하여 주십시오. - 반환: 0 == 성공, -1 == 실패
msgid는 메시지 큐의 식별자 입니다. msgp는 msgget()에서 설명을 드렸습니다만 전송 대상인 데이터 입니다. 메시지 큐에 전송되는 데이터 구조는 아래와 같습니다.
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 값을 항상 첫 번째에 가지고 있으며, 이 값을 이용하여 원하는 자료만 걸러 낼 수 있습니다. 그러므로 데이터의 크기에는 long 값이 반드시 들어 가기 때문에 data type을 나타내는 long 크기는 제거합니다. 그래서 예제에서도 long 크기를 제거했습니다.
sizeof( t_data) - sizeof( long)
상대 프로세스가 메시지 큐에 쌓이 자료를 계속 잘 가져간다면 전송을 계속할 수 있습니다만 만일 자료를 가져가지 못한다면 큐의 용량에 따라 전송에 실패할 수 있습니다. 이럴 때에는 상대가 자료를 가져가고 큐가 비워질 때까지 기다릴 수 있고, 또는 실패를 했음을 확인하면서 바로 복귀할 수 있습니다.
이와 같은 동작 선택은 마지막 인수인 int msgflg 의 값을 이용하면됩니다.
msgflg | 의미 |
IPC_CREAT | key에 해당하는 큐가 있다면 큐의 식별자를 반환하며, 없으면 생성합니다. |
IPC_EXCL | key에 해당하는 큐가 없다면 생성하지만 있다면 -1을 반환하고 복귀합니다. |
C언어 msgsnd() 함수 예제
////////////////////////// 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언어 메시지 큐로부터 데이터 수신 함수 msgrcv() (1) | 2020.03.16 |
---|---|
C언어 메시지 큐 생성 함수 msgget() (0) | 2020.03.16 |
C언어 FIFO 파이프 만들기 함수 mkfifo() (0) | 2020.03.16 |