Linux下消息队列学习笔记

小潘seo 重庆小潘seo博客和你一起学习SEO知识,共同分享SEO优化~

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

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

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. intmain(void)
  6. {
  7. intmsgid;
  8. printf("thisistest1!\n");
  9. msgid=msgget(1001,0666|IPC_CREAT);
  10. printf("msgid=%d\n",msgid);
  11. return0;
  12. }

执行结果:

  1. [root@server~]#gcc-otest1test1.c
  2. [root@server~]#./test1
  3. thisistest1!
  4. msgid=32768
  5. [root@server~]#ipcs
  6. ------SharedMemorySegments--------
  7. keyshmidownerpermsbytesnattchstatus
  8. ------SemaphoreArrays--------
  9. keysemidownerpermsnsems
  10. 0x000000000root6001
  11. ------MessageQueues--------//phpfensi.com
  12. keymsqidownerpermsused-bytesmessages
  13. 0x000003e932768root66600

从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. intmain(void)
  6. {
  7. inti;
  8. printf("thisistest2!\n");
  9. i=msgctl(32768,IPC_RMID,NULL);//这里已经知道消息id等于32768
  10. if(0==i)
  11. {
  12. printf("msqdeleted!\n");
  13. }
  14. return0;
  15. }
  16. //执行结果:
  17. [root@server~]#gcc-otest2test2.c
  18. [root@server~]#./test2
  19. thisistest2!
  20. msqdeleted!
  21. [root@server~]#ipcs
  22. ------SharedMemorySegments--------
  23. keyshmidownerpermsbytesnattchstatus
  24. ------SemaphoreArrays--------
  25. keysemidownerpermsnsems
  26. 0x000000000root6001
  27. ------MessageQueues--------
  28. keymsqidownerpermsused-bytesmessages

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

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. structmymsg{
  2. longmtype;
  3. charmbuf[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. typedefstruct
  7. {
  8. longmtype;
  9. charmbuf[1024];
  10. }mymsg;
  11. intmain(void)
  12. {
  13. inti;
  14. intmsgid1,msgid2;
  15. mymsgmessage1,message2,message3;
  16. printf("thisistest3!\n");
  17. msgid1=msgget(1002,0666|IPC_CREAT);//key1002
  18. if(msgid1<0)
  19. {
  20. printf("createkey=1002error,errno=%d\n",errno);
  21. exit(-1);
  22. }
  23. msgid2=msgget(1003,0666|IPC_CREAT);//key1003
  24. if(msgid2<0)
  25. {
  26. printf("createkey=1003error,errno=%d\n",errno);
  27. exit(-1);
  28. }
  29. //初始化
  30. message1.mtype=1;//设定一个消息类型
  31. memcpy(message1.mbuf,"firstmessage",13);
  32. message3.mtype=1;
  33. memcpy(message3.mbuf,"hellotest4.",12);
  34. //test3进程在msgid1上发消息
  35. i=msgsnd(msgid1,(void*)&message1,strlen(message1.mbuf)+1,0);
  36. if(i<0)
  37. {
  38. printf("sendmessage1error,errno=%d\n",errno);
  39. exit(-1);
  40. }
  41. //test3进程从msgid1取消息,存到message2中
  42. i=msgrcv(msgid1,(void*)&message2,1024,0,0);
  43. if(i<0)
  44. {
  45. printf("reverror,errno=%d\n",errno);
  46. exit(-1);
  47. }
  48. else
  49. {
  50. //显示取出的消息
  51. printf("%s\n",message2.mbuf);
  52. }
  53. //test3进程在msgid2上发消息
  54. i=msgsnd(msgid2,(void*)&message3,strlen(message3.mbuf)+1,0);
  55. if(i<0)
  56. {
  57. printf("sendmessage3error,errno=%d\n",errno);
  58. exit(-1);
  59. }
  60. return0;
  61. }

例子程序: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. typedefstruct
  7. {
  8. longmtype;
  9. charmbuf[1024];
  10. }mymsg;
  11. intmain(void)
  12. {
  13. inti,j;
  14. mymsgmessage;
  15. printf("thisistest4!\n");
  16. i=msgget(1003,0666|IPC_CREAT);
  17. if(i<0)
  18. {
  19. printf("createkey=1003error,errno=%d\n",errno);
  20. exit(-1);
  21. }
  22. //test4进程在key=1003的消息队列上取消息
  23. j=msgrcv(i,(void*)&message,1024,0,0);
  24. if(j<0)
  25. {
  26. printf("reverror,errno=%d\n",errno);
  27. exit(-1);
  28. }
  29. else
  30. {
  31. //显示取出的消息
  32. printf("%s\n",message.mbuf);
  33. }
  34. return0;
  35. }

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

test3执行结果,代码如下:

  1. [root@server~]#./test3
  2. thisistest3!
  3. firstmessage

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

  1. keymsqidownerpermsused-bytesmessages
  2. 0x000003ea98305root66600
  3. 0x000003eb131074root666131
  4. //test4执行结果:
  5. [root@server~]#./test4
  6. thisistest4!
  7. hellotest4.

以上.

相关广告
  • Linux下消息队列学习笔记 Linux下消息队列学习笔记 Linux下消息队列学习笔记
相关阅读

Linux下消息队列学习笔记

2019/10/10 17:45:58 | 谷歌SEO算法 | 百度K站