`
unsoundboy
  • 浏览: 61108 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

linux消息队列解析

阅读更多
基本概念

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);
         }
     }
}
分享到:
评论

相关推荐

    进程间通信之深入消息队列的详解

     关于线程的管理(互斥量和条件变量)见:Linux线程管理必备:解析互斥量与条件变量的详解 一、消息队列的特点  1.消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识. 2.消息队列允许一个或...

    Linux内核解析案例详解

    系统调度:研究Linux内核的进程调度算法和策略,了解进程优先级、调度器运行队列、上下文切换等相关概念。 内存管理:深入了解Linux内核的内存管理机制,包括虚拟内存管理、页面置换算法、内存分配和释放等。 文件...

    Linux编程--Linux内核

    4.3.2 消息队列 44 4.3.3 信号量 45 4.3.4 共享存储区 47 第5章 PCI 49 5.1 PCI的地址空间 49 5.2 PCI配置头 50 5.3 PCI的I/O和存储地址空间 51 5.4 PCI-ISA桥 51 5.5 PCI-PCI 桥 51 5.5.1 PCI-PCI桥:PCI I/O和存储...

    嵌入式Linux应用程序开发标准教程(第2版全)

    8.6.2 消息队列的应用 8.7 实验内容 8.7.1 管道通信实验 8.7.2 共享内存实验 8.8 本章小结 8.9 思考与练习 第9章 多线程编程 9.1 Linux线程概述 9.1.1 线程概述 9.1.2 线程机制的分类和特性 9.2 Linux线程编程 ...

    TCP socket SYN队列和Accept队列区别原理解析

    首先我们必须明白,处于“LISTENING”状态的TCP socket,有两个独立的队列: SYN队列(SYN Queue) Accept队列(Accept Queue) 这两个术语有时也被称为“reqsk_queue”,“ACK backlog...在Linux下,重传的次数为:

    Linux编程从入门到精通

    4.3.2 消息队列 44 4.3.3 信号量 45 4.3.4 共享存储区 47 第5章 PCI 49 5.1 PCI的地址空间 49 5.2 PCI配置头 50 5.3 PCI的I/O和存储地址空间 51 5.4 PCI-ISA桥 51 5.5 PCI-PCI 桥 51 5.5.1 PCI-PCI桥:PCI I/O和存储...

    Trie树 linux32 SDK V3.0

    1、SDK开发包包括:动态库、头文件、开发手册、产品手册、解决方案、demo等。 2、Trie树SDK中的API支持以下功能 ...11)消息队列 12)超大规模时钟 13)内存数据表 14)内存目录数据结构 15)域名解析

    LINUX编程白皮书 (全集)

    4.3.2 消息队列 44 4.3.3 信号量 45 4.3.4 共享存储区 47 第5章 PCI 49 5.1 PCI的地址空间 49 5.2 PCI配置头 50 5.3 PCI的I/O和存储地址空间 51 5.4 PCI-ISA桥 51 5.5 PCI-PCI 桥 51 5.5.1 PCI-PCI桥:PCI I/O和存储...

    通用内存多级树 linux32 SDK V3.0

    1、SDK开发包包括:动态库、头文件、开发手册、demo。 2、内存多级树树SDK中的API支持以下功能 1)插入节点 ...11)消息队列 12)超大规模时钟 13)内存数据表 14)内存目录数据结构 15)域名解析

    Linux内核 内容很全

    进程间通信机制 41 4.1 信号机制 41 4.2 管道 42 4.3 套接字 44 4.3.1 System V的进程间通信机制 44 4.3.2 消息队列 44 4.3.3 信号量 45 4.3.4 共享存储区 47 第5章 PCI 49 5.1 PCI的...

    linux编程白皮书

    4.3.2 消息队列 44 4.3.3 信号量 45 4.3.4 共享存储区 47 第5章 PCI 49 5.1 PCI的地址空间 49 5.2 PCI配置头 50 5.3 PCI的I/O和存储地址空间 51 5.4 PCI-ISA桥 51 5.5 PCI-PCI 桥 51 5.5.1 PCI-PCI桥:PCI I/O和存储...

    嵌入式Linux应用程序开发详解

    8.5.1 消息队列概述 267 8.5.2 消息队列实现 268 8.6 实验内容 272 8.6.1 管道通信实验 272 8.6.2 共享内存实验 275 本章小结 277 思考与练习 278 第9章 多线程编程 279 9.1 Linux下线程...

    LINUX系统管理白皮书

    14.5.5 按需运行sendmail队列 149 14.5.6 报告邮件特征 150 14.6 二进制附件的合成和匹配 150 14.7 获取更多的信息 150 第15章 网络新闻 151 15.1 何谓Usenet 151 15.2 Usenet如何对新闻加以控制 152 第16章 ...

    解析linux下安装memcacheq(mcq)全过程笔记

    memcacheQ是一个单纯的分布式消息队列服务。一,MEMCACHEQ的应用背景Web应用中为什么会需要消息队列?主要原因是由于在高并发环境下,由于来不及同步处理,请求往往会发生堵塞,比如说,大量的insert,update之类的...

    基于c++及linux网络编程的web服务器源码.zip

    基于c++及linux网络编程的web服务器源码.zip 基于c++及linux网络编程的web服务器 该web服务器的主要内容如下: 使用了epoll边沿触发+EPOLLONESHOT+非阻塞IO 使用了一个固定线程数的线程池 实现了一个任务队列,...

    C++ Linux WebServer服务器

    利用单例模式与阻塞队列实现异步的日志系统,记录服务器运行状态; 利用RAII机制实现了数据库连接池,减少数据库连接建立与关闭的开销,同时实现了用户注册登录功能。 增加logsys,threadpool测试单元(todo: timer,...

    LINUX编程白皮书

    4.3.2 消息队列 44 4.3.3 信号量 45 4.3.4 共享存储区 47 第5章 PCI 49 5.1 PCI的地址空间 49 5.2 PCI配置头 50 5.3 PCI的I/O和存储地址空间 51 5.4 PCI-ISA桥 51 5.5 PCI-PCI 桥 51 5.5.1 PCI-PCI桥:PCI I/O和存储...

Global site tag (gtag.js) - Google Analytics