当前位置:首页 > linux教程 > 列表

Linux下消息队列学习笔记

发布:smiling 来源: PHP粉丝网  添加日期:2015-04-23 22:47:33 浏览: 评论:0 

消息队列是进程间通讯的一种方法,一开始我以为消息队列是类似一个管道,一头连接一个进程、一头连接另一个进程,只能由这两个进程来进行互相的读写,其实这是错的,消息队列是系统层面的,它不属于某两个进程,它是由系统维护的一个链表结构,对消息队列的读写就是一个对链表的操作,默认是在链表的一端写数据,另一端读数据(先进先出),进程也可以取指定某种消息类型的消息.

在一个进程里创建了消息队列,且是可读可写的,那么系统中的所有进程都可以对它进行读写操作.

1、打开或创建一个消息队列

原型:int msgget(key_t key, int msgflg);

参数:

1)key:消息队列的key值。

2)msgflg:

IPC_CREAT:如果key对应的消息队列对象不存在,则创建,否则则进行打开操作,返回0.

IPC_EXCL:如果key对应的消息队列对象不存在,则返回-1;否则则进行打开操作,返回0。

权限控制:0666表示可读可写,和上面的IPC_CREAT做逻辑或操作.

返回值:成功返回,创建的或打开的消息队列的id,失败返回-1.

例子程序:test1.c,代码如下:

  1. #include <sys/types.h> 
  2. #include <sys/ipc.h> 
  3. #include <sys/msg.h> 
  4. #include <stdio.h> 
  5. int main(void) 
  6.  int msgid; 
  7.  printf("this is test1!\n"); 
  8.  
  9.  msgid = msgget(1001, 0666|IPC_CREAT); 
  10.  printf("msgid = %d\n", msgid); 
  11.  
  12.  return 0; 

执行结果:

  1. [root@server ~]# gcc -o test1 test1.c 
  2. [root@server ~]# ./test1 
  3. this is test1! 
  4. msgid = 32768 
  5. [root@server ~]# ipcs 
  6. ------ Shared Memory Segments -------- 
  7. key        shmid      owner      perms      bytes      nattch     status      
  8. ------ Semaphore Arrays -------- 
  9. key        semid      owner      perms      nsems      
  10. 0x00000000 0          root       600        1         
  11. ------ Message Queues --------  //phpfensi.com 
  12. key        msqid      owner      perms      used-bytes   messages     
  13. 0x000003e9 32768      root       666        0            0      

从ipcs命令的结果可以知道,消息队列在创建它的进程退出后,还存在于系统中,说明消息队列是系统一层的,并不是属于某个进程的.

2、设置消息队列属性(包括删除)

原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf);

参数:

1)msqid:消息队列的id.

2)cmd:执行的控制命令.

IPC_STAT:读取消息队列属性,取得此队列的msqid_ds 结构,并将其存放在buf指向的结构中.

IPC_SET:设置消息队列属性.

IPC_RMID:删除消息队列.

IPC_INFO:读取消息队列基本情况,此命令等同于 ipcs 命令.

例子程序:test2.c,代码如下:

  1. #include <sys/types.h> 
  2. #include <sys/ipc.h> 
  3. #include <sys/msg.h> 
  4. #include <stdio.h> 
  5. int main(void) 
  6.  int i; 
  7.  printf("this is test2!\n"); 
  8.  i = msgctl(32768, IPC_RMID, NULL);//这里已经知道消息id等于32768 
  9.  if (0 == i) 
  10.  { 
  11.   printf("msq deleted!\n"); 
  12.  } 
  13.  return 0; 
  14. //执行结果: 
  15. [root@server ~]# gcc -o test2 test2.c 
  16. [root@server ~]# ./test2 
  17. this is test2! 
  18. msq deleted! 
  19. [root@server ~]# ipcs 
  20. ------ Shared Memory Segments -------- 
  21. key        shmid      owner      perms      bytes      nattch     status      
  22. ------ Semaphore Arrays -------- 
  23. key        semid      owner      perms      nsems      
  24. 0x00000000 0          root       600        1         
  25. ------ Message Queues -------- 
  26. key        msqid      owner      perms      used-bytes   messages 

原有的消息队列被删除了.

3、向消息队列写/读消息

原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

参数:

1)msqid:消息队列的id.

2)msgp:指向消息缓冲区的指针,该指针指向如下的一个用户可定义的通用结构.

  1. struct mymsg { 
  2.   long mtype; 
  3.   char mbuf[1024]; 
  4. }; 

3)msgsz:消息的大小。

4)msgflg:可以为IPC_NOWAIT或0,表示操作是阻塞式的还是非阻塞式的,设置为IPC_NOWAIT,在msgsnd()中,如果消息队列已经满了,则不会阻塞,立即返回-1(EAGAIN).

在msgrcv()中,如果消息队列为空,则不做等待,立即返回-1(ENOMSG),设置为0,在msgsnd()中,进程阻塞直到(a)有空间可以容纳要发送的消息;或(b)从系统中删除了此队列(返回EIDRM);或(c)捕捉到一个信号,并从信号处理程序返回(返回EINTR)。

