1. IPC通信:Posix消息队列
  2.  
  3.  消息队列可以认为是一个链表。进程(线程)可以往里写消息,也可以从里面取出消息。一个进程可以往某个消息队列里写消息,然后终止,另一个进程随时可以从消息队列里取走这些消息。这里也说明了,消息队列具有随内核的持续性,也就是系统不重启,消息队列永久存在。
  4.  
  5. 创建(并打开)、关闭、删除一个消息队列
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <mqueue.h> //头文件
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <unistd.h>
  13. #include <fcntl.h>
  14. #include <errno.h>
  15.  
  16. #define MQ_NAME ("/tmp")
  17. #define MQ_FLAG (O_RDWR | O_CREAT | O_EXCL) // 创建MQ的flag
  18. #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建MQ的权限
  19.  
  20. int main()
  21.  
  22. {
  23. mqd_t posixmq;
  24. int rc = ;
  25.  
  26. /*
  27. 21 函数说明:函数创建或打开一个消息队列
  28. 22 返回值:成功返回消息队列描述符,失败返回-1,错误原因存于errno中
  29. 23 */
  30. posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, NULL);
  31.  
  32. if(- == posixmq)
  33. {
  34. perror("创建MQ失败");
  35. exit();
  36. }
  37.  
  38. /*
  39. 33 函数说明:关闭一个打开的消息队列,表示本进程不再对该消息队列读写
  40. 34 返回值:成功返回0,失败返回-1,错误原因存于errno中
  41. 35 */
  42. rc = mq_close(posixmq);
  43. if( != rc)
  44. {
  45. perror("关闭失败");
  46. exit();
  47. }
  48.  
  49. /*
  50. 44 函数说明:删除一个消息队列,好比删除一个文件,其他进程再也无法访问
  51. 45 返回值:成功返回0,失败返回-1,错误原因存于errno中
  52. 46 */
  53. rc = mq_unlink(MQ_NAME);
  54. if( != rc)
  55. {
  56. perror("删除失败");
  57. exit();
  58. }
  59.  
  60. return ;
  61. }
  62.  
  63. 编译并执行:
  64.  
  65. root@linux:/mnt/hgfs/C_libary# gcc -o crtmq crtmq.c
  66. /tmp/ccZ9cTxo.o: In function `main':
  67. crtmq.c:(.text+0x31): undefined reference to `mq_open'
  68. crtmq.c:(.text+0x60): undefined reference to `mq_close'
  69. crtmq.c:(.text+0x8f): undefined reference to `mq_unlink'
  70. collect2: ld returned exit status
  71. 因为mq_XXX()函数不是标准库函数,链接时需要指定;库-lrt;
  72. root@linux:/mnt/hgfs/C_libary# gcc -o crtmq crtmq.c -lrt
  73.  
  74. root@linux:/mnt/hgfs/C_libary# ./crtmq
  75. 最后程序并没有删除消息队列(消息队列有随内核持续性),如再次执行该程序则会给出错误信息:
  76. root@linux:/mnt/hgfs/C_libary# ./crtmq
  77. 创建MQ失败: File exit()
  78.  
  79. 编译这个程序需要注意几点:
  80.  
  81. 、消息队列的名字最好使用“/”打头,并且只有一个“/”的名字。否则可能出现移植性问题;(还需保证在根目录有写权限,为了方便我在root权限下测试)
  82. 、创建成功的消息队列不一定能看到,使用一些方法也可以看到,本文不做介绍;
  83.  
  84.   消息队列的名字有如此规定,引用《UNIX网络编程 卷2》的相关描述: mq_open,sem_open,shm_open这三个函数的第一个参数是
  85. 一个IPC名字,它可能是某个文件系统中的一个真正存在的路径名,也可能不是。Posix.1是这样描述Posix IPC名字的。
  86. )它必须符合已有的路径名规则(最多由PATH_MAX个字节构成,包括结尾的空字节)
  87. )如果它以斜杠开头,那么对这些函数的不同调用将访问同一个队列,否则效果取决于实现(也就是效果没有标准化)
  88. )名字中的额外的斜杠符的解释由实现定义(同样是没有标准化) 因此,为便于移植起见,Posix IPC名字必须以一个斜杠打头,并且不能再包含任何其他斜杠符。
  89.  
  90. IPC通信:Posix消息队列读,写
  91.  
  92. 创建消息队列的程序:
  93.  
  94. #include <stdio.h>
  95. #include <stdlib.h>
  96. #include <mqueue.h> //头文件
  97. #include <sys/types.h>
  98. #include <sys/stat.h>
  99. #include <unistd.h>
  100. #include <fcntl.h>
  101. #include <errno.h>
  102.  
  103. #define MQ_NAME ("/tmp")
  104. #define MQ_FLAG (O_RDWR | O_CREAT | O_EXCL) // 创建MQ的flag
  105. #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建MQ的权限
  106.  
  107. int main()
  108.  
  109. {
  110. mqd_t posixmq;
  111. int rc = ;
  112.  
  113. /*
  114. 21 函数说明:函数创建或打开一个消息队列
  115. 22 返回值:成功返回消息队列描述符,失败返回-1,错误原因存于errno中
  116. 23 */
  117. posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, NULL);
  118.  
  119. if(- == posixmq)
  120. {
  121. perror("创建MQ失败");
  122. exit();
  123. }
  124.  
  125. /*
  126. 33 函数说明:关闭一个打开的消息队列,表示本进程不再对该消息队列读写
  127. 34 返回值:成功返回0,失败返回-1,错误原因存于errno中
  128. 35 */
  129. rc = mq_close(posixmq);
  130. if( != rc)
  131. {
  132. perror("关闭失败");
  133. exit();
  134. }
  135.  
  136. #if 0
  137. /*
  138. 45 函数说明:删除一个消息队列,好比删除一个文件,其他进程再也无法访问
  139. 46 返回值:成功返回0,失败返回-1,错误原因存于errno中
  140. 47 */
  141. rc = mq_unlink(MQ_NAME);
  142. if( != rc)
  143. {
  144. perror("删除失败");
  145. exit();
  146. }
  147.  
  148. return ;
  149. #endif
  150. }
  151.  
  152. 编译并执行:
  153.  
  154. root@linux:/mnt/hgfs/C_libary# gcc -o crtmq crtmq.c -lrt
  155. root@linux:/mnt/hgfs/C_libary# ./crtmq
  156. 程序并没有删除消息队列(消息队列有随内核持续性),如再次执行该程序则会给出错误信息:
  157. root@linux:/mnt/hgfs/C_libary# ./crtmq
  158. 创建MQ失败: File exit()
  159. 向消息队列写消息的程序:
  160.  
  161. 消息队列的读写主要使用下面两个函数:
  162. /*头文件*/
  163. #include <mqueue.h>
  164.  
  165. /*返回:若成功则为消息中字节数,若出错则为-1 */
  166. int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);
  167.  
  168. /*返回:若成功则为0, 若出错则为-1*/
  169. ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);
  170.  
  171. /*消息队列属性结构体*/
  172. struct mq_attr {
  173. long mq_flags; /* Flags: 0 or O_NONBLOCK */
  174. long mq_maxmsg; /* Max. # of messages on queue */
  175. long mq_msgsize; /* Max. message size (bytes) */
  176. long mq_curmsgs; /* # of messages currently in queue */
  177. };
  178.  
  179. #include <stdio.h>
  180. #include <stdlib.h>
  181. #include <mqueue.h>
  182. #include <sys/types.h>
  183. #include <sys/stat.h>
  184. #include <unistd.h>
  185. #include <fcntl.h>
  186. #include <errno.h>
  187.  
  188. /*向消息队列发送消息,消息队列名及发送的信息通过参数传递*/
  189. int main(int argc, char *argv[])
  190. {
  191. mqd_t mqd;
  192. char *ptr;
  193. size_t len;
  194. unsigned int prio;
  195. int rc;
  196.  
  197. if(argc != )
  198. {
  199. printf("Usage: sendmq <name> <bytes> <priority>\n");
  200. exit();
  201. }
  202.  
  203. len = atoi(argv[]);
  204. prio = atoi(argv[]);
  205.  
  206. //只写模式找开消息队列
  207. mqd = mq_open(argv[], O_WRONLY);
  208. if(- == mqd)
  209. {
  210. perror("打开消息队列失败");
  211. exit();
  212. }
  213.  
  214. // 动态申请一块内存
  215. ptr = (char *) calloc(len, sizeof(char));
  216. if(NULL == ptr)
  217. {
  218. perror("申请内存失败");
  219. mq_close(mqd);
  220. exit();
  221. }
  222.  
  223. /*向消息队列写入消息,如消息队列满则阻塞,直到消息队列有空闲时再写入*/
  224. rc = mq_send(mqd, ptr, len, prio);
  225. if(rc < )
  226. {
  227. perror("写入消息队列失败");
  228. mq_close(mqd);
  229. exit();
  230. }
  231.  
  232. // 释放内存
  233. free(ptr);
  234. return ;
  235. }
  236.  
  237. 编译并执行:
  238.  
  239. root@linux:/mnt/hgfs/C_libary# gcc -o sendmq sendmq.c -lrt
  240. root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp
  241. root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp
  242. root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp
  243. root@linux:/mnt/hgfs/C_libary# ./sendmq /tmp
  244.   上面先后向消息队列“/tmp”写入了四条消息,因为先前创建的消息队列只允许存放3条消息,本次第四次写入时程序会阻塞。直到有另外进程从消息队列取走消息后本次写入才成功返回。
  245.  
  246. 读消息队列:
  247.  
  248. #include <stdio.h>
  249. #include <stdlib.h>
  250. #include <mqueue.h>
  251. #include <sys/types.h>
  252. #include <sys/stat.h>
  253. #include <unistd.h>
  254. #include <fcntl.h>
  255. #include <errno.h>
  256.  
  257. /*读取某消息队列,消息队列名通过参数传递*/
  258. int main(int argc, char *argv[])
  259. {
  260. mqd_t mqd;
  261. struct mq_attr attr;
  262. char *ptr;
  263. unsigned int prio;
  264. size_t n;
  265. int rc;
  266.  
  267. if(argc != )
  268. {
  269. printf("Usage: readmq <name>\n");
  270. exit();
  271. }
  272.  
  273. /*只读模式打开消息队列*/
  274. mqd = mq_open(argv[], O_RDONLY);
  275. if(mqd < )
  276. {
  277. perror("打开消息队列失败");
  278. exit();
  279. }
  280.  
  281. // 取得消息队列属性,根据mq_msgsize动态申请内存
  282. rc = mq_getattr(mqd, &attr);
  283. if(rc < )
  284. {
  285. perror("取得消息队列属性失败");
  286. exit();
  287. }
  288.  
  289. /*动态申请保证能存放单条消息的内存*/
  290. ptr = calloc(attr.mq_msgsize, sizeof(char));
  291. if(NULL == ptr)
  292. {
  293. printf("动态申请内存失败\n");
  294. mq_close(mqd);
  295. exit();
  296. }
  297.  
  298. /*接收一条消息*/
  299. n = mq_receive(mqd, ptr, attr.mq_msgsize, &prio);
  300. if(n < )
  301. {
  302. perror("读取失败");
  303. mq_close(mqd);
  304. free(ptr);
  305. exit();
  306. }
  307.  
  308. printf("读取 %ld 字节\n 优先级为 %u\n", (long)n, prio);
  309. return ;
  310. }
  311.  
  312. 编译并执行:
  313.  
  314. root@linux:/mnt/hgfs/C_libary# vi readmq.c
  315. root@linux:/mnt/hgfs/C_libary# vi readmq.c
  316. root@linux:/mnt/hgfs/C_libary# gcc -o readmq readmq.c -lrt
  317. root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
  318. 读取 字节
  319. 优先级为
  320. root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
  321. 读取 字节
  322. 优先级为
  323. root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
  324. 读取 字节
  325. 优先级为
  326. root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
  327. 读取 字节
  328. 优先级为
  329. root@linux:/mnt/hgfs/C_libary# ./readmq /tmp
  330.  
  331.   程序执行五次,第一次执行完,先前阻塞在写处的程序成功返回。第五次执行,因为消息队列已经为空,程序阻塞。直到另外的进程向消息队列写入一条消息。另外,还可以看出Posix消息队列每次读出的都是消息队列中优先级最高的消息。
  332.  
  333. IPC通信:Posix消息队列的属性设置
  334.  
  335. Posix消息队列的属性使用如下结构存放:
  336. struct mq_attr
  337. {
  338. long mq_flags; /*阻塞标志位,0为非阻塞(O_NONBLOCK)*/
  339. long mq_maxmsg; /*队列所允许的最大消息条数*/
  340. long mq_msgsize; /*每条消息的最大字节数*/
  341. long mq_curmsgs; /*队列当前的消息条数*/
  342. };
  343. 队列可以在创建时由mq_open()函数的第四个参数指定mq_maxmsg,mq_msgsize。 如创建时没有指定则使用默认值,一旦创建,则不可再改变。
  344. 队列可以在创建后由mq_setattr()函数设置mq_flags
  345.  
  346. #include <mqueue.h>
  347.  
  348. /*取得消息队列属性,放到mqstat地fh*/
  349. int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat);
  350.  
  351. /*设置消息队列属性,设置值由mqstat提供,原先值写入omqstat*/
  352. int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat);
  353.  
  354. 均返回:若成功则为0,若出错为-
  355.  
  356. 程序获取和设置消息队列的默认属性:
  357. #include <stdio.h>
  358. #include <stdlib.h>
  359. #include <mqueue.h>
  360. #include <sys/types.h>
  361. #include <sys/stat.h>
  362. #include <unistd.h>
  363. #include <fcntl.h>
  364. #include <errno.h>
  365.  
  366. #define MQ_NAME ("/tmp")
  367. #define MQ_FLAG (O_RDWR | O_CREAT | O_EXCL) // 创建MQ的flag
  368. #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建MQ的权限
  369.  
  370. int main()
  371. {
  372. mqd_t posixmq;
  373. int rc = ;
  374.  
  375. struct mq_attr mqattr;
  376.  
  377. // 创建默认属性的消息队列
  378. posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, NULL);
  379. if(- == posixmq)
  380. {
  381. perror("创建MQ失败");
  382. exit();
  383. }
  384.  
  385. // 获取消息队列的默认属性
  386. rc = mq_getattr(posixmq, &mqattr);
  387. if(- == rc)
  388. {
  389. perror("获取消息队列属性失败");
  390. exit();
  391. }
  392.  
  393. printf("队列阻塞标志位:%ld\n", mqattr.mq_flags);
  394. printf("队列允许最大消息数:%ld\n", mqattr.mq_maxmsg);
  395. printf("队列消息最大字节数:%ld\n", mqattr.mq_msgsize);
  396. printf("队列当前消息条数:%ld\n", mqattr.mq_curmsgs);
  397.  
  398. rc = mq_close(posixmq);
  399. if( != rc)
  400. {
  401. perror("关闭失败");
  402. exit();
  403. }
  404.  
  405. rc = mq_unlink(MQ_NAME);
  406. if( != rc)
  407. {
  408. perror("删除失败");
  409. exit();
  410. }
  411. return ;
  412. }
  413.  
  414. 编译并执行:
  415. root@linux:/mnt/hgfs/C_libary# gcc -o attrmq attrmq.c -lrt
  416. root@linux:/mnt/hgfs/C_libary# ./attrmq
  417. 队列阻塞标志位:
  418. 队列允许最大消息数:
  419. 队列消息最大字节数:
  420. 队列当前消息条数:
  421. root@linux:/mnt/hgfs/C_libary#
  422.  
  423. 设置消息队列的属性:
  424.  
  425. #include <stdio.h>
  426. #include <stdlib.h>
  427. #include <mqueue.h>
  428. #include <sys/types.h>
  429. #include <sys/stat.h>
  430. #include <unistd.h>
  431. #include <fcntl.h>
  432. #include <errno.h>
  433.  
  434. #define MQ_NAME ("/tmp")
  435. #define MQ_FLAG (O_RDWR | O_CREAT | O_EXCL) // 创建MQ的flag
  436. #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建MQ的权限
  437.  
  438. int main()
  439. {
  440. mqd_t posixmq;
  441. int rc = ;
  442.  
  443. struct mq_attr mqattr;
  444.  
  445. // 创建默认属性的消息队列
  446. mqattr.mq_maxmsg = ; // 注意不能超过系统最大限制
  447. mqattr.mq_msgsize = ;
  448. //posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, NULL);
  449. posixmq = mq_open(MQ_NAME, MQ_FLAG, FILE_MODE, &mqattr);
  450.  
  451. if(- == posixmq)
  452. {
  453. perror("创建MQ失败");
  454. exit();
  455. }
  456.  
  457. mqattr.mq_flags = ;
  458. mq_setattr(posixmq, &mqattr, NULL);// mq_setattr()只关注mq_flags,adw
  459.  
  460. // 获取消息队列的属性
  461. rc = mq_getattr(posixmq, &mqattr);
  462. if(- == rc)
  463. {
  464. perror("获取消息队列属性失败");
  465. exit();
  466. }
  467.  
  468. printf("队列阻塞标志位:%ld\n", mqattr.mq_flags);
  469. printf("队列允许最大消息数:%ld\n", mqattr.mq_maxmsg);
  470. printf("队列消息最大字节数:%ld\n", mqattr.mq_msgsize);
  471. printf("队列当前消息条数:%ld\n", mqattr.mq_curmsgs);
  472.  
  473. rc = mq_close(posixmq);
  474. if( != rc)
  475. {
  476. perror("关闭失败");
  477. exit();
  478. }
  479.  
  480. rc = mq_unlink(MQ_NAME);
  481. if( != rc)
  482. {
  483. perror("删除失败");
  484. exit();
  485. }
  486.  
  487. return ;
  488. }
  489. 复制代码
  490. 编译运行:
  491.  
  492. 复制代码
  493. root@linux:/mnt/hgfs/C_libary# gcc -o setattrmq setattrmq.c -lrt
  494. root@linux:/mnt/hgfs/C_libary# ./setattrmq
  495. 队列阻塞标志位:
  496. 队列允许最大消息数:
  497. 队列消息最大字节数:
  498. 队列当前消息条数:
  499. 本文转自:http://blog.csdn.net/liuhongxiangm/article/details/8716232

