转自 http://blog.csdn.net/liang890319/article/details/8280934

代码来自:嵌入式Linux应用开发标准教程

消息可以理解为写信给某个人,这里在应用中是告诉系统写信人和写信的内容就可以了,

别人会来看发信人是谁,如果不是自己想要的就放弃读信或者只要有消息自己就读取消息

消息队列就是按队列的方式处理很多消息,先发的最先被读

消息队列:

1)消息队列是一种以链表式结构组织的一组数据,存放在内核中,是由各进程通过消息队列标识符来引用的一种数据传送方式.

2)有两种可以创建消息队列的API函数:system V和POSIX,两者稍有不同,但原理一样.

3)这两类消息队列都采用固定大小,而且要确保所有进程遵循相同的消息结构,接受者必须确定消息的大小,并一次对信息进行读取,否则读取失败.

4)msgget返回的消息队列ID在进程间是有效的,即父子进程或者并行进程都可以用消息队列的方式进行通信.

5)两种API函数的侧重点都略有不同,System

V中消息的优先级有一定的弹性,但是POSIX却严格地遵循优先级的顺序.

消息队列函数

-----------------------------------------------------

linux消息队列函数

--------------------------------

头文件:

#include

#include

#include

www.2cto.com

------------------------------------------

1、系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。

ftok原型如下:

key_t ftok( char * fname, int id )

fname就时你指定的文件名,id是子序号。

在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。

如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16

进制为0x26,则最后的key_t返回值为0x26010002。

查询文件索引节点号的方法是: ls -i

当删除重建文件后,索引节点号由操作系统根据当时文件系统的使用情况分配,因此与原来不同,所以得到的索引节点号也不同。

如果要确保key_t值不变,要目确保ftok的文件不被删除,要么不用ftok,指定一个固定的key_t 值,比如:

#define IPCKEY 0x111

char path[256];

sprintf( path,

"%s/etc/config.ini", (char*)getenv("HOME") );

msgid=ftok( path, IPCKEY

);[/code]

同一段程序,用于保证两个不同用户下的两组相同程序获得互不干扰的IPC键值。

由于

etc/config.ini(假定)为应用系统的关键配置文件,因此不存在被轻易删除的问题——即使被删,也会很快被发现并重建(此时应用系统也将被重起)。

ftok()的设计目的也在于此。

----------------------------------------------------

2、int msgget(key_t key, int msgflg);

//创建消息队列

参数:

key:消息队列关联的键。为IPC_PRIVATE时表示创建自己的消息队列

msgflg:消息队列的建立标志和访问权限。msgflg

的低位用来确定消息队列的访问权限。

IPC_CREAT:如果 key不存在,创建

IPC_EXCL:如果 key 存在,返回失败

IPC_NOWAIT:如果需要等待,直接返回错误

如果单独使用IPC_CREAT,则msgget()要么返回一个新创建的消息队列的标识符,要么返回具有相同关键字值的队列的标识符。如果

IPC_EXCL和IPC_CREAT一起使用,则msgget()要么创建一个新的消息队列,要么如果队列已经存在则返回一个失败值-1。

返回说明:

如果成功,返回消息队列标识符

如果失败,则返回-1:errno=EACCESS(权限不允许)

EEXIST(队列已经存在,无法创建)

EIDRM(队列标志为删除)

ENOENT(队列不存在)

ENOMEM(创建队列时内存不够)

ENOSPC(超出最大队列限制)

www.2cto.com

举例:

msgid=msgget(IPC_PRIVATE,IPC_CREAT|IPC_EXCL|00666); //创建消息队列

--------------------------------------------------

3、int msgsnd(int msqid, const void

*msgp, size_t msgsz, int msgflg); //将消息送入消息队列

参数:

msqid:消息队列的标识符。

msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下

struct msgbuf {

long mtype;

char mtext[1];

};

msgsz:消息的大小。

msgflg:用来指明进程在队列数据满(msgsnd)或空(msgrcv)的情况下所应采取的行动。

如果设置为

