linux、uinux消息队列进程通信

徘徊边缘 提交于 2020-02-17 11:25:37

下次打开时候还会残留以前的消息2.没有删除消息队列。

消息队列的基本概念消息队列 也叫做报文队列)Unix系统V版本中3种进程间通信机制之一。另外两种是信号灯和共享内存。这些IPC机制使用共同的授权方法。只有通过系统调用将标志符传送给核心之后,消息队列就是一个消息的链表。就是把消息看作一个记录。进程才干存取这些资源。这种系统IPC对象使用的控制方法和文件系统非常类似。使用对象的引用标志符作为资源表中的索引。

并且这个记录具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以依照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读出消息。

而接收方如果没有收到消息也不需等待。这种通信机制相对简单,Linux采用消息队列的方式来实现消息传送。这种消息的发送方式是发送方不必等待接收方检查它所收到消息就可以继续工作下去。但是应用顺序使用起来就需要使用相对复杂的方式来应付了新的消息总是放在队列的末尾,接收的时候并不总是从头来接收,可以从中间来接收。

只有在内核重起或者显示删除一个消息队列时,消息队列是随内核持续的并和进程相关。该消息队列才会真正被删除。因此系统中记录消息队列的数据结构 structipc_idmsg_id位于内核中,系统中的所有消息队列都可以在结构msg_id中中找到访问入口。

IPC标识符:每一个IPC目标都有一个唯一的IPC标识符。这里所指的IPC目标是指一个单独的消息队列、一个信号量集或者一个共享的内存段。系统内核使用此标识符在系统内核中指明 IPC目标。

则必需使用一个 IPC关键字。客户端进程和服务器端进程必需双方都同意此关键字。这是建立一个客户机/服务器框架的第一步。SystemVIPC机制中,IPC关键字:想要获得唯一的标识符。建立两端联系的路由方法是和IPC关键字直接相关的通过在应用顺序中设置关键字值,每一次使用的关键字都可以是相同的一般情况下,可以使用ftok函数为客户端和服务器端发生关键字值。

ipc命令命令ipc用于读取SystemVIPC目标的状态。

ipc-q只显示消息队列。

ipc-s只显示信号量。

ipc-m只显示共享内存。

ipc–help其他参数。

消息队列的主要调用

消息队列的主要调用有下面4个内核中实现消息传送机制的代码基本上都在文件ipc/msg.c中。

这个消息调用负责返回这个队列的标识号;如果这个队列不存在就创建一个消息队列,1msgget调用者提供一个消息队列的键标 用于表示个消息队列的唯一名字)当这个消息队列存在时候。然后返回这个消息队列的标识号 主要由sys_msgget执行。

主要由sys_msgsnd执行。2msgsnd向一个消息队列发送一个消息。

主要由sys_msgrcv执行。3msgrcv从一个消息队列中收到一个消息。

可以执行检索、删除等的操作,4msgctl消息队列上执行指定的操作。根据参数的不同和权限的不同。主要由sys_msgctl执行。

#includ<SYSTYPES.H="">#includ<SYSIPC.H="">#includ<SYSMSG.H="">

intmsggetkey_tmsgkeiintflag;取得一个消息队列的ID如不存在则建立。

返回值:胜利时:消息队列的ID失败时:-1

msgflag与上一章所讲的共享内存的flag起一样的作用,intmsgsndintmsqidstructmsgbuf*msgpsize_tmsgsizintmsgflag;向消息队列送消息返回值:胜利时:0失败时:-1msqid消息队列的IDsize_tmsgsiz结构体成员mdata大小。不过,当这个参数为IPC_NOWA IT时候,如果消息队列已满,则返回错误值。如果不为IPC_NOWA IT消息队列已满 情况下,会一直等到消息队列有空地方的时候再发送。

