免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1430 | 回复: 0
打印 上一主题 下一主题

linux消息队列解析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-10 19:45 |只看该作者 |倒序浏览

基本概念
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 #include  
/*请求方程序msgreq.c*/
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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);
         }
     }
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103428/showart_2067368.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP