UNIX环境下如何应用消息队列实现进程间通信

Unix/Linux 进程间通信消息队列应用实例 场景:     进程A向消息队列写消息,而进程B则从消息队列读消息。 消息队列和之前的管道不同,消息队列是相对独立于进程的,它不需要进程自己来提供同步方法。消息队列里面有消息就可以读。 读取消息实例:msg_rcv.c #include #include #include #include #include #include struct my_msg_st { 阅读详情

一、引言

----进入九十年代后,随着计算机和网络技术的发展,很多数据处理系统都采用开放系统结构的客户机/服务器网络模式。即客户机提出任务请求,由服务器做相应处理,执行被请求的任务,然后将结果返回给客户机。例如:银行ATM的前置机和数据处理的主机之间即构成客户机/服务器模式;电话银行的前置机和银行数据处理主机之间也构成这种模式结构。还有POS等。这样,各种应用的请求是很频繁的,数据主机在处理通存通兑,ATM,电话银行,POS等各种请求时,如果没有相应机制的控制,数据将出现混乱,有可能产生透支,也有可能处理密码已改变的帐户.。数据的完整性,安全性无法控制。而消息队列正是解决这一问题的有力工具。它使主机在处理各种请求时,按照先后顺序有条不紊地进行,保证了数据的一致性和安全性。

二、基本概念

----1.队列

----队列是信息的线性表,它的访问次序是先进先出(FIFO)。也就是说,置入队列中的第一个数据项将是从队列中第一次读出的数据项,置入的第二项将是读出的第二项,依此类推。这是队列允许的唯一存取操作,其它随机访问是不允许的。这种数据结构保证对数据资源的请求将严格按照先后顺序进行,因而可用于对事件的调度并起到I/O缓冲的作用。

----2.报文

----发送进程和接收进程进行信息的交换,一般是通过将信息划分为若干段放入数据交换缓冲器中,进程间通过对该缓冲器的存取来实现通信。因此,数据是以不连续的形式在进程间传送,这些不连续的部分就叫报文。

----3.消息队列

----将报文按队列的结构进行组织就叫消息队列。该队列用于存放正被发送或接收的每一个报文的标题信息。每一个消息队列还对应有一个数据结构,它含有消息队列的存取权限,和消息队列的当前状态信息等信息。消息队列可进行"发送"和"接收"操作。


三、消息队列的编程要点及运作过程

----1.消息队列的创建

----在报文能够发送和接收之前,必须创建一个能够唯一被识别出的消息队列和数据结构,这个被创建的唯一标识符叫做消息队列描述符(msqid),用来识别或引用相关的消息队列和数据结构。用msgget(longkey,intmsgflg)系统调用来创建消息队列,其中key是一个长整型,可由用户设定也可通过ftok()获得。msgflg的值是八进制的消息队列操作权和控制命令的组合。操作权定义为:


操作允许权八进制整数

用户可读0400

用户可写0200

同组可读0040

同组可写0020

其它可读0004

其它可写0002


----操作权可相加而派生,如用户可"读"、"写"的权限为0400|0200=0600。控制命令可取IPC_CREAT或IPC_EXCL。如果要创建一个key=888且属主和同组可读写的消息队列,执行以下系统调用msgget(0x888,0660|IPC_CREAT)。创建后可用ipcs命令看到以下信息:


IPCstatusfrom/dev/memasofSun

Jan2506:49:521970

TIDKEYMODEOWNERGROUP

MessageQueues:

.q70x00000888--rw-rw----

rootsystem

...


----它的消息队列描述符是7,属主是root,同组是system,存取权是属主、用户可读写。如果执行msgget(0x888,0660|IPC_CREAT)时,与0x888对应的消息队列已存在,则返回该消息队列的描述符msqid。
----2.消息的发送

----消息队列一经创建即可用msgsnd(intmsqid,void*msgp,size_tmsgsz,intmsgflg)发送消息。msgqid是经msgget创建的消息队列描述符,msgp是指向消息段的指针,该指针所指结构含有报文类型和要发送或接收的报文:


structmsgbuf{

longmtype;/*消息类型*/

charmtext[512];

/*消息正文,512暂定为消息段的大小*/

}

----msgsz是msgp参量指向的数据结构中字符数组的长度,即报文长度,最大值由MSGMAX确定。msgflg是当消息队列满时(队列中无空闲空间),系统要采取的行动.如果msgflg&IPC_NOWAIT=真,调用进程立即返回,不发送该消息。如果msgflg&IPC_NOWAIT=假,调用进程暂停执行,处于"挂起"状态,且不发送该消息。直到下列情况之一出现:
-----引起暂停的条件不再存在,如队列出现空闲,即可发送
-----该消系队列被从系统中删去
-----调用进程接收到一个要捕捉的信号,如中断信号,此时不发送消息,调用进程按signal中描述的方式执行。

----如果msgsnd返回0则发送成功。返回-1则表示发送失败,错误类型可具体查看errno。

----3.消息的接收

----用msgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg)系统调用从msqid消息队列中读取一条信息并将其放入消息段指针msgp指向的结构。msgsz给出mtext的字节数,如果所接收的消息比msgsz大且msgflg&MSG_NOERROR为真,则按msgsz的大小截断而不通知调用进程。msgtyp指定要求的消息类型:

----msgtyp=0接收消息队列中的第一个报文
----msgtyp>0接收消息队列中的类型为msgtyp的第一个报文
----msgtyp<0接收消息队列中小于等于msgtyp绝对值的最低类型的第一个报文

----当队列上没有所期望类型的消息或消息队列为空时msgflg指出调用进程要采取的行动:如果msgflg&IPC_NOWAIT为真,则调用进程立即结束并返回-1。如msgflg&IPC_NOWAIT为假,则调用进程暂停执行直至出现:

-----队列中放入所需类型的消息,调用进程接收该消息
-----msqid消息队列从系统中删除
-----调用进程接收到捕获的信号,此时不接收消息,调用进程按signal描述的方式执行。

----如果msgrev执行成功,则返回放入mtext中的字节数,失败返回-1,错误类型可查errno。

----4.消息队列的控制和撤销

----用msgctl(intmsqid,intcmd,structmsqid_ds*buf)系统调用实现对消息队列的控制。msgqid必须是用msgget创建的消息队列描述符。cmd可以是:

----IPC_STAT查看消息队列的状态,结果放入buf指针指向的结构
----IPC_SET为消息队列设置属主标识,同组标识,操作允许权,最大字节数
----IPC_RMID删除指定的msqid以及相关的消息队列和结构

四、编程示例

----下面给出一个运用消息队列,实现进程通信的实例。以下程序在IBMRS/6000小型机(AIX操作系统)上和IBMPC(UNIX操作系统)上分别调试通过。该程序主要模拟根据帐号查询余额的过程。包括三方面:

请求进程从标准输入读入帐号,并将该帐号通过消息队列发送给服务进程;

服务进程接收该帐号后,按照请求的先后顺序在标准输入上输入该帐户的姓名和余额,并将结果返回给客户进程;

请求进程接收返回的信息,并将结果输出在标准输出上。
----服务进程(msgcenter)先于请求进程(msgreq)启动.客户进程启动时要携带请求编号,可同时起动多个请求进程。


/*请求方程序msgreq.c*/

#include

#include

#include

#include

#include

static struct msgbuf1{

long mtype;

char mtext[100];

} sndbuf, rcvbuf, *msgp ;

extern int errno;

main(int argc, char **argv)

{ int rtrn, msqid ;

char name[10];

double balance;

if (argc!=2){ fprintf(stderr,

"msgreq [01-99]/n"); exit(-1); }

if ( (msqid = msgget(0x888, IPC_CREAT|0660)) == -1 ){

fprintf(stderr, "msgget 888 failed !/n"); exit(-1);

}

msgp=&sndbuf;

sprintf(sndbuf.mtext,"%2.2s",argv[1]);

printf("输入4位帐号:");

scanf("%s",&sndbuf.mtext[2]);

sndbuf.mtext[6]=0;

msgp->mtype=666;

rtrn=msgsnd(msqid,msgp, strlen(sndbuf.mtext), 0);

if (rtrn==-1){

perror("msgsnd"); exit(-1);

}

msgp=&rcvbuf;

fprintf(stderr,"等待后台数据处理进程的回答....");

rtrn=msgrcv(msqid,msgp, 100, atoi(argv[1]), 0);

if(rtrn==-1){ perror("msgrcv"); exit(-1); }

sscanf(rcvbuf.mtext,"%[^|]|%lf",name,&balance);

printf("/n姓名=%s/n",name);

printf("余额=%lf/n",balance);

}

 

