본문으로 바로가기
homeimage
  1. Home
  2. 컴퓨터/프로그래밍
  3. C언어 메시지 큐로 데이터 전송 함수 msgsnd()

C언어 메시지 큐로 데이터 전송 함수 msgsnd()

· 댓글개 · 바다야크

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
SNS 공유하기
💬 댓글 개
최근글
이모티콘창 닫기
울음
안녕
감사해요
당황
피폐

이모티콘을 클릭하면 댓글창에 입력됩니다.