消息队列函数原型

在建立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. 前端解析Markdown

    目录 前端解析Markdown 1.使用strapdown 1.1.下载 1.2.使用 2.使用marked(配合highlightjs) 2.1.下载 2.2.使用 3.使用mdjs(配合highl ...

  2. MySQL教程和使用手册

    MySQL 教程 MySQL 教程.MySQL 安装.MySQL 管理.MySQL PHP 语法.MySQL 连接.MySQL 创建数据库.MySQL 删除数据库.MySQL 选择数据库.MySQL ...

  3. cs224d 作业 problem set1 (一) 主要是实现word2vector模型,SGD,CBOW,Softmax,算法

    ''' Created on 2017年9月13日 @author: weizhen ''' import numpy as np def sigmoid(x): return 1 / (1 + np ...

  4. 用 Flask 来写个轻博客 (5) — (M)VC_SQLAlchemy 的 CRUD 详解

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 SQLAlchemy 的 CRUD Create 增添数据 ...

  5. 4.Grafana展示监控数据

    Grafana是什么?我们知道Node_export监控服务器状态,但是没有具体的展示,简单来说,Grafana的主要作用就是对监控的数据进行图形化展示. docker部署 grafana我们这里采用 ...

  6. 微信小程序观察者模式 observers

    const app = getApp(); const request = require('../../../utils/request.js'); Component({ options: { m ...

  7. Python List列表的操作说明

    Python中List的N种操作,其简单程度令人叹为观止... C:\Users\rhys>python Python 2.7.14 (v2.7.14:84471935ed, Sep 16 20 ...

  8. angularJS CDN

    http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js

  9. css篇-页面布局-三栏布局

    页面布局 题目:假设高度已知,请写出三栏布局,其中左栏.右栏宽度各为300px,中间自适应. 1)浮动 2)绝对定位 3)Flexbox 4)表格布局 5)网格布局(CSS3的Grid布局) 代码: ...

  10. 一道简单的面试题,难倒各大 Java 高手!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 最近栈长在我们的<Java技术栈知识星球>上分享的一道 Java 实战面试题,很有意思,现在拿出来和大家分享下, ...