/*服务方程序msgcenter.c*/

#include

#include

#include

#include

#include

static struct msgbuf1{

long mtype;

char mtext[100];

} sndbuf, rcvbuf , *msgp;

extern int errno;

main()

{ int rtrn, msgqid ;

char strbuf[100];

if ( (msqid = msgget(0x888, IPC_CREAT|0600)) == -1 ){

fprintf(stderr, "msgget 888 failed !/n"); exit(-1);

}

while(1) {

msgp=&rcvbuf;

fprintf(stderr,"等待前台进程的请求....");

rtrn=msgrcv(msqid, msgp, 100, 666 ,MSG_NOERROR);

if(rtrn==-1){ perror("msgrcv");exit(-1); }

msgp=&sndbuf;

sprintf(strbuf,"%2.2s/0",rcvbuf.mtext);

msgp->mtype=atoi(strbuf);

printf("/n输入帐号=%4.4s的帐户姓名:",&rcvbuf.mtext[2]);

scanf("%s",sndbuf.mtext);

strcat(sndbuf.mtext,"|");

printf("输入该帐户余额:");

scanf("%s",strbuf);

strcat(sndbuf.mtext,strbuf);

rtrn=msgsnd(msqid,msgp, strlen(sndbuf.mtext), 0);

if (rtrn==-1){ perror("msgsnd"); exit(-1); }

}

}

 
进程间通信消息队列 首先说一下什么是消息队列消息队列进程间通信的一种,它是由操作系统维护的以字节序列为基本单位的间接通信机制,它提供了一个进程向另一个进程发送一个带类型的数据块的方法。 我们知道用管道来实现进程间通信的机制是两个进程利用管道文件来实现数据交流,那么消息队列与管道有什么区别呢? 首先看一下管道通信机制的模型: 然后消息队列通信模型: 从上面图中可看出两者有着本质的区别。那么两个进程怎... 阅读详情

相关推荐

UNIX网络编程第二卷:精通进程间通信(IPC)

本文还有配套的精品资源,点击获取 简介:《UNIX网络编程卷2:进程间通信》是W. Richard Stevens所著的经典作品,系统地讲解了UNIX系统中进程间通信的关键技术和方法。本书涵盖了管道、信号、共享内存、消息队列、信号量、套接字、命名管道、内存映射以及进程间同步与互斥等核心概念。通过这本书,读者将深入了解如何在UNIX系统上实现高效的多进程应用,并掌握包括实用程...

weixin_35696112的博客 1448

利用消息队列实现进程间通信

利用消息队列基本函数,实现Linux系统下进程A和进程B之间的消息收发。 msgsend输入‘end’,退出程序

Unix环境下利用Socket和消息队列构建应用通信平台

Unix环境下利用Socket和消息队列构建应用通信平台

linux消息队列操作

消息队列的操作无非有下面三种类型:1、 打开或创建消息队列消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,只需提供该消息队列的键值即可;注:消息队列描述字是由在系统范围内唯一的键值生成的,而键值可以看作对应系统内的一条路经。2、 读写操作消息读写操作非常简单,对开发人员来说,每个消息都类似如下的数据结构

6万+

进程间通信 —— 消息队列

本文主要记录在学习Linux进程间通信时,关于消息队列的原理、实例代码及总结

再努力一点点就好了 3493

UNIX/Linux进程间通信IPC系列(四)消息队列

消息队列 消息队列是消息的链表,存放在内核中并由消息队列标识符标识。在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达。这跟管道和FIFO是相反的,对后两者来说,除非读出者已存在,否则先有写入者是没有意义的。   管道和FIFO都是随进程持续的,XSI IPC(消息队列、信号量、共享内存)都是随内核持续的。 当一个管道或FIFO的最后一次关闭发生时,仍在该管道或

菜鸟的自留地-mooyang 1万+

Unix网络编程-进程间通信---6、System IPC---消息队列

