进程间通讯--消息队列

上一篇 / 下一篇  2009-05-19 19:42:56 / 个人分类:C/C++

我的栏目
  • 栏目:C/C++

 

~.^i"qZXtS0

51Testing软件测试网/``)ua%Y

1. 创建消息队列

0]!sbS{/\3l0

       #include<sys/types.h>51Testing软件测试网]w H R6D3|_*Ic.h o\&y
       #include<sys/ipc.h>
}Q ? Hz0       #include<sys/msg.h>51Testing软件测试网!}O3hl-^?$p
       intmsgget(key_t key,intmsgflg);

#_e4SZS'`c0

                  成功返回队列ID,失败返回-1

'pp:cUd:~(p+I0

参数51Testing软件测试网8b7c fh4v \

说明

Y%S$C&i!~0

key

7cF+N}:D [7i0

创建/打开队列key,ftok产生,可以直接给常量

/L5n"BH;Q+Qi0

msgflg

X'[?&b X$g0

创建/打开方式IPC_CREATIPC_EXCLIPC_NOWAIT

3E!w#k+yN t iA0

          通常是msgflg =IPC_CREAT| IPC_EXCL|0666,意思是若不存在key值的队列则创建,否则如果存在则打开队列,0666意思与一般文件权限一样,XXX-本用户,同组用户,其他用户的读写执行的权限。

Q.o eI0{2MScw0

       #include<sys/types.h>51Testing软件测试网w-mg1mYu'j
       #include<sys/ipc.h>51Testing软件测试网mU2smNj o
       key_t ftok(constchar*pathname,intproj_id);
51Testing软件测试网8f4g~1Y Lsu

//获取pathname相对应的一个键值, pathname必须是存在并且可读取的文件,proj_id表示序号,用来区别同时的存在文件。成功返回key值,失败返回-1

]QN|Z&?&v|0

         

3z_F[&jq]0

2. 队列读写51Testing软件测试网1oGm&Y^m2Hc%]Cd

       #include<sys/types.h>51Testing软件测试网&J&x c*H jF6|
       #include<sys/ipc.h>
5TKE UTr0       #include<sys/msg.h>
51Testing软件测试网2oe0_IhZ4eI[3V

a)        读取数据――阻塞读取消息队列,直到解除阻塞。

-|g:] t,| h'c N@0

ssize_t msgrcv(intmsqid,structmsgbuf*msgp,size_tmsgsz,longmsgtyp,intmsgflg);51Testing软件测试网p;K0| Y5njx5nm Jh

参数

5M6M%l/V:C"kE2V Cdn0

说明51Testing软件测试网:PYG M;J*Q

msqid51Testing软件测试网p K }t| e e/Y

已打开的消息队列id

IX!I ux0

msgp

a,\n\%~6K \ jtm0