IPC通信:Posix消息队列的更多相关文章

  1. Unix IPC之Posix消息队列(1)

    部分参考:http://www.cnblogs.com/Anker/archive/2013/01/04/2843832.html IPC对象的持续性:http://book.51cto.com/ar ...

  2. Unix IPC之Posix消息队列(3)

    struct mq_attr { long mq_flags; /* message queue flag : 0, O_NONBLOCK */ long mq_maxmsg; /* max numb ...

  3. Unix IPC之Posix消息队列(2)

    /* Query status and attributes of message queue MQDES. */ extern int mq_getattr (mqd_t __mqdes, stru ...

  4. Linux IPC POSIX 消息队列

    模型: #include<mqueue.h> #include <sys/stat.h> #include <fcntl.h> mq_open() //创建/获取消 ...

  5. Linux IPC实践(7) --Posix消息队列

    1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For m ...

  6. UNIX IPC: POSIX 消息队列 与 信号

    POSIX消息队列可以注册空队列有消息到达时所触发的信号,而信号触发对应的信号处理函数. 下面是一份基本的消息队列和信号处理结合的代码(修改自UNIX网络编程:进程间通信) #include < ...

  7. UNIX IPC: POSIX 消息队列

    首先在我的MAC OSX上试了一下虽然有_POSIX_MESSAGE_PASSING的宏定义,但是用gcc编译会提示没有mqueue.h头文件,先放一边.在Ubuntu上使用正常,不过POSIX消息队 ...

  8. [转]Linux进程通信之POSIX消息队列

    进程间的消息队列可以用这个实现,学习了下. http://blog.csdn.net/anonymalias/article/details/9799645?utm_source=tuicool&am ...

  9. Linux进程间通信(IPC)编程实践(十二)Posix消息队列--基本API的使用

    posix消息队列与system v消息队列的区别: (1)对posix消息队列的读总是返回最高优先级的最早消息,对system v消息队列的读则能够返回随意指定优先级的消息. (2)当往一个空队列放 ...

随机推荐

  1. request.getcontextPath() 详解(转)

    本文转自:http://blog.csdn.net/pengxuan/article/details/6604578 <%=request.getContextPath()%>是为了解决相 ...

  2. Java虚拟机学习 - 对象引用强度 ( 8 )

    无论是通过计数算法判断对象的引用数量,还是通过根搜索算法判断对象引用链是否可达,判定对象是否存活都与“引用”相关. 引用主要分为 :强引用(Strong Reference).软引用(Soft Ref ...

  3. Android开发学习之Gallery和GridView浅析

    一.Gallery的简介 Gallery(画廊)是一个锁定中心条目并且拥有水平滚动列表的视图,一般用来浏览图片,并且可以响应事件显示信息.Gallery还可以和ImageSwitcher组件结合使用来 ...

  4. AspxPivotGrid和WebChartControl数据联动处理日志

    AspxPivotGrid具有很好的表格样式体验,WebChartControl也是个很内容丰富的做图控件,我希望实现的功能是这样的, 处理题库统计分析图表,用户点AspxPivotGrid绑定知识点 ...

  5. AME_Oracle自带AME审批链详解AME Standard Handler(概念)

    2014-05-30 Created By BaoXinJian Oracle 自带了3大类,13个子类的审批链Action Type, 对应了13个标准的AME Standard Handler

  6. Python监控Windows下的文件变化

    windows下监控文件系统的变化.用python非常方便.实例代码例如以下,非常easy.也不多说了. import os import win32file import win32con ACTI ...

  7. MFC改变对话框背景颜色

    原文链接: http://blog.sina.com.cn/s/blog_59955afc0100spjz.html 方法一:调用CWinApp类的成员函数SetDialogBkColor来实现. - ...

  8. C# 动态获取代码所在行号

    通过System.Diagnostics.StackTrace获取代码所在行号和文件信息 获取行号信息 /// <summary> /// Get line number of code ...

  9. python bs4 + requests4 简单爬虫

    参考链接: bs4和requests的使用:https://www.cnblogs.com/baojinjin/p/6819389.html 安装pip:https://blog.csdn.net/z ...

  10. python标准库介绍——6 math模块详解

    ==math 模块== ``math`` 模块实现了许多对浮点数的数学运算函数. 这些函数一般是对平台 C 库中同名函数的简单封装, 所以一般情况下, 不同平台下计算的结果可能稍微地有所不同, 有时候 ...