IPC_NOWAIT,则在消息队列已满时不发送消息并且调用进程立即返回错误信息EAGAIN。

如果设置为 0,则调用进程阻塞直至消息队列不为满。

返回说明:

成功执行时,msgsnd()返回0, 失败返回-1

举例:msgsnd(g_msg_id,&msg_snd,sizeof(msg_snd.msg_item),IPC_NOWAIT);

//非阻塞发送消息

----------------------------------------------------------

4、ssize_t msgrcv(int msqid, void *msgp,

size_t msgsz, long msgtyp, int msgflg); //从消息队列读取信息

参数:

msgtyp:

msgtyp =

0:收取队列中的第一条消息,任意类型。

msgtyp > 0:收取第一条 msgtyp 类型的消息。

这个能判断自己该不该收这个消息是不是想要的发信人发来的

msgtyp < 0:收取第一条最低类型(小于或等于

msgtyp 的绝对值)的消息。

其他参数参考msgsnd函数。

返回说明:

成功执行时,msgrcv()返回0, 失败返回-1

举例:msgrcv(msgid,&msg_rbuf,sizeof(msg_rbuf.msg_item),10,0);

//阻塞接收

www.2cto.com

----------------------------------------------------------

5、int msgctl (int msqid, int cmd,

struct msqid_ds *buf); //消息队列属性控制

参数:

msqid:消息队列的标识符。

cmd:执行的控制命令,即要执行的操作。包括以下选项:

IPC_STAT:读取消息队列属性。取得此队列的msqid_ds

结构,并将其存放在buf指向的结构中。

IPC_SET :设置消息队列属性。

IPC_RMID:删除消息队列。

IPC_INFO:读取消息队列基本情况。此命令等同于 ipcs 命令。

这 4 条命令(IPC_STAT、IPC_SET、IPC_INFO 和

IPC_RMID)也可用于信号量和共享存储。

buf:临时的 msqid_ds

结构体类型的变量。用于存储读取的消息队列属性或需要修改的消息队列属性。

举例:msgctl(qid, IPC_RMID, NULL)  //删除消息队列

摘自 pj81102的专栏

实例1:一个程序,自己发消息,然后自己再从队列上读消息

#include

#include

#include

#include

#include

#include

#include

#define BUFSZ 512

structmessage

{

longmsg_type;

charmsg_text[BUFSZ];

};

intmain()

