萬盛學電腦網

 萬盛學電腦網 >> Linux教程 >> Linux 多線程同步之消息隊列

Linux 多線程同步之消息隊列

class="154048">

  消息隊列是消息的鏈表,存放在內核中並有消息隊列標示符標示。

  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| 的數據;若這種消息有若干個,則取類型值最小的消息

  消息隊列創建步驟:

  #defineMSG_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>

  #defineMSG_FILE "."

  #defineBUFFER 255

  #definePERM 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);

  }

copyright © 萬盛學電腦網 all rights reserved