和结构体的名称。尽量不要修改结构体成员的名称和类型。实际上,注意这里的这个 structmsgbuf*msgp.要求的格式如下:structmsgbuf{longmtype;charmdata[256];};longmtype这里我用来保管本进程的PID.mdata则是保管要发送的数据。由于mdata大小不一定(根据实际需要定义)所以这个结构体并没有事先定义好。但是定义这个结构体的时候一定要遵循这个规定。可以改的只有mdata大小。根据mtype还可以有所选择地接受消息。这在下面将会谈到

如果消息队列是空的则等到有消息可读的时候再读。当不为IPC_NOWA IT时候,intmsgrcvintmsqidstructmsgbuf*msgpsize_tmsgsizlongmsgtypintmsgflag;从消息队列取得一个消息返回值:胜利时:0失败时:-1msqid*msgpmsgsiz不用说了longmsgtyp结构体msgbufmtype成员。msgflag与上述一样。只不过为IPC_NOWA IT时候。如果消息队列是空的则返回错误值(与字面上理解的有些相反)

下面这个链接帮助了更好地理解了msgrcv中的longmsgtyp这个参数和

structmsgbuf{longmtype;charmdata[256];};

里的longmtype这个结构体成员。

http://topic.csdn.net/u/20120131/15/235be4a4-3901-41ef-a577-55a5650efeeb.html?14521

为了控制管理消息队列,同样地。一样有一个函数msgctl如下:#includ<SYSTYPES.H="">#includ<SYSIPC.H="">#includ<SYSMSG.H="">

intmsgctlintmsqidintcmdstructmsqid_d*buf;返回值:胜利时:0失败时:-1cmd所指定的值与共享内存局部相同。

最后自己写了一个利用消息队列实现进程通信

将B端发送的消息类型为偶数。基本思路:每次将A端发送消息时的消息类型标志为奇数。

A端读取消息类型为偶数的消息(也就是说是从B端发送过来的

B端读取消息类型为奇数的消息(也就是说是从A端发送过来的

[cpp]viewplaincopi//A .c#includ<SYSTYPES.H="">#includ<SYSIPC.H="">#includ<SYSMSG.H="">#includ<STDIO.H>

intmain

发送偶数消息类型*/intmsqid;key_tmsgkey;structmsgbuf{longmtype;charmdata[256];};structmsgbufmsgdata*p;p=&msgdata;msgkei=ftok"."'a';/*计算标识符*/msqid=msggetmsgkeiIPC_CREA T|0666;/*取得消息队列的ID*{intcount=0;/*打印奇数消息类型。/

while1

{printf"MiiBotre";fflushstdin;/*刷新规范输入缓冲区*/getp->mdata;/*输入字符串*/p->mtype=count;

if!msgsndmsqidpsizeofp->mdata0/*送消息*/{count=count+2;}

msgrcvmsqidpsizeofp->mdatacount+10;/*读消息*/ifp->mtype%2==1{printf"Firefoxbug%s\n"p->mdata;count+=2;}

}return0;}[cpp]viewplaincopi//B.c#includ<SYSTYPES.H="">#includ<SYSIPC.H="">#includ<SYSMSG.H="">#includ<STDIO.H>

intmain

发送偶数消息类型*/intmsqid;key_tmsgkey;structmsgbuf{longmtype;charmdata[256];};structmsgbufmsgdata*p;p=&msgdata;msgkei=ftok"."'a';msqid=msggetmsgkeiIPC_CREA T|0666{intcount=1;/*打印奇数消息类型。;

while1

{printf"Firefoxbug";fflushstdin;getp->mdata;p->mtype=count;if!msgsndmsqidpsizeofp->mdata0

{count=count+2;}

msgrcvmsqidpsizeofp->mdatacount-10;ifp->mtype%2==0{printf"MiiBotre%s\n"p->mdata;count+=2;}

}return0;}A.c和B.c顺序基本上是一样的这个顺序还有一些不完善的地方:

必需等对方输入以后才 会显示结果。这里我也不清楚怎么回事。gdb调试还不太会,1.每个端口不能连续输入。错误不太会找。希望高手指教,呵呵。

本文地址:http://www.ftnanke.com

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!