進程間通訊之消息隊列

消息隊列是消息的連接表,存放在內核中並由消息隊列標識符標識。在本節中,咱們把消息隊列簡稱爲隊列(queue),其標識符爲隊列ID(queue ID)。html

msgget用於建立一個新隊列或打開一個現存的隊列msgsnd將新消息添加到隊列尾端。每一個消息包含一個正長整型類型字段,一個非負長度以及實際數據字節(對應於長度),全部這些都在將消息添加到隊列時,傳送給msgsnd。msgrcv用於從隊列中取消息。咱們並不必定要以先進先出次序取消息,也能夠按消息的類型字段取消息。編程

每一個隊列都有一個msgqid_ds結構與其相關聯:服務器

struct msqid_ds {
    struct ipc_perm    msg_perm;      /* http://www.cnblogs.com/nufangrensheng/p/3561681.html */
    msgqnum_t          msg_qnum;      /* # of messages on queue */
    msglen_t           msg_qbytes;    /* max # of bytes no queue */
    pid_t              msg_lspid;     /* pid of last msgsnd() */
    pid_t              msg_lrpid;     /* pid of last msgrcv() */
    time_t             msg_stime;     /* last-msgsnd() time */
    time_t             msg_rtime;     /* last-msgrcv() time */
    time_t             msg_ctime;     /* last-change time */
    ...
};

此結構規定了隊列的當前狀態。結構中所示的各成員是由Single UNIX Specification定義的。具體實現可能包括標準中沒有定義的另外一些字段。函數

調用的第一個函數一般是msgget,其功能是打開一個現存隊列或建立一個新隊列。學習

#include <sys/msg.h>
int msgget(key_t key, int flag);
返回值:若成功則返回消息隊列ID,若出錯則返回-1

http://www.cnblogs.com/nufangrensheng/p/3561681.html中標識符和鍵部分,說明了將key變換成一個標識符的規則,而且討論是否建立一個新隊列或訪問一個現存隊列。ui

當建立一個新隊列時,初始化msqid_ds結構的下列成員:spa

若執行成功,msgget返回非負隊列ID。此後,該值就可被用於其餘三個消息隊列函數(msgsnd、msgrcv和msgctl)。指針

msgctl函數對隊列執行多種操做。它和另外兩個與信號量和共享存儲有關的函數(semctl和shmctl)是XSI IPC的相似於ioctl的函數(亦即垃圾桶函數)。code

#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
返回值:若成功則返回0,若出錯則返回-1

cmd參數說明對由msqid指定的隊列要執行的命令:htm

IPC_STAT    取此隊列的msqid_ds結構,並將它存放在buf指向的結構中。

IPC_SET      按由buf指定結構中的值,設置與此隊列相關結構中的下列四個字段:msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes。此命令只能由下列兩種進程執行:一種是其有效用戶ID等於msg_perm.cuid或msg_perm.uid;另外一種是具備超級用戶特權的進程。只有超級用戶才能增長msg_qbytes的值。

IPC_RMID    從系統中刪除該消息隊列以及仍在該隊列中的全部數據。這種刪除當即生效。仍在使用這一消息隊列的其餘進程在它們下一次試圖對此隊列進行操做時,將出錯返回EIDRM。此命令只能由下列兩種進程執行:一種是其有效用戶ID等於msg_perm.cuid或msg_perm.uid;另外一種是具備超級用戶特權的進程。

這三條命令(IPC_STAT、IPC_STAT和IPC_RMID)也可用於信號量和共享存儲。

調用msgsnd將數據放到消息隊列中。

#include <sys/msg.h>
int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);
返回值:若成功則返回0,若出錯則返回-1

每一個消息都由三部分組成,它們是:正長整型類型字段、非負長度(nbytes)以及實際數據字節(對應於長度)。消息老是放在隊列尾端

ptr參數指向一個長整型數,它包含了正的整型消息類型,在其後緊跟着消息數據。(若nbytes是0,則無消息數據。)若發送的最長消息是512字節,則可定義下列結構:

struct mymesg {
    long    mtype;         /* positive message type */
    char    mtext[512];    /* message data, of length nbytes */
};