在msgrcv()中,进程阻塞直到(a)有了指定类型的消息;或(b)从系统中删除了此队列(返回EIDRM);或(c)捕捉到一个信号并从信号处理程序返回(返回EINTR)。

5)msgtype:用于msgrcv()函数,指定消息的类型。相当于区分消息类别的标志位。

msgtype = 0,返回消息队列中的第一个消息。

返回值:

msgsnd(),成功返回0,出错返回-1。

msgrcv(),成功返回消息数据部分的长度,出错返回-1。

例子程序:test3.c,代码如下:

  1. #include <sys/types.h> 
  2. #include <sys/ipc.h> 
  3. #include <sys/msg.h> 
  4. #include <stdio.h> 
  5. #include <errno.h> 
  6. typedef struct 
  7.  long mtype; 
  8.  char mbuf[1024]; 
  9. }mymsg; 
  10. int main(void) 
  11.  int i; 
  12.  int msgid1, msgid2; 
  13.  mymsg message1, message2, message3; 
  14.  
  15.  printf("this is test3!\n"); 
  16.  
  17.  msgid1 = msgget(1002, 0666|IPC_CREAT);//key 1002 
  18.  if (msgid1 < 0) 
  19.  { 
  20.   printf("create key=1002 error, errno=%d\n", errno); 
  21.   exit(-1); 
  22.  } 
  23.  msgid2 = msgget(1003, 0666|IPC_CREAT);//key 1003 
  24.  if (msgid2 < 0) 
  25.  { 
  26.   printf("create key=1003 error, errno=%d\n", errno); 
  27.   exit(-1); 
  28.  } 
  29.  //初始化 
  30.  message1.mtype = 1;//设定一个消息类型 
  31.  memcpy(message1.mbuf, "first message", 13); 
  32.  message3.mtype = 1; 
  33.  memcpy(message3.mbuf, "hello test4.", 12); 
  34.  
  35.  //test3进程在msgid1上发消息 
  36.  i = msgsnd(msgid1, (void *)&message1, strlen(message1.mbuf)+1, 0); 
  37.  if (i < 0) 
  38.  { 
  39.   printf("send message1 error, errno=%d\n", errno); 
  40.   exit(-1); 
  41.  } 
  42.  
  43.  //test3进程从msgid1取消息,存到message2中 
  44.  i = msgrcv(msgid1, (void *)&message2, 1024, 0, 0); 
  45.  if (i < 0) 
  46.  { 
  47.   printf("rev error, errno=%d\n", errno); 
  48.   exit(-1); 
  49.  } 
  50.  else 
  51.  { 
  52.   //显示取出的消息 
  53.   printf("%s\n", message2.mbuf); 
  54.  } 
  55.  //test3进程在msgid2上发消息 
  56.  i = msgsnd(msgid2, (void *)&message3, strlen(message3.mbuf)+1, 0); 
  57.  if (i < 0) 
  58.  { 
  59.   printf("send message3 error, errno=%d\n", errno); 
  60.   exit(-1); 
  61.  } 
  62.  
  63.  return 0; 

例子程序:test4.c,代码如下:

  1. #include <sys/types.h> 
  2. #include <sys/ipc.h> 
  3. #include <sys/msg.h> 
  4. #include <stdio.h> 
  5. #include <errno.h> 
  6. typedef struct 
  7.  long mtype; 
  8.  char mbuf[1024]; 
  9. }mymsg; 
  10. int main(void) 
  11.  int i, j; 
  12.  mymsg message; 
  13.  
  14.  printf("this is test4!\n"); 
  15.  
  16.  i = msgget(1003, 0666|IPC_CREAT); 
  17.  if (i < 0) 
  18.  { 
  19.   printf("create key=1003 error, errno=%d\n", errno); 
  20.   exit(-1); 
  21.  } 
  22.  
  23.  //test4进程在key=1003的消息队列上取消息 
  24.  j = msgrcv(i, (void *)&message, 1024, 0, 0); 
  25.  if (j < 0) 
  26.  { 
  27.   printf("rev error, errno=%d\n", errno); 
  28.   exit(-1); 
  29.  } 
  30.  else 
  31.  { 
  32.   //显示取出的消息 
  33.   printf("%s\n", message.mbuf); 
  34.  } 
  35.  
  36.  return 0; 

开两个终端,一个执行test3,另一个执行test4.

test3执行结果,代码如下:

  1. [root@server ~]# ./test3 
  2. this is test3! 
  3. first message 

ipcs命令能看到key=1003的消息队列中有一条消息,使用了13字节长度,代码如下:

  1. key        msqid      owner      perms      used-bytes   messages 
  2. 0x000003ea 98305      root       666        0            0        
  3. 0x000003eb 131074     root       666        13           1        
  4. //test4执行结果: 
  5. [root@server ~]# ./test4 
  6. this is test4! 
  7. hello test4. 

以上.

Tags: Linux消息队列 Linux队列消息

分享到: