linux IPC 消息队列
消息队列函数原型
在建立IPC通讯时(如消息队列,共享内存)必须建立一个ID值。通常情况下,这个ID值由ftok函数得到
#inlcude <sys/types.h>
#include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id);
返回值:成功返回键值,失败-1。
pathname:现有文件路径
proj_id:低8位整型
假如要确保key_t值不变,要目确保ftok的文档不被删除 ,要么不用ftok,指定一个固定的key_t值。
在linux下通过ftok()产生ipc键值、且ftok()与配置文件相关,则在更改了配置文件后必须将应用重起。否则将导致不可预料的后果!
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h> int main()
{
printf("key=%0x\n", ftok("aaa.txt", ));
return ;
}
ftok
打开一个现有队列或创建一个新队列:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> int msgget(key_t key, int msgflg);
返回值:成功消息队列ID,失败-1
key:函数ftok返回值或IPC_PRIVATE(适合用在有亲缘关系的进程中)
msgflg: 消息队列的简历标志和存取权限
IPC_CREAT如果内核中没有此队列,则创建它。
IPC_EXCL当和IPC_CREAT一起使用时,如果队列已经存在,则失败。
如果单独使用IPC_CREAT,则msgget()要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。如果IPC_EXCL和IPC_CREAT一起使用,则msgget()要么创建一个新的消息队列,要么如果队列已经存在则返回一个失败值-。IPC_EXCL单独使用是没有用处的。 返回说明:
成功执行时,返回消息队列标识值。失败返回-,errno被设为以下的某个值 ,有时也会返回0,这个时候也是可以正常使用的
EACCES:指定的消息队列已存在,但调用进程没有权限访问它,而且不拥有CAP_IPC_OWNER权能
EEXIST:key指定的消息队列已存在,而msgflg中同时指定IPC_CREAT和IPC_EXCL标志
ENOENT:key指定的消息队列不存在同时msgflg中不指定IPC_CREAT标志
ENOMEM:需要建立消息队列,但内存不足
ENOSPC:需要建立消息队列,但已达到系统的最大消息队列容量
msgflg参数
对队列执行多种操作。他和另外两个与信号量及共享存储有关的函数(semctl和shmctl)都是类似于ioctl的函数(亦即垃圾桶函数)。
#include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf);
返回值:成功:0,失败-1
msqid:消息队列对象的标识符
cmd:消息队列进行操作
IPC_STAT:取此队列的msqid_ds结构,并将它存放在buf中
IPC_SET:将字段msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_bytes从buf指向的结构复制到,与这个队列相关的msqid_ds结构中。
此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cuid或msg_perm.uid,另一种是具有超级用户特权的进程。
只有超级用户才能增加msg_qbytes的值。
IPC_EMID:从系统中删除该消息队列以及仍在该队列中的所有数据。这种删除立即生效。仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作时,将得到错误。
此命令只能由下列两种进程执行:一种是其有效用户ID等于msg_perm.cui或msg_perm.uid;另一种是具有超级用户特权的进程。
buf:缓存msqid_ds结构
struct msqid_ds {
struct ipc_perm msg_perm; /* Ownership and permissions */
time_t msg_stime; /* Time of last msgsnd(2) */
time_t msg_rtime; /* Time of last msgrcv(2) */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes in
queue (nonstandard) */
msgqnum_t msg_qnum; /* Current number of messages
in queue */
msglen_t msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t msg_lspid; /* PID of last msgsnd(2) */
pid_t msg_lrpid; /* PID of last msgrcv(2) */
};
struct msqid_ds
其中又有ipc_perm结构:
struct ipc_perm {
key_t __key; /* Key supplied to msgget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
struct ipc_perm
调用msgsnd将数据放到消息队列中
#include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
返回值:成功0,失败-1
msqid:消息队列识别码
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收消息,是用户定义的通用结构。
msgsz:消息的大小
msgflg: 0当消息队列满时,msgsnd会阻塞,直到消息能写进队列
IPC_NOWAIT当消息队列已满时,msgsnd函数不等待立即返回
IPC_NOERROR若发送的消息大于size字节,则把消息截断,截断部分将丢弃,且不通知发送进程
msgp结构为:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[]; /* message data */
};
struct msgbuf
msgrcv从队列中取用消息
#include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
返回值:成功返回消息数据部分的长度,出错-
msqid:消息队列识别码
msgp:消息结构体,和msgsnd一样
msgsz:接收消息的大小
msgtyp: 0接收第一个消息
>0接收类型等于msgtyp的第一个消息
<0接收类型等于或小于msgtyp绝对值的第一个消息
msgflg: 0阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待
IPC_NOWAIT如果没有返回条件的消息调用立即返回
IPC_EXCEPT与msgtype配合使用返回队列中第一个类型不为msgtype的消息
IPC_NOERROR如果队列中满足条件的消息内容大于所请求的size字节,则把消息截断并丢弃截断部分
消息队列使用的例子:
#include <stdio.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h> #define TEXT_SIZE 512 struct msgbuf {
long mtype;
char mtext[TEXT_SIZE];
}; int main(int argc, char *argv[])
{
int msqid;
pid_t pid;
struct msgbuf msg; msqid = msgget(IPC_PRIVATE, IPC_CREAT|);
if(msqid == -)
{
printf("create msg queue failed!\n");
return -;
} pid = fork();
if(pid < ) {
printf("fork failed!\n");
return -;
} else if(pid == ) { /* child */
msgrcv(msqid, &msg, sizeof(msg), , IPC_NOWAIT);
printf("child: msg.mtext is %s\n", msg.mtext);
strcpy(msg.mtext, "Hello, too!");
msgsnd(msqid, &msg, sizeof(msg), IPC_NOWAIT);
} else { /* parent */
msg.mtype = ;
strcpy(msg.mtext, "Hello!");
msgsnd(msqid, &msg, sizeof(msg), IPC_NOWAIT);
sleep();
msgrcv(msqid, &msg, sizeof(msg), , IPC_NOWAIT);
printf("parent:msg.mtext is %s\n", msg.mtext);
}
return ;
}
linux IPC 消息队列的更多相关文章
- linux IPC 消息队列(二)
我在网上想找多进程之间的通信方式,发现有人写的消息队列很好,搬过来: common.h #ifndef __COMMON_H_ #define __COMMON_H_ #include <std ...
- IPC——消息队列
Linux进程间通信——使用消息队列 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管 ...
- 详解linux进程间通信-消息队列
前言:前面讨论了信号.管道的进程间通信方式,接下来将讨论消息队列. 一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构 ...
- Linux进程间通信—消息队列
四.消息队列(Message Queue) 消息队列就是消息的一个链表,它允许一个或者多个进程向它写消息,一个或多个进程向它读消息.Linux维护了一个消息队列向量表:msgque,来表示系统中所有的 ...
- linux进程间通信-消息队列
一 消息队列的介绍 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构. 我们可以通过发送消息来避免命名管道的 ...
- Linux进程间通信-消息队列(mqueue)
前面两篇文章分解介绍了匿名管道和命名管道方式的进程间通信,本文将介绍Linux消息队列(posix)的通信机制和特点. 1.消息队列 消息队列的实现分为两种,一种为System V的消息队列,一种是P ...
- linux 下消息队列发送后没有信息
在使用消息队列时,调用 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
- linux中消息队列<一>
1 概念 (1)链表式结构组织,存放于内核. (2)通过队列标识来引用. (3)通过一个消息类型来索引指定的数据 2 创建消息队列 #include <sys/msg.h> int msg ...
- linux进程间通信消息队列:msgsnd: Invalid argument
今天写了个消息队列的小测试程序结果send端程序总是出现:msgsnd: Invalid argument,搞了半个小时也没搞明白,后来查资料发现我将(st_msg_buf.msg_type = 0; ...
随机推荐
- 轻松解决U盘拷贝文件时提示文件过大问题
现在的高科技时代生活中,u盘的使用已经是许多从事电脑it行业的人每天都必须要用到的用具.可以在一台电脑上使用u盘拷贝文件到另外一台电脑上进行使用,加上它的身材小巧,非常方便我们随身携带到任何地方进行使 ...
- centos6 sersync2使用
接收端rsyncd搭建 http://www.cnblogs.com/hanxiaohui/p/8675409.html 推送端sersync2使用 安装 源码包D:\share\src\sersyn ...
- echarts绘制饼图时的一点特殊设置
最后的效果如图,需要在中间展示的部分换行然后字体大小不同. 以下为option的设置,使用rich里面的参数来设置更多的文本样式,使用‘\n’来控制换行 let option = { color: c ...
- display和visibility
display: none; visibility: hidden; 相同点:两者都是隐藏元素不同点:display不保留位置,visibility保留位置
- (55)C# windows 消息
窗体捕获消息 namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeC ...
- 创建线程方法&守护线程
创建线程方法1. class mythread extends Thread{ 重写run方法 } mythread m=new mythread () 启动:m.start() 创建线程方法2. c ...
- 跨站请求伪造(CSRF)与跨域问题
1.CSRF定义 伪装来自受信任用户的请求来访问受信任的网站,(攻击者盗用了你的身份,以你的名义发送恶意请求) 产生条件 1.用户要登录受信任的网站,并在本地生成cookie 2.在不退出安全网站的情 ...
- flex属性flex-grow、flex-shrink、flex-basis
tip: 1)这些属性写在子元素中,作用于子元素(父元素中应设置display:flex) 2)作用是子元素如何分配父元素的空间 3) flex-grow 是扩展比率,当子元素宽度总和小于父元素宽度时 ...
- 一道面试题:js返回函数, 函数名后带多个括号的用法及join()的注意事项
博客搬迁,给你带来的不便,敬请谅解! http://www.suanliutudousi.com/2017/11/13/js%E8%BF%94%E5%9B%9E%E5%87%BD%E6%95%B0%E ...
- 【模板】fread读入优化 & fwrite输出优化
#include <iostream> #include <cstdio> #include <cctype> #define SIZE (1 << 2 ...