1、使用消息队列标识符表示(和普通文件fd相似) 2、打开一个消息队列标识符时,内核对应维护一个信息结构体 内核给每一个system V IPC维护一个信息结构体: struct ipc_perm{ uid_t uid; gid_t gid; uid_t cuid; gid_t ugid; mode_t mode;//读写权限 ulong_t seq; ket_t ...

LuckyDog0623的博客 381

java消息队列如何实现通信,UNIX环境下如何应用消息队列实现进程间通信

一、 引 言---- 进 入 九 十 年 代 后, 随 着 计 算 机 和 网 络 技 术 的 发 展, 很 多 数 据 处 理 系 统 都 采 用 开 放 系 统 结 构 的 客 户 机/ 服 务 器 网 络 模 式。 即 客 户 机 提 出 任 务 请 求, 由 服 务 器 做 相 应 处 理, 执 行 被 请 求 的 任 务, 然 后 将 结 果 返 回 给 客 户 机。 例 如: 银 行A...

weixin_39872257的博客 149

UNIX进程间通信

UNIX进程间通信方式 目录 1. 无名管道 2. 有名管道 3. 共享内存 4. 消息队列 5. 信号灯 1.无名管道 1.1摘要: 1.1.1无名管道为一种半双工通信方式,需要双方通信时,需要建立起两个管道,只能用于父子进程和兄弟进程之间的通信。 1.1.2无名管道单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。 1.1.3数

weixin_48101626的博客 488

进程间通信如何高效实现?嵌入式Linux开发者必看的IPC实战指南

掌握嵌入式 Linux 的 C 语言进程间通信高效实现方法,详解管道、消息队列、共享内存等IPC机制在资源受限环境中的应用与优化,提升系统响应速度与稳定性。适用于工业控制、物联网设备开发,值得收藏。

LogicShoal的博客 870

Hyperf方案 进程间通信IPC

【代码】Hyperf方案 进程间通信IPC。

qq_37805832的博客 31

数据通信与交换

Unix环境下利用Socket和消息队列构建应用通信平台》 《基于消息队列软总线的系统集成与数据交换方案》

citongke1的专栏 791

UNIX环境高级编程学习之第十五章进程间通信 - 通过消息队列实现进程间通信

UNIX环境高级编程学习之第十五章进程间通信 - 通过消息队列实现进程间通信

lovelixiujie的专栏 1332

深入理解Linux内核笔记一

同步和临界区: 实现可重入内核需要利用同步机制,因为如果当内核控制路径对某个内核数据结构进行操作时被挂机,那么,其它内核控制路径就不应当再对该数据结构进行操作。 对全局变量的安全访问通过原子操作来保证。 如果内核支持抢占,如Linux,那么在应用同步机制时,确保进入临界区前禁止抢占,退出临界区时启用抢占。 信号量: 可以把信号量看成一个对象,其组成如下: 一个整数变量 一个等待进程的链表 两个原子方法:down()和up() 每个要保护的数据结构都有它自己的信号量,其初始值为1。当内核控制路

dw147258dw的专栏 814

Unix进程间通信

如果没有指定IPC_NOWAIT,则进程阻塞直到( a)有空间可以容纳要发送的消息,或( b)从系统中删除了此队列,或( c)捕捉到一个信号,并从信号处理程序返回。● key:这是一个键(key),用于标识信号量集。小于0:进行信号量的获取操作(P操作),如果信号量的当前值至少是 sem_op 绝对值,那么 sem_op 的绝对值会从信号量值中减去。对用户而言, sem_base指针是没有价值的,它指向内核中的 sem结构数组,该数组中包含了sem_nsems个元素,每个元素各对应于集合中的一个信号量值。

qq_56110001的博客 2073

Linux进程间通信的几种方式总结-概述_linux unix进程间通信有哪些方式

前者对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。Linux则把两者继承了下来UNIX进程间通信方式包括:管道、FIFO、信号。System V进程间通信方式包括:System V消息队列、System V信号灯、System V共享内存POSIX进程间通信包括:posix消息队列、posix信号灯、posix共享内存。

2501_90249181的博客 820

UNIX环境高级编程---进程间通信总结

进程间通信1 管道匿名管道命名管道2 消息队列3 信号量4 共享内存5 信号6 套接字总结 Linux下的进程通信机制叫做IPC(InterProcess Communication),在Linux下有6大通信的方法,分别是:Socket、管道、信号、信号量、消息队列、共享内存。 每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。 1 管道 匿名管道 匿名管道是在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利。匿名管道是半双

qq_41683305的博客 1765
上一篇: Unicode简介
下一篇: 中国互联网top100的主要业务分析
mmquit
博客等级 码龄19年 23粉丝 16原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值