【正文】
int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg)。該系統(tǒng)調用從msgid代表的消息隊列中讀取一個消息,并把消息存儲在msgp指向的msgbuf結構中。msqid為消息隊列描述字;消息返回后存儲在msgp指向的地址,msgsz指定msgbuf的mtext成員的長度(即消息內容的長度),msgtyp為請求讀取的消息類型;讀消息標志msgflg可以為以下幾個常值的或: IPC_NOWAIT 如果沒有滿足條件的消息,調用立即返回,此時,errno=ENOMSG IPC_EXCEPT 與msgtyp0配合使用,返回隊列中第一個類型不為msgtyp的消息 IPC_NOERROR 如果隊列中滿足條件的消息內容大于所請求的msgsz字節(jié),則把該消息截斷,截斷部分將丟失。 msgrcv手冊中詳細給出了消息類型取不同值時(0。 0。 =0),調用將返回消息隊列中的哪個消息。msgrcv()解除阻塞的條件有三個:1. 消息隊列中有了滿足條件的消息; 2. msqid代表的消息隊列被刪除; 3. 調用msgrcv()的進程被信號中斷; 調用返回:成功返回讀出消息的實際字節(jié)數(shù),否則返回1。3)int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg)。向msgid代表的消息隊列發(fā)送一個消息,即將發(fā)送的消息存儲在msgp指向的msgbuf結構中,消息的大小由msgze指定。對發(fā)送消息來說,有意義的msgflg標志為IPC_NOWAIT,指明在消息隊列沒有足夠空間容納要發(fā)送的消息時,msgsnd是否等待。造成msgsnd()等待的條件有兩種: 當前消息的大小與當前消息隊列中的字節(jié)數(shù)之和超過了消息隊列的總容量; 當前消息隊列的消息數(shù)(單位個)不小于消息隊列的總容量(單位字節(jié)數(shù)),此時,雖然消息隊列中的消息數(shù)目很多,但基本上都只有一個字節(jié)。 msgsnd()解除阻塞的條件有三個: 1. 不滿足上述兩個條件,即消息隊列中有容納該消息的空間; 2. msqid代表的消息隊列被刪除; 3. 調用msgsnd()的進程被信號中斷; 調用返回:成功返回0,否則返回1。4)int msgctl(int msqid, int cmd, struct msqid_ds *buf)。該系統(tǒng)調用對由msqid標識的消息隊列執(zhí)行cmd操作,共有三種cmd操作:IPC_STAT、IPC_SET 、IPC_RMID。1. IPC_STAT:該命令用來獲取消息隊列信息,返回的信息存貯在buf指向的msqid結構中; 2. IPC_SET:該命令用來設置消息隊列的屬性,要設置的屬性存儲在buf指向的msqid結構中;可設置屬性包括:、同時,也影響msg_ctime成員。 3. IPC_RMID:刪除msqid標識的消息隊列; 調用返回:成功返回0,否則返回1。三、消息隊列的限制每個消息隊列的容量(所能容納的字節(jié)數(shù))都有限制,該值因系統(tǒng)不同而不同。在后面的應用實例中,輸出了redhat ,結果參見附錄 3。另一個限制是每個消息隊列所能容納的最大消息數(shù):在redhad ,該限制是受消息隊列容量制約的:消息個數(shù)要小于消息隊列的容量(字節(jié)數(shù))。注:上述兩個限制是針對每個消息隊列而言的,系統(tǒng)對消息隊列的限制還有系統(tǒng)范圍內的最大消息隊列個數(shù),以及整個系統(tǒng)范圍內的最大消息數(shù)。一般來說,實際開發(fā)過程中不會超過這個限制。四、消息隊列應用實例消息隊列應用相對較簡單,下面實例基本上覆蓋了對消息隊列的所有操作,同時,程序輸出結果有助于加深對前面所講的某些規(guī)則及消息隊列限制的理解。include sys/include sys/include void msg_stat(int,struct msqid_ds )。main(){int gflags,sflags,rflags。key_t key。int msgid。int reval。struct msgsbuf{ int mtype。 char mtext[1]。 }msg_sbuf。struct msgmbuf { int mtype。 char mtext[10]。 }msg_rbuf。struct msqid_ds msg_ginfo,msg_sinfo。char* msgpath=/unix/msgqueue。key=ftok(msgpath,39。a39。)。gflags=IPC_CREAT|IPC_EXCL。msgid=msgget(key,gflags|00666)。if(msgid==1){ printf(msg create error\n)。 return。}//創(chuàng)建一個消息隊列后,輸出消息隊列缺省屬性msg_stat(msgid,msg_ginfo)。sflags=IPC_NOWAIT。=10。[0]=39。a39。reval=msgsnd(msgid,amp。msg_sbuf,sizeof(),sflags)。if(reval==1){ printf(message send error\n)。}//發(fā)送一個消息后,輸出消息隊列屬性msg_stat(msgid,msg_ginfo)。rflags=IPC_NOWAIT|MSG_NOERROR。reval=msgrcv(msgid,amp。msg_rbuf,4,10,rflags)。if(reval==1) printf(read msg error\n)。else printf(read from msg queue %d bytes\n,reval)。//從消息隊列中讀出消息后,輸出消息隊列屬性msg_stat(msgid,msg_ginfo)。=8。//just a try=8。//=16388。//此處驗證超級用戶可以更改消息隊列的缺省msg_qbytes//注意這里設置的值大于缺省值reval=msgctl(msgid,IPC_SET,amp。msg_sinfo)。if(reval==1){ printf(msg set info error\n)。 return。}msg_stat(msgid,msg_ginfo)。//驗證設置消息隊列屬性reval=msgctl(msgid,IPC_RMID,NULL)。//刪除消息隊列if(reval==1){ printf(unlink msg queue error\n)。 return。}}void msg_stat(int msgid,struct msqid_ds msg_info){int reval。sleep(1)。//只是為了后面輸出時間的方便reval=msgctl(msgid,IPC_STAT,amp。msg_info)。if(reval==1){ printf(get msg info error\n)。 return。}printf(\n)。printf(current number of bytes on queue is %d\n,)。printf(number of messages in queue is %d\n,)。printf(max number of bytes on queue is %d\n,)。//每個消息隊列的容量(字節(jié)數(shù))都有限制MSGMNB,值的大小因系統(tǒng)而異。在創(chuàng)建新的消息隊列時,//msg_qbytes的缺省值就是MSGMNBprintf(pid of last msgsnd is %d\n,)。printf(pid of last msgrcv is %d\n,)。printf(last msgsnd time is %s, ctime(amp。()))。printf(last msgrcv time is %s, ctime(amp。()))。printf(last change time is %s, ctime(amp。()))。printf(msg uid is %d\n,)。printf(msg gid is %d\n,)。}程序輸出結果見附錄 3。小結:消息隊列與管道以及有名管道相比,具有更大的靈活性,首先,它提供有格式字節(jié)流,有利于減少開發(fā)人員的工作量;其次,消息具有類型,在實際應用中,可作為優(yōu)先級使用。這兩點是管道以及有名管道所不能比的。同樣,消息隊列可以在幾個進程間復用,而不管這幾個進程是否具有親緣關系,這一點與有名管道很相似;但消息隊列是隨內核持續(xù)的,與有名管道(隨進程持續(xù))相比