• 文章中心
  • 简述Linux 多线程同步之消息队列

    作者:好用官网u盘装系统 文章来源:u盘装系统 发布时间:2014-05-15 13:03点击:

      消息队列是消息的链表,存放在内核中并有消息队列标示符标示。
      msgget用于创建一个新队列或打开一个现存的队列。msgsnd将新消息加入到消息队列中;每个消息包括一个long型的type;和消息缓存;msgrcv用于从队列中取出消息;取消息很智能,不一定先进先出
      ①msgget,创建一个新队列或打开一个现有队列
      #include <sys/msg.h>
      int msgget ( key_t key, int flag );
      //成功返回消息队列ID;错误返回-1
      ②msgsnd: 发送消息
      #include <sys/msg.h>
      int msgsnd( int msgid, const void* ptr, size_t nbytes, int flag )
      //成功返回0,错误返回-1
      a:   flag可以指定为IPC_NOWAIT;  若消息队列已满,则msgsnd立即出错返回EABAIN;
      若没指定IPC_NOWAIT; msgsnd会阻塞,直到消息队列有空间为止
      ③msgrcv: 读取消息:
      ssize_t msgrcv( int msgid, void* ptr, size_t nbytes, long type, int flag );
      a. type == 0; 返回消息队列中第一个消息,先进先出
      b. type > 0    返回消息队列中类型为tpye的第一个消息
      c. type < 0    返回消息队列中类型 <=  |type| 的数据;若这种消息有若干个,则取类型值最小的消息
      消息队列创建步骤:
      #define   MSG_FILE "."
      struct msgtype {
      long mtype;
      char buffer[BUFFER+1];
      };
      if((key=ftok(MSG_FILE,'a'))==-1)
      {
      fprintf(stderr,"Creat Key Error:%s\n", strerror(errno));
      exit(1);
      }
      if((msgid=msgget(key, IPC_CREAT | 0666/*PERM*/))==-1)
      {
      fprintf(stderr,"Creat Message  Error:%s\n", strerror(errno));
      exit(1);
      }
      msg.mtype = 1;
      strncpy(msg.buffer, argv[1], BUFFER);
      msgsnd(msgid, &msg, sizeof(struct msgtype), 0);
      msgrcv(msgid, &msg, sizeof(struct msgtype), 1, 0);
      示例代码:
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <errno.h>
      #include <sys/types.h>
      #include <sys/ipc.h>
      #include <sys/msg.h>
      #include <sys/stat.h>
      #include <pthread.h>
      #define   MSG_FILE "."
      #define   BUFFER 255
      #define   PERM S_IRUSR|S_IWUSR
      #define IPCKEY 0x111
      struct msgtype {
      long mtype;
      char buffer[BUFFER+1];
      };
      void* thr_test( void* arg ){
      struct msgtype msg;
      int msgid;
      msgid =  *((int*)arg);
      printf("msqid = %d  IPC_NOWAIT = %d\n", msgid, IPC_NOWAIT);
      time_t tt = time(0)+8;
      //while( time(0) <= tt )
      //{
      msgrcv(msgid, &msg, sizeof(struct msgtype), 1, 0);
      fprintf(stderr,"Server Receive:%s\n", msg.buffer);
      msg.mtype = 2;
      msgsnd(msgid, &msg, sizeof(struct msgtype), 0);
      //}
      pthread_exit( (void*)2 );
      }
      int main(int argc, char **argv)
      {
      struct msgtype msg;
      key_t key;
      int msgid;
      pthread_t tid;
      if(argc != 2)
      {
      fprintf(stderr,"Usage:%s string\n", argv[0]);
      exit(1);
      }
      /*
      char path[256];
      sprintf( path, "%s/", (char*)getenv("HOME") );
      printf( "path is %s\n", path );
      msgid=ftok( path, IPCKEY );
      */
      if((key=ftok(MSG_FILE,'a'))==-1)
      {
      fprintf(stderr,"Creat Key Error:%s\n", strerror(errno));
      exit(1);
      }
      if((msgid=msgget(key, IPC_CREAT | 0666/*PERM*/))==-1)
      {
      fprintf(stderr,"Creat Message  Error:%s\n", strerror(errno));
      exit(1);
      }
      pthread_create( &tid, NULL, thr_test, &msgid );
      fprintf(stderr,"msid is :%d\n", msgid);
      msg.mtype = 1;
      strncpy(msg.buffer, argv[1], BUFFER);
      msgsnd(msgid, &msg, sizeof(struct msgtype), 0);
      exit(0);
      }