{

intqid;

key_t key;

intlen;

structmessage msg;

if((key = ftok(".",'a')) == -1)

{

perror("ftok");

exit(1);

}

if((qid = msgget(key,IPC_CREAT|0666)) == -1)

{

perror("msgget");

exit(1);

}

printf("Opened queue %d\n",qid);

puts("Please enter the message to queue:");

if((fgets((&msg)->msg_text, BUFSZ, stdin)) == NULL)//消息内容

{

puts("no message");

exit(1);

}

msg.msg_type = getpid(); //消息类型,可以理解为发信人名字

len = strlen(msg.msg_text);

if((msgsnd(qid, &msg, len, 0))

{

perror("message posted");

exit(1);

}

if(msgrcv(qid, &msg, BUFSZ, getpid(), 0)

{

perror("msgrcv");

exit(1);

}

printf("message is:%s\n",(&msg)->msg_text);

if((msgctl(qid, IPC_RMID, NULL))

{

perror("msgctl");

exit(1);

}

exit(0);

}

实例2:一个程序发送消息  另一个接收消息,读的是第一条消息不判断是不是自己想要的消息

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 512

structmessage

{

longmsg_type;

charmsg_text[BUFFER_SIZE];

};

intmain()

{

intqid;

key_t key;

structmessage msg;

if((key = ftok(".",'a')) == -1)

{

perror("ftok");

exit(1);

}

if((qid = msgget(key, IPC_CREAT|0666)) == -1)

{

perror("msgget");

exit(1);

}

printf("Open queue %d\n",qid);

while(1)

{

printf("Enter some message to the queue(enter 'quit' to exit):");

if((fgets(msg.msg_text, BUFFER_SIZE, stdin)) == NULL)

{

puts("no message");

exit(1);

}

msg.msg_type = getpid();

if((msgsnd(qid, &msg, strlen(msg.msg_text), 0))

{

perror("message posted");

exit(1);

}

if(strncmp(msg.msg_text,"quit", 4) == 0)

{

break;

}

}

exit(0);

}

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_SIZE 512

structmessage

{

longmsg_type;

charmsg_text[BUFFER_SIZE];

};

intmain()

{

intqid;

key_t key;

structmessage msg;

if((key = ftok(".",'a')) == -1)

{

perror("ftok");

exit(1);

}

if((qid = msgget(key, IPC_CREAT|0666)) == -1)

{

perror("msgget");

exit(1);

}

printf("Open queue %d\n", qid);

do

{

memset(msg.msg_text, 0, BUFFER_SIZE);

if(msgrcv(qid, (void*)&msg, BUFFER_SIZE, 0, 0)

{

perror("msgrcv");

exit(1);

}

printf("The message from process %d : %s", msg.msg_type, msg.msg_text);

} while(strncmp(msg.msg_text,"quit", 4));

if((msgctl(qid, IPC_RMID, NULL))

{

perror("msgctl");

exit(1);

}

exit(0);

}

实例3

#include

#include

#include

#include

#include

#include

#include

struct

msgmbuf

{

long

msg_type;

int

msg_date;

char

msg_text[1024];

};

int main()

{

int

ret;

int

qid;

key_t

key;

struct

msgmbuf msg;

msg.msg_type=100;

key=ftok(".",'a');

if(key==-1)

{

perror("产生标准key错误!\n");

exit(1);

}

qid=msgget(key,IPC_CREAT|0666);

if(qid==-1)

{

perror("创建消息队列失败!");

exit(1);

}

while(1)

{

printf("请输入发送内容:\n");

scanf("%s",&msg.msg_text);

msg.msg_date=system("date|cut -d' ' -f

5");

ret=msgsnd(qid,&msg,sizeof(msg.msg_text),msg.msg_type);

if(ret<0)

{

perror("添加消息失败!");

exit(1);

}

msg.msg_type=200;

msgrcv(qid,&msg,sizeof(msg),msg.msg_type,0);

if(ret<0)

{

perror("读取消息失败!");

exit(1);

}

printf("读取的内容为:\n%s\n",msg.msg_text);

}

msgctl(qid,IPC_RMID,NULL);

return

0;

}

#include

#include

#include

#include

#include

struct

msgmbuf

{

int

msg_type;

int

msg_date;

char

msg_text[1024];

};

int main()

{

int

ret;

int

qid;

key_t

key;

struct

msgmbuf msg;

msg.msg_type=100;

key=ftok(".",'a');

if(key==-1)

{

perror("产生标准key错误!\n");

exit(1);

}

qid=msgget(key,IPC_CREAT|0666);

if(qid==-1)

{

perror("创建消息队列失败!");

exit(1);

}

while(1)

{

ret=msgrcv(qid,&msg,sizeof(msg),msg.msg_type,0);

if(ret==-1)

{

perror("读取消息失败!");

exit(1);

}

printf("读取的内容为:\n%s\n",msg.msg_text);

msg.msg_type=200;

printf("请输入发送内容:\n");

scanf("%s",&msg.msg_text);

msg.msg_date=system("date|cut -d' ' -f 5");

ret=msgsnd(qid,&msg,sizeof(msg.msg_text),msg.msg_type);

if(ret==-1)

{

perror("添加消息失败!");

exit(1);

}

}

msgctl(qid,IPC_RMID,NULL);

return

0;

}

linux 进程uhxuhao,linux 进程间通信三 消息队列以及实例相关推荐

  1. Linux进程通信之System V消息队列

    System V消息队列是Open Group定义的XSI,不属于POSIX标准.System V IPC的历史相对很早,在上个世70年代后期有贝尔实验室的分支机构开发,80年代加入System V的 ...

  2. msgget();msgsnd();msgrcv();msgctl(); 消息队列 Linux进程间的通信方式之消息队列

    Linux进程间的通信方式 ----消息队列. 消息队列和共享内存类似 消息队列它允许一个或多个进程向它写消息,一个或多个进程向它写读消息. 消息队列存在于系统内核中,消息的数量受系统限制. 我们来看 ...

  3. 【Linux系统编程】进程间通信之消息队列

    00. 目录 文章目录 00. 目录 01. 消息队列概述 02. 消息队列相关函数 03. 消息队列读写操作 04. 测试代码 05. 附录 01. 消息队列概述 消息队列提供了一种在两个不相关的进 ...

  4. Linux进程间通信详解(三) —— 消息队列及函数

    消息队列的概念 消息队列就是一个消息的链表,每个消息队列都有一个队列头,用结构struct msg_queue来描述.队列头中包含了该队列的大量信息,包括消息队列的键值.用户ID.组ID.消息数目.读 ...

  5. linux消息通信无法接收,进程间通信:消息队列有关问题:进程1接收不到进程2的消息...

    进程间通信:消息队列有关问题:进程1接收不到进程2的消息 进程间通信:消息队列有关问题:进程1接收不到进程2的消息 日期:2014-05-16 浏览次数:20365 次 进程间通信:消息队列问题:进程 ...

  6. Linux进程间通信——使用消息队列

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

  7. c语言系统编程八:Linux进程间通信之消息队列

    Linux进程间通信之消息队列 一 消息队列概述 二 消息队列的特点 三 消息队列的创建和使用 3.1 获取系统唯一的key值 3.2 创建消息队列 3.3 查看消息队列和删除消息队列的shell命令 ...

  8. linux 消息对lie_Linux进程间通信之消息队列总结

    一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构(消息队列.信号量或共享存储段)都用一个非负整数的标识符( i d ...

  9. Linux系统编程(七)消息队列

    Linux系统编程(七)消息队列 一.什么是消息队列 二.消息队列内部原理 三.实现消息队列的收发 1.发送消息队列 2.接收消息队列 四.消息队列与命名管道的比较 一.什么是消息队列 消息队列提供了 ...

最新文章

  1. 图森无人车联合UCSD新研究:自动驾驶更省油
  2. android 成长日记 5.关于progress控件和Alertdialog和layout学习
  3. 国科大高级人工智能12-博弈
  4. 字符串左侧补0_(48)C++面试之最长不含重复字符的子字符串(动态规划)
  5. 七大步骤,详解预置算法构建模型的全过程
  6. HDOJ-1201 18岁生日
  7. 20行代码实现网页图片抓取。(待完善
  8. C语言入门教程,C语言学习教程
  9. JXT查询数据库导入到Execl
  10. 【Unity3D】sRGB伽马(gamma)空间和sRGB Frame Buffer线性空间的简单介绍
  11. Android上多进程中使用webview的问题
  12. neo4j的搭建和实例使用
  13. 小文聊天机器人(jquery.chatbot.js)使用指南
  14. mysql查询表中不重复数据
  15. javaScript常用语法(持续更新)
  16. 数据库中各表关联图及其说明_如何在图中思考:图论及其应用的说明性介绍
  17. 实验7-1-9 数字加密 (15 分)
  18. Mac OS X 10.10 + WineBottler + XQuartz 成功运行 诛仙3
  19. 广州大学大学物理第十一章 真空中的静电场
  20. layui模板引擎做动态增加和减少表单

热门文章

  1. 介绍一个优秀的单片机图形库,GuiLite
  2. 李宏毅-DeepLearning-2017-Unsupervised Learning:Neighbor Embedding
  3. ClickHouse压测
  4. 25天能过教资吗?逢考必过锦鲤贴
  5. 理解OpenCL中的工作组、工作项的索引
  6. 车牌号正则表达式(包括新能源汽车)
  7. 加速AI工业化 百度云智峰会发布20大新品
  8. 微信公众号H5开发,在微信浏览器打开H5,无法一键下载图片
  9. Mapstruct使用说明(一)
  10. 三秒一页,快速录入书籍中的文字,掌握这个黑科技不加薪才怪