UNP(卷2:進程間通信)—— 第6章:System V消息隊列

System V 消息隊列使用消息隊列標識符(Message Queue Identifier)。具有足夠特權的任何進程都可以往一個給定進程放置一個消息。也可以讀出一個消息。跟Posix消息隊列一樣,在寫消息之前,不求另外某個進程正在等待該隊列上一個消息的到達。

對於每個消息隊列,內核維護一個定義在<sys/msg.h>頭文件中的信息結構。

struct msqid_ds {
    struct ipc_perm   msg_perm;   /* read_write perms */
    struct msg       *msg_first;  /* first message on queue,unused  */
    struct msg       *msg_last;   /* last message in queue,unused */
    time_t            msg_stime;  /* last msgsnd time */
    time_t            msg_rtime;  /* last msgrcv time */
    time_t            msg_ctime;  /* last change time */
    unsigned long  msg_lcbytes;   /* Reuse junk fields for 32 bit */
    unsigned long  msg_lqbytes;   /* ditto */
    msglen_t          msg_cbytes; /* current number of bytes on queue */
    msgqnum_t         msg_qnum;   /* number of messages in queue */
    msglen_t          msg_qbytes; /* max number of bytes on queue */
    pid_t             msg_lspid;  /* pid of last msgsnd */
    pid_t             msg_lrpid;  /* last receive pid */
};


msgget

創建一個新的消息隊列或者訪問一個已存在的消息隊列。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);
                                      // 返回:若成功則爲非負標識符,出錯爲-1
key:既可以是ftok的返回值,也可以是常值IPC_PRIVATE。

msgflg:讀寫權限位的組合(MSG_R、MSG_W),還可以與  IPC_CREATE、IPC_CREATE | IPC_EXCL 按爲或。

當創建一個新的消息隊列時,msqid_ds結構的如下成員被初始化:
(1)msg_perm結構的uid和cuid成員被設置成當前進程的有效用戶ID,gid和cgid成員被設置成當前進程的有效組ID
(2)msgflg中的讀寫權限位存放在msg_perm.mode中
(3)msg_qnum,msg_lspid,msg_lrpid,msg_stime,msg_rtime被置爲0
(4)msg_ctime被設置成當前時間
(5)msg_qbytes被設置成系統限制值


msgsnd、msgrcv

msgsnd使用msgget打開一個消息隊列後,使用msgsnd往其上放置一個消息。

msgrcv從某個消息隊列中讀出一個消息。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
                                                                      // 返回:若成功則爲0,出錯-1

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
                                                                      // 返回:若成功則爲讀入緩衝區中的數據的字節數,出錯-1

struct msgbuf {
    long mtype;      /* message type, must be > 0 */
    char mtext[1];    /* message data */
};

--------------------------------------  msgsnd -----------------------------------------  

msqid:由msgget返回的標識符。

msgp:結構指針,msgbuf。通常一個字節的數據是不夠用的,可以自定義。

msgflg:可以是0,可以是IPC_NOWAIT(使得msgsnd調用非阻塞nonblocking,如果沒有存放新消息的可用空間,就立馬返回)。

  • 在指定的隊列中已有太多的字節;
  • 在系統範圍存在太多的消息。

如果這兩個條件有一個存在,而且IPC_NOWAIT已指定,msgsnd就返回一個EAGAIN錯誤。如果有一個存在,且未指定IPC_NOWAIT標誌,那麼調用線程被投入睡眠,直到:

  • 具備存放新消息的空間;
  • 由msqid標識的消息隊列從系統中刪除(返回EIDRM錯誤);
  • 調用線程被某個信號所中斷(返回EINTR錯誤。)

------------------------------------ msgrcv -----------------------------------------------

msgtyp:指定希望讀出什麼樣的消息。

  • type == 0: 表示將會返回隊列中的第一個消息。
  • type > 0 : 表示將會返回隊列中消息類型的值等於type參數的第一個消息。
  • type < 0 : 表示將會返回隊列中小於或者等於type的絕對值中最小的第一個消息。

msgflg指定所請求的消息不在隊列時的處理。在沒有消息可得的情況下,如果設置了IPC_NOWAIT位,立即返回一個ENOMSG錯誤,否則阻塞到下列某個事件發生爲止
(1)有一個所請求類型的消息可獲取
(2)由msqid標識的消息隊列被從系統中刪除
(3)調用線程被某個捕獲的信號所中斷
msgflg參數中另有一位可以指定MSG_NOERROR,當所接收消息的真正數據部分大於length參數時,如果設置了該位,msgrcv函數只是截短數據部分,而不返回錯誤,否則,返回一個E2BIG錯誤。


msgctl

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
                                                         // 返回:若成功則爲0,出錯-1
msgctl提供在一個消息隊列上的各種控制操作。

有三個命令:
(1)IPC_RMID:  從系統中刪除msqid指定的消息隊列。當前在該隊列上的任何消息都被丟棄
(2)IPC_SET  :  給隊列設置其中的msqid_ds結構的四個成員:msg_perm.uid, msg_perm.gid, msg_perm.mode和msg_qbytes
(3)IPC_STAT:  給調用者返回指定隊列的當前msqid_ds結構

複用消息

  與一個隊列中的每個消息相關聯的類型字段提供了兩個特性:

(1)類型字段可以用於標識消息,從而允許多個進程在單個隊列上複用消息。

(2)類型字段可以用做優先級,允許接收者以不同於先進先出的某個順序讀出各個消息。


限制






















發佈了98 篇原創文章 · 獲贊 74 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章