消息队列函数原型

在建立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 消息队列的更多相关文章

  1. linux IPC 消息队列(二)

    我在网上想找多进程之间的通信方式,发现有人写的消息队列很好,搬过来: common.h #ifndef __COMMON_H_ #define __COMMON_H_ #include <std ...

  2. IPC——消息队列

    Linux进程间通信——使用消息队列 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管 ...

  3. 详解linux进程间通信-消息队列

    前言:前面讨论了信号.管道的进程间通信方式,接下来将讨论消息队列. 一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构 ...

  4. Linux进程间通信—消息队列

    四.消息队列(Message Queue) 消息队列就是消息的一个链表,它允许一个或者多个进程向它写消息,一个或多个进程向它读消息.Linux维护了一个消息队列向量表:msgque,来表示系统中所有的 ...

  5. linux进程间通信-消息队列

    一 消息队列的介绍 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构. 我们可以通过发送消息来避免命名管道的 ...

  6. Linux进程间通信-消息队列(mqueue)

    前面两篇文章分解介绍了匿名管道和命名管道方式的进程间通信,本文将介绍Linux消息队列(posix)的通信机制和特点. 1.消息队列 消息队列的实现分为两种,一种为System V的消息队列,一种是P ...

  7. linux 下消息队列发送后没有信息

    在使用消息队列时,调用 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  8. linux中消息队列<一>

    1 概念 (1)链表式结构组织,存放于内核. (2)通过队列标识来引用. (3)通过一个消息类型来索引指定的数据 2 创建消息队列 #include <sys/msg.h> int msg ...

  9. linux进程间通信消息队列:msgsnd: Invalid argument

    今天写了个消息队列的小测试程序结果send端程序总是出现:msgsnd: Invalid argument,搞了半个小时也没搞明白,后来查资料发现我将(st_msg_buf.msg_type = 0; ...

随机推荐

  1. flume源码

    IDEA查看源码 IDEA快捷键 1 查看接口的实现类:Ctrl+Alt+B 选中按快捷键,然后跳到实现类的地方去 2 切换页面:Alt+<- 和 Alt+-> Alt+-> 3 查 ...

  2. shell 以指定字符拆分字符串

    string="hell|ttt|sss|2222" OLD_IFS="$IFS" IFS="|" array=($string) IFS= ...

  3. Linux文本处理三剑客之——grep

    一Linux文本处理三剑客之——grep Linux文本处理三剑客都支持正则表达式 grep :文本过滤( 模式:pattern) 工具,包括grep, egrep, fgrep (不支持正则表达式) ...

  4. Nacos 1.1.4 发布,业界率先支持 Istio MCP 协议

    Nacos是阿里巴巴开源的服务发现与配置管理项目,本次发布的1.1.4版本,主要带来的是与Istio的对接功能,使用的是Istio最新的MCP协议.本文将介绍包括这个功能在内的新版本发布的功能. 升级 ...

  5. I2C自编设备驱动设计

    一.自编设备驱动模型 at24.c: static int __init at24_init(void) { io_limit = rounddown_pow_of_two(io_limit); re ...

  6. POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)

    In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...

  7. 《NULL-2019团队》第一次作业:OUC二手交易平台

    前言 项目名称:OUC二手交易平台 项目简介:针对在校大学生的二手交易平台,相对于现在市面已有的二手APP,将其使用的普遍性范围缩小,针对在校大学生,这样可以有效的保证交易的真实性和公平性.   NA ...

  8. 原来... 用debug如何查看当前标志寄存器的标志位值?

    -r 用这个指令,得到的信息右下角: NV   UP   EI   PL   NZ   NA   PO   NC这些符号代表的就是标志寄存器里常用标志位的值. 这个是符号值对应表: 溢出标志OF(Ov ...

  9. HTML-参考手册: HTML 全局属性

    ylbtech-HTML-参考手册: HTML 全局属性 1.返回顶部 1. HTML 全局属性 New : HTML5 新属性. 属性 描述 accesskey 设置访问元素的键盘快捷键. clas ...

  10. 7-4 IP思考

    内网ip和公网Ip 什么是内网IP:  一些小型企业或者学校,通常都是申请一个固定的IP地址,然后通过IP共享(IP Sharing),使用整个公司或学校的机器都能够访问互联网.而这些企业或学校的机器 ...