- 浏览: 63415 次
- 性别:
- 来自: 武汉
基本概念
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)启动.客户进程启动时要携带请求编
号,可同时起动多个请求进程。
程序在HP-unix有点问题!! C,S都生成ID一样的消息队列
而且要加两个头文件:#include <stdlib.h> #include <string.h>
/*请求方程序msgreq.c*/
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static struct msgbuf1
{
long mtype;
char mtext[100];
} sndbuf, rcvbuf, *msgp ;
extern int errno;
int 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 <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct msgbuf1
{
long mtype;
char mtext[100];
} sndbuf, rcvbuf , *msgp;
extern int errno;
int main()
{
int rtrn, msqid ;
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);
}
}
}
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)启动.客户进程启动时要携带请求编
号,可同时起动多个请求进程。
程序在HP-unix有点问题!! C,S都生成ID一样的消息队列
而且要加两个头文件:#include <stdlib.h> #include <string.h>
/*请求方程序msgreq.c*/
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static struct msgbuf1
{
long mtype;
char mtext[100];
} sndbuf, rcvbuf, *msgp ;
extern int errno;
int 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 <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct msgbuf1
{
long mtype;
char mtext[100];
} sndbuf, rcvbuf , *msgp;
extern int errno;
int main()
{
int rtrn, msqid ;
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);
}
}
}
发表评论
-
vim 设置
2011-07-06 19:56 622svn checkout http://vimide.goog ... -
Linux网络编程-- 服务器模型
2010-12-30 16:34 733在网络程序里面,一般的 ... -
深度掌握NFS服务器
2010-09-30 10:48 1005对于NFS服务器,可能你 ... -
nfs速度优化
2010-09-30 10:07 15071.设置块大小 mount命令的risize和wsize指定了 ... -
shell比较小数大小
2010-09-26 14:56 17471. awk -v a=0.7 -v b=0.5 'BEGIN ... -
linux svn命令
2010-08-12 10:53 8441、Linux命令行下将文件c ... -
linux下常用压缩格式的压缩与解压方法
2010-08-10 10:50 676.tar 解包: tar xvf FileName.tar 打 ... -
GDB调试
2010-08-06 14:26 10781 GDB 命令行参数 启动 G ... -
有用的linux命令
2010-08-04 15:27 676关闭防火墙:services iptables stop 重 ... -
很有用的命令
2010-07-28 13:37 638useradd $name; echo $passwd | p ... -
Linux环境下使用Eclipse开发C++动态链接库程序
2010-07-26 17:42 2324Linux中也有类似Windows中DLL的变成方法,只不过名 ... -
两机建立信任关系
2010-07-15 15:16 7141. Setup a new directory " ... -
利用多核多线程进行程序优化
2010-07-07 14:26 771样例程序 程序功能:求 ...
相关推荐
1. **解析消息队列的创建过程**:查看msgget函数如何查找或创建消息队列,以及如何设置队列的属性。 2. **研究消息的发送和接收**:通过msgsnd和msgrcv函数,了解消息如何被添加到队列、如何从队列中移除以及如何...
在Linux操作系统中,消息队列是一种非常重要的进程间通信(IPC)机制,它允许不同进程之间传递结构化数据。这个“linux下消息队列例程源码.zip”压缩包很可能包含了一些示例代码,用于演示如何在Linux内核环境下使用...
本文将详细解析标题“linux消息队列使用示例”中涉及的知识点,并通过描述中的简单示例代码来理解消息队列的工作原理。 首先,我们需要了解消息队列的基本概念。消息队列是内核维护的一个特殊的数据结构,它存储由...
本文将深入探讨如何使用消息队列在两个不同的Linux进程中进行通信,基于提供的文件`msg_rcv.c`和`msg_send.c`,我们可以理解为接收端和发送端的实现。 ### 1. 消息队列的概念 消息队列是一种内核级的数据结构,它...
根据给定的信息,我们可以分析并总结出关于进程与消息队列的相关知识点: ### 进程与消息队列的基础概念 1. **进程**:在计算机系统中,进程是正在运行的程序实例。每个进程都有一个独立的地址空间,并且可以执行...
Linux消息队列是一种进程间通信(IPC)机制,允许不同进程之间传递消息。在这个名为“mqueue”的项目中,开发者创建了一个简单的示例,用于演示如何在Linux环境下使用C语言实现消息队列的功能。通过提供的代码,我们...
总结来说,消息队列在Linux系统编程中扮演着重要角色,它提供了有序、可靠的数据传递手段,适用于需要长时间保存消息或者希望消息按顺序处理的场景。通过学习和理解消息队列的工作原理以及示例代码,开发者可以更好...
消息队列和共享内存作为Linux系统中的IPC机制,为进程间的数据交换和资源共享提供了高效的方法。消息队列是内核维护的、存放在内存中的消息链表,支持按类型随机查询消息,不局限于先进先出的次序。而共享内存则允许...
在Linux系统编程中,银行管理系统的实现是一个典型的案例,它涉及到多进程间的通信与协作,这里我们主要关注的是基于消息队列的通信机制。消息队列是Linux内核提供的一种进程间通信(IPC, Inter-Process ...
Linux操作系统提供了多种进程间通信(IPC,Inter-Process Communication)机制,其中包括消息队列。消息队列允许不同进程之间通过发送和接收消息进行通信,而无需知道对方的详细信息。这种方式既简单又高效,尤其...
消息队列的优点在于它提供了消息的存取控制,允许进程异步通信,而且消息不会丢失,即使发送消息的进程突然终止。 在实际应用中,这些进程通信机制各有优缺点。例如,信号量适合控制资源的并发访问,而管道则简单且...
### Linux中的消息队列学习笔记 #### 消息队列概念 消息队列是一种进程间通信方式,允许发送包含一定格式的数据消息。消息队列中的消息由消息类型和消息文本组成,消息类型是一个整数值,它用于区分不同类型的事件...
在Linux操作系统中,消息队列是一种进程间通信(IPC,Inter-Process Communication)机制,它允许进程之间通过消息传递数据。本报告详细分析了LINUX的消息函数,包括它们的主要功能、子模块以及相关数据结构。以下是...
【标题】:“Linux信号机制解析.pdf” 【描述】:“Linux信号机制解析.pdf” 【标签】:“Linux 操作系统 系统开发 参考文献 专业指导” 【部分内容】:分析了信号机制的特性,指出了早期信号机制的不足、原因...
### ActiveMQ 消息队列概述 #### 一、ActiveMQ简介 ActiveMQ是由Apache基金会提供的一个开源消息中间件,其作为业界最成熟且功能强大的消息总线之一,在分布式系统和微服务架构中发挥着核心作用。ActiveMQ遵循Java...
- **进程间通信(IPC)**:包括信号、管道、消息队列、共享内存等多种方式,用于进程间的同步和数据交换。 - **线程**:现代Linux内核支持线程,每个线程拥有独立的执行栈和程序计数器,但共享进程的内存空间。 #...
4. **AMQP协议**:RabbitMQ基于AMQP(Advanced Message Queuing Protocol)协议,书中会深入解析AMQP协议的结构和机制,帮助读者理解消息传递的细节。 5. **消息持久化与高可用**:如何确保消息在系统故障后不丢失...
本文将详细探讨"队列实现的内存管理源代码"这一主题,重点解析其在Linux环境下的应用及工作原理。 队列是一种线性数据结构,具有先进先出(FIFO)的特性,即最早进入队列的元素最先被处理。在内存管理中,队列可以...