因而,ptr就是一個指向mymesg結構的指針。接收者可使用消息類型以非先進先出的次序取消息。

參數flag的值能夠指定爲IPC_NOWAIT。這相似於文件I/O的非阻塞I/O標誌(見http://www.cnblogs.com/nufangrensheng/p/3544997.html)。若消息隊列已滿(或者是隊列中的消息總數等於系統限制值,或隊列中的字節總數等於系統限制值),則指定IPC_NOWAIT使得msgsnd當即出錯返回EAGAIN。若是沒有指定IPC_NOWAIT,則進程阻塞直到下述狀況出現爲止:有空間能夠容納要發送的消息;從系統中刪除了此隊列;或捕捉到一個信號,並從信號處理程序返回。在第二種狀況下,返回EIDRM(「標識符被刪除」)。最後一種狀況則返回EINTR。

注意,對刪除消息隊列的處理不是很完善。由於對每一個消息隊列並無設置一個引用計數器(對打開文件則有這種計數器),因此刪除一個隊列會形成仍在使用這一隊列的進程在下次對隊列進行操做時出錯返回。信號量機制也以一樣的方式處理其刪除。相反,刪除一個文件時,要等到使用該文件的最後一個進程關閉了它的文件描述符後,才能刪除文件中的內容。

當msgsnd成功返回,與消息隊列相關的msqid_ds結構獲得更新,以代表發出該調用的進程ID(msg_lspid)、進行該調用的時間(msg_stime),並指示隊列中增長了一條消息(msg_qnum)。

msgrcv從隊列中取用消息:

#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag);
返回值:若成功則返回消息的數據部分的長度,若出錯則返回-1

如同msgsnd中同樣,ptr參數指向一個長整型數(返回的消息類型存放在其中),跟隨其後的是存放實際消息數據的緩衝區。nbytes說明數據緩衝區的長度。若返回的消息大於nbytes,並且在flag中設置了MSG_NOERROR,則該消息被截短。(在這種狀況下,不通知咱們消息截短了,消息的截去部分被丟棄。)若是沒有設置這一標誌,而消息又太長,則出錯返回E2BIG(消息仍留在隊列中)。

參數type使咱們能夠指定想要哪種消息:

type == 0    返回隊列中的第一個消息。

type > 0      返回隊列中消息類型爲type的第一個消息。

type < 0      返回隊列中消息類型值小於或等於type絕對值的消息,若是這種消息有若干個,則取類型值最小的消息。

type值非0用於以非先進先出次序讀消息。例如,若應用程序對消息賦優先權,那麼type就能夠是優先權值。若是一個消息隊列由多個客戶進程和一個服務器進程使用,那麼type字段能夠用來包含客戶進程的進程ID(只要進程ID能夠存放在長整型中)。

能夠指定flag值爲IPC_NOWAIT,使操做不阻塞。這使得若是沒有所指定類型的消息,則msgrcv返回-1,errno設置爲ENOMSG。若是沒有指定IPC_NOWAIT,則進程阻塞直至以下狀況出現才終止:有了指定類型的消息;從系統中刪除了此隊列(出錯則返回-1且errno設置爲EIDRM);或捕捉到一個信號並從信號處理程序返回(msgrcv返回-1,errno設置爲EINTR)。

msgrcv成功執行時,內核更新與該消息隊列相關聯的msqid_ds結構,以指示調用者的進程ID(msg_lrpid)和調用時間(msg_rtime),並將隊列中的消息數(msg_qnum)減1。

 

消息隊列原來的實施目的是提供比通常IPC更高速度的進程通訊方法,但如今與其餘形式的IPC相比,在速度方面已經沒有什麼差異了。考慮到使用消息隊列具備的問題(見http://www.cnblogs.com/nufangrensheng/p/3561681.html中優勢和缺點部分),咱們得出的結論是,在新的應用程序中不該當再使用它們

本篇博文內容摘自《UNIX環境高級編程》(第二版),僅做我的學習記錄所用。關於本書可參考:http://www.apuebook.com/

相關文章
相關標籤/搜索