linux c编程:Posix消息队列
Posix消息队列可以认为是一个消息链表. 有足够写权限的线程可以往队列中放置消息, 有足够读权限的线程可以从队列中取走消息
在某个进程往一个队列写入消息前, 并不需要另外某个进程在该队列上等待消息的到达.
这跟管道和FIFO是相反的, 因为对于管道,FIFO来说, 除非读出者已经存在, 光有写入者是没有意义的。一个进程在往某消息队列写入消息后, 终止进程. 另一个进程某时刻读出该消息;然而对于管带或FIFO而言, 当管道或FIFO的最后一次关闭发生时,仍在管道或FIFO中的数据将被抛弃
消息队列的布局如下图
下面介绍队列用到函数:
1 mqd_t mq_open(const char* name, int oflag, mode_t mode, struct mq_attr* attr);
函数打开或者创建一个posix消息队列。当我们的实际操作是创建一个新的队列时(即所要创建的队列不存在, 且oflag中已经指定O_CREAT), mode 和 attr参数是需要的.
函数的返回值称为消息队列描述符, 这个值用作其他消息队列操作函数的第一个参数值。另外根据man 7 mq_overview里面的介绍。在链接的时候必须链接librt库,采用-lrt的方法
如果没有链接的话,会出现下面的错误
root@zhf-maple:/home/zhf/codeblocks_prj/unix_network# gcc -c main.c -o main_tmp
root@zhf-maple:/home/zhf/codeblocks_prj/unix_network# ./main_tmp test2
bash: ./main_tmp: 无法执行二进制文件: 可执行文件格式错误
name:
posix IPC名字。(必须以/开头,且后面不能再含有/)
oflag:
标志。
标志——————————作用
O_CREAT———————没有该对象则创建
O_EXCL————————如果O_CREAT指定,但name不存在,就返回错误
O_NONBLOCK—————以非阻塞方式打开消息队列
O_RDONLY———————只读
O_RDWR————————读写
O_WRONLY———————只写
mode:
权限——————作用
S_IWUSR——用户/属主写
S_IRUSR——用户/属主读
S_IWGRP——组成员写
S_IRGRP——组成员读
S_IWOTH——其他用户写
S_IROTH——其他用户读
attr:结构体如下:
struct mq_attr {
long mq_flags; /* Flags: 0 or O_NONBLOCK */
————在mq_open创建时被初始化;
————在mq_setattr中设置;
————其值为0(阻塞)或者O_NONBLOCK(非阻塞)。
long mq_maxmsg; /* Max. # of messages on queue */
——队列的消息个数最大值:
————只能在mq_open创建时被初始化。
long mq_msgsize; /* Max. message size (bytes) */
——队列中每个消息的最大值:
————只能在mq_open创建时被初始化。
long mq_curmsgs; /* # of messages currently in queue */
——当前队列的消息个数:
————在mq_getattr中获得。
};
2 int mq_close(mqd_t mqdes):关闭消息队列
关闭之后调用进程不在使用该描述符,但消息队列不会从系统中删除,进程终止时,会自动关闭已打开的消息队列,和调用mq_close一样。参数为mq_open()函数返回的值
3 int mq_unlink(const char *name): 从系统中删除某个消息队列
删除会马上发生,即使该队列的描述符引用计数仍然大于0。参数为mq_open()函数第一个参数。
4设置和获取队列属性
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
参数mqdes为mq_open()函数返回的消息队列描述符。
参数attr、newattr、oldattr为消息队列属性结构体指针;
5向消息队列放置和取走消息
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);
参数msg_ptr为指向消息的指针。
msg_len为消息长度,该值不能大于属性值中mq_msgsize的值。
msg_prio为优先级,消息在队列中将按照优先级大小顺序来排列消息。
如果消息队列已满,mq_send()函数将阻塞,直到队列有可用空间再次允许放置消息或该调用被信号打断;如果O_NONBLOCK被指定,mq_send()那么将不会阻塞,而是返回EAGAIN错误。如果队列空,mq_receive()函数将阻塞,直到消息队列中有新的消息;如果O_NONBLOCK被指定,mq_receive()那么将不会阻塞,而是返回EAGAIN错误。
下面就来看第一个例子:
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <mqueue.h>
#include <fcntl.h>
#include "func.h"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(int argc,char **argv)
{
int c,flags;
mqd_t mqd;
struct mq_attr attr;
flags = O_RDWR|O_CREAT;
printf("create mqueue.\n");
if((mqd = mq_open(argv[1],flags,FILE_MODE,NULL)) == -1)
{
perror("mq_open() error");
exit(-1);
}
mq_getattr(mqd,&attr);
printf("max #msgs = %ld,max #bytes/msg = %ld,#currently on queue = %ld\n",attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
mq_close(mqd);
exit(0);
}
在执行代码前,首先要创建消息队列存放的路径。一般是/dev/mqueue。没有的话需要创建一个。然后执行mount -t mqueue none /dev/mqueue进行挂载。参考说明如下
gcc main.c -o main_tmp -lrt
./main_tmp /test123
执行完后,在dev/mqueue路径下面就能看到创建的队列文件以及队列里面的信息。
cat /dev/mqueue/test123
QSIZE:0 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
linux c编程:Posix消息队列的更多相关文章
- Linux 进程间通信(posix消息队列 简单)实例
Linux 进程间通信(posix消息队列 简单)实例 详情见: http://www.linuxidc.com/Linux/2011-10/44828.htm 编译: gcc -o consumer ...
- POSIX 消息队列 和 系列函数
一.在前面介绍了system v 消息队列的相关知识,现在来稍微看看posix 消息队列. posix消息队列的一个可能实现如下图: 其实消息队列就是一个可以让进程间交换数据的场所,而两个标准的消息队 ...
- Linux进程间通信(IPC)编程实践(十二)Posix消息队列--基本API的使用
posix消息队列与system v消息队列的区别: (1)对posix消息队列的读总是返回最高优先级的最早消息,对system v消息队列的读则能够返回随意指定优先级的消息. (2)当往一个空队列放 ...
- [转]Linux进程通信之POSIX消息队列
进程间的消息队列可以用这个实现,学习了下. http://blog.csdn.net/anonymalias/article/details/9799645?utm_source=tuicool&am ...
- Linux IPC实践(7) --Posix消息队列
1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For m ...
- Linux IPC POSIX 消息队列
模型: #include<mqueue.h> #include <sys/stat.h> #include <fcntl.h> mq_open() //创建/获取消 ...
- Linux环境编程之IPC进程间通信(五):Posix消息队列1
对于管道和FIFO来说.必须应该先有读取者存在.否则先有写入者是没有意义的. 而消息队列则不同,它是一个消息链表,有足够写权限的线程可往别的队列中放置消息,有足够读权限的线程可从队列中取走消息.每一个 ...
- linux网络编程之posix消息队列
在前面已经学习了System v相关的IPC,今天起学习posix相关的IPC,关于这两者的内容区别,简单回顾一下: 而今天先学习posix的消息队列,下面开始: 接下来则编写程序来创建一个posix ...
- 进程间通信--POSIX消息队列
相关函数: mqd_t mq_open(const char *name, int oflag); mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, si ...
随机推荐
- EffectiveJava(4)通过私有构造器强化不可实例化的能力
通过私有构造器强化不可实例化的能力 原理:只有当类不包含显式的构造器时,编译器才会生成缺省的构造器,因此只要让这个类包含私有构造器,他就不能被实例化 这种方式下,子类没有可访问的超类构造器可调用 // ...
- Node.js 使用jQuery取得Nodejs http服务端返回的JSON数组示例
server.js代码: // 内置http模块,提供了http服务器和客户端功能(path模块也是内置模块,而mime是附加模块) var http=require("http" ...
- Java 实例
Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 Java 实例 – 如何编译一个Java 文件? Java 实 ...
- Laravel之哈希/常用函数/分页
一.哈希 1.简介Laravel Hash 门面为存储用户密码提供了安全的Bcrypt 哈希算法.如果你正在使用Laravel 应用自带的AuthController 控制器,将会自动为注册和认证使用 ...
- Oracle 导入导出数据库
imp userid=yrsuser/yrsuser2587 fromuser=yrsuser touser=yrsuser file=E:\yrs.dmp exp userid=yrsuser/yr ...
- linux watch命令
watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行.在Linux下,watch是周期性的执行下个 ...
- 1.5.2 WHERE子句
1.5.2 WHERE子句正在更新内容,请稍后
- Java 多线程 并发编程 (转)
一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进程的地址空间是互相隔离的:进程拥有各种 ...
- asp.net repeater Container.ItemIndex
<asp:Repeater ID="myRepeater" runat="server"> <HeaderTemplate> <t ...
- 使用Firebug进行断点调试详解
利用Firebug我们可以非常方便地对网页上的任何JavaScript代码进行断点调试. 首先,使用快捷键F12在当前页面打开Firebug,并切换到脚本选项卡. 其次,我们需要为指定的js代码添加断 ...