接收存放的消息队列缓存结构51Testing软件测试网\`rz3?Kz ?o

msgsz

*DJ1} Nb!hL0

消息数据长度

@(o0o$f9V X$s9S0

msgtyp51Testing软件测试网(p)oNgDJ[$q.Y

消息类型。=0读取队列中第一个数据。51Testing软件测试网w%O/~0fL$X/CH

msgflg51Testing软件测试网`S9}Mx4h|YcX[

读取标志通常使用IPC_NOWAIT:即没有满足条件的消息,立即返回,此时,错误代码errno=ENOMSG51Testing软件测试网#y-^'Nq:S

IPC_EXCEPT:与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息51Testing软件测试网;j"?'^&B ms s

MSG_NOERROR:截断超长数据51Testing软件测试网5n3Y-u2N:dI6twJ3K\

缓冲内容结构如下:

J/N|$N^(V'A:zY0

structmsgbuf{
2z[ Pn\,oX!M0longmtype;    /* 消息类型 must be > 0 */51Testing软件测试网 @ ?!g-AAl?6|5G!A~
charmtext[1];/* 消息数据 这里只是一个数组的首地址,并非是只有一个字符 */
+@Mx%v8{2fD pFp0            };
51Testing软件测试网!`,~.jf%G j+fJ2Dp?

msgrcv()解除阻塞的条件三个条件:51Testing软件测试网y7Sz?2vd

1. 消息队列中有了满足条件的消息(或使用了);51Testing软件测试网:m*N[8|{%gP'a7M

2. msqid代表的消息队列被删除;51Testing软件测试网F}l-i5abC^6n

3. 调用msgrcv()的进程被信号中断;51Testing软件测试网V/Cz3\'u"xQtx*?

a)        发送数据51Testing软件测试网 e7K#t @,m

int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);51Testing软件测试网-?-m\Uu\|.l%^M/P

参数

Y,V8{i4p0cE"]0

说明

ac%s Om0

msqid

bH&L)\ g2@cP^O0

已打开的消息队列id51Testing软件测试网`+dp4Nw+W'v4cHM

msgp

Vr5\xw6G0

发送存放的消息队列缓存结构51Testing软件测试网} TX5Hn\jz4V!H

msgsz

fT?4?B0

消息数据长度51Testing软件测试网K6Z4UI-c Th

msgflg51Testing软件测试网'EeSc i8P ^(p

消息类型。=0读取队列中第一个数据。51Testing软件测试网2N ~)p8^(}(E

 51Testing软件测试网j3~ \,Qs Ffp

 51Testing软件测试网0\/KC TMrnb

 

-~l.aoX0

3. 消息队列控制51Testing软件测试网P`'lN8W"Dch A g

       #include<sys/types.h>
z'PA.t_0       #include<sys/ipc.h>
#L-U*h@c!}2qgX;o0       #include<sys/msg.h>    
7W(q'f O_4qM0       intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);

ej6Z?.x9N\'M};Lp2h0

        成功返回0,失败返回-151Testing软件测试网|!R+Qo5gK aE

参数51Testing软件测试网P1t%gojR

说明

.Xe#NZUz Cd0

msqid

&D9e[kc;a&H K0gS2M0

已打开的消息队列id51Testing软件测试网%o'H;D/X E+h,s

cmd

/^-S*O;Scm0

控制类型选项51Testing软件测试网6m"b p,m8J5J

IPC_STAT:取得队列状态

Qh|%a6Vvz0

IPC_SET:设置队列属性

)X1k&@\8b4Ko b0

IPC_RMID:删除消息队列51Testing软件测试网-B/y'I9Y;~%|\ Wt

buf51Testing软件测试网u.VD*P/va

存放队列的属性结构51Testing软件测试网n&lI(h i'iG

 51Testing软件测试网ue\]3M#N4ELh.f

      队列属性如下:51Testing软件测试网:t0?$b @/O+g3n1?C

structmsqid_ds51Testing软件测试网^ qF"D\)lgGF
{51Testing软件测试网mx+Yg(k,s?
  structipc_perm msg_perm;/* structure describing operation permission */
'B ]~-M|L-cr q0  __time_t msg_stime;/*最后一次发送消息的时间 */51Testing软件测试网 }r'O6bT
  unsignedlongint__unused1;/*保留*/
9^)qwFq0  __time_t msg_rtime;/* 最后一次接收数据时间 */
%GT7P;[iI z0  unsignedlongint__unused2;    /*保留*/51Testing软件测试网9QsEBS K3U
  __time_t msg_ctime;/* 最后修改时间 */
b bp Jl0EB0  unsignedlongint__unused3;/*保留*/
iD.G5R5|q5h0  unsignedlongint__msg_cbytes;/* 当前队列字节数 */
f[.A-du ]2L8ZD0  msgqnum_t msg_qnum;/* 当前队列的消息数 */51Testing软件测试网va3b*b,OZ
  msglen_t msg_qbytes;/* 队列中容量 */51Testing软件测试网?$V?:J&r8w
  __pid_t msg_lspid;/* 最后发送消息的进程号 */
;K2l ja Te-QP_9k0  __pid_t msg_lrpid;/* 最后接收队列的进程号*/
!tyct^,TVJ0  unsignedlongint__unused4;/*保留*/
|FyGTb$WSK,?0  unsignedlongint__unused5;/*保留*/51Testing软件测试网 ]B"~1qSq-F'\
};

7TYi N%p+I M0

4.例子:51Testing软件测试网:@)?d"` ~[ ~,_

#include<sys/types.h>51Testing软件测试网i_)UJ+ENrX_
#include<sys/msg.h>51Testing软件测试网fNF^.kNnKE6b!S
#include<unistd.h>51Testing软件测试网"q&`h.Z&M,tL
#definemsgkey 0x1100000151Testing软件测试网:Te O/IbtS-Zr]R
structmsg_buf51Testing软件测试网L+H5y^:F
    {51Testing软件测试网"JUI/XQS~
        intmtype;51Testing软件测试网u;b1C#ZhqM
        chardata[255];
-{B"z0UV0    };
M^ t4Zr0 
g9QI r'aEBC0intmain()
9n].alR`0{51Testing软件测试网"l'N0x.Zg.n NVwm
        key_t key;
br eN.NP-f0        intmsgid;51Testing软件测试网I|6h)X!?f0kblb
        intret;51Testing软件测试网wNE1I,t6Y]hT
        structmsg_buf msgbuf;
&Z X s:Z A.X\k0 51Testing软件测试网^+bb^^NAH G
        key=ftok("/tmp/1",'a');51Testing软件测试网{(i1_Q3Yn$nh _)an
        printf("key =[%x]\n",key);
X Dnu!Q!KdT0        //msgid=msgget(key,IPC_CREAT|IPC_EXCL|0666); /*通过文件对应*/51Testing软件测试网v$q pJ$Lc u
        msgid=msgget(msgkey,IPC_CREAT|IPC_EXCL|0666);/*或者取常量*/51Testing软件测试网GEVmJ"m%J `
        if(msgid==-1)51Testing软件测试网r'P4o [S3Nu_5G,a d
        {
A _KL-xX?0                printf("create error\n");51Testing软件测试网.r2qg:dw,W4T s
                return-1;
,X4G9QQK4n[R*S0        }51Testing软件测试网!l!eL2K X5hc9uljzh
 
HdN){xl0        msgbuf.mtype=getpid();
~Mm4c,G'^%e e$t0        strcpy(msgbuf.data,"test haha");51Testing软件测试网9],n%md*Ab j4\Y
        ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);51Testing软件测试网 u%k*u*K*g
        if(ret==-1)51Testing软件测试网Z:N$g W3]sk0B3}.F
        {51Testing软件测试网dfEE&^
                printf("send message err\n");
5X,LsU'| leGi{/Zps0                return-1;
QC%l5b6F`WZ0        }51Testing软件测试网j5[ifjq
 51Testing软件测试网/~bh;N&r;Q,R~k"?
        memset(&msgbuf,0,sizeof(msgbuf));51Testing软件测试网r? @K](PMn
        ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);
X)`#` \8GD%oh2?0        if(ret==-1)
O'u g@0G%p5tj;S M0        {51Testing软件测试网 p;d#]QT-Mb,v7U
                printf("recv message err\n");
)hs7AmT+\w0                return-1;51Testing软件测试网)G{U\.LN
        }51Testing软件测试网2^I(QW[L r
        printf("recv msg =[%s]\n",msgbuf.data);
O|8x6Cw/Y,](q0 
\u PB-_m#F|S5c0        ret=msgctl(msgid,IPC_RMID,NULL);
//删除消息队列
!Vwj7b|"v[1T8I0

dQ9JF8ss7yU0        if(ret==-1)51Testing软件测试网\W%m'c6o&H-}`
        {51Testing软件测试网U yb~}
                printf("del msg err\n");51Testing软件测试网x$|0G|M6u+\hQ:@
                return-1;
lX(Qe'Q_ V~0        }51Testing软件测试网_ \O9M%vES6KV
 51Testing软件测试网'eEZ,rRF"ec
}

t&RP B1i7l0

_v+SQvM.~'Ou Q0  进程间通讯信息查看51Testing软件测试网O2g t Mw#SMz-R

51Testing软件测试网!J6b0[TkS

   ipcs -q  --查看消息队列信息,具体 man ipcs可以看到更多的内容51Testing软件测试网4Uk \5s8w9UwFng

51Testing软件测试网PSH!z~Nd ^~.M

 51Testing软件测试网UIb_;b/?&E5w&z"p

{u H J d0实际应该当中消息都是通过循环接受处理。一般是服务端-> 建立消息队列 ->循环处理{接受数据  ->处理数据 ->返回处理[可以回写使用不同的消息类型,或者送往发送的消息队列]}n  ->结束处理比如消除队列。

~'K2XN.ZmL0F `,h051Testing软件测试网 my6Hg4[nk,? h

 51Testing软件测试网sA:VQ7v2DQ3Y

51Testing软件测试网IR%gEh-tyO Xt

Refer to:http://blog.chinaunix.net/u1/53810/showart_425856.html

;y'wWP0cC{0

oK5e(z:C]/w];t0http://docs.huihoo.com/joyfire.net/11.html51Testing软件测试网8N6G?/?-am;ew `

4n1g)SK9uU]tEs0http://blog.csdn.net/Miros/archive/2007/09/11/1779993.aspx

$? C;|(x[t6c$W9N0

2OC br!B#G:Fg0http://www.mscto.com/JavaScript/2009010958071.html51Testing软件测试网kF5C&Xzv!N.JNR

!vk T|9Yf/D~5N0 

~yT__mD5M0

TAG: Linux 进程

 

评分:0

我来说两句

Open Toolbar