天天看點

Linux IPC實踐(7) --Posix消息隊列

1. 建立/擷取一個消息隊列

參數:

   name:  消息隊列名字;

   oflag: 與open函數類型, 可以是O_RDONLY, O_WRONLY, O_RDWR, 還可以按位或上O_CREAT, O_EXCL, O_NONBLOCK.

   mode: 如果oflag指定了O_CREAT, 需要指定mode參數;

   attr: 指定消息隊列的屬性;

傳回值:

   成功: 傳回消息隊列檔案描述符;

   失敗: 傳回-1;

注意-Posix IPC名字限制:

   1. 必須以”/”開頭, 并且後面不能還有”/”, 形如:/file-name;

   2. 名字長度不能超過NAME_MAX

   3. 連結時:Link with -lrt.

/** System V 消息隊列

通過msgget來建立/打開消息隊列

int msgget(key_t key, int msgflg);

**/

2. 關閉一個消息隊列

3. 删除一個消息隊列

4. 擷取/設定消息隊列屬性

   newattr: 需要設定的屬性

   oldattr: 原來的屬性

通過msgctl函數, 并将cmd指定為IPC_STAT/IPC_SET來實作

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

5. 發送消息

   msg_ptr: 指向需要發送的消息的指針

   msg_len: 消息長度

   msg_prio: 消息的優先級

通過msgsnd函數來實作消息發送

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

6. 從消息隊列中讀取消息

  msg_len: 讀取的消息的長度, 注意: 此值一定要等于mq_attr::mq_msgsize的值, 該值可以通過mq_getattr擷取, 但一般是8192位元組     [this must be greater than the mq_msgsize attribute of the queue (see mq_getattr(3)).]

  msg_prio: 儲存擷取的消息的優先級

  成功: 傳回讀取的消息的位元組數

  失敗: 傳回-1

  注意: 讀取的永遠是消息隊列中優先級最高的最早的消息, 如果消息隊列為, 如果不指定為非阻塞模式, 則mq_receive會阻塞;

通過msgrcv函數來實作消息發送的

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

7. 建立/删除消息到達通知事件

參數sevp:

   NULL: 表示撤銷已注冊通知;

   非空: 表示當消息到達且消息隊列目前為空, 那麼将得到通知;

通知方式:

   1. 産生一個信号, 需要自己綁定

   2. 建立一個線程, 執行指定的函數

注意: 這種注冊的方式隻是在消息隊列從空到非空時才産生消息通知事件, 而且這種注冊方式是一次性的!

sigev_notify代表通知的方式: 一般常用兩種取值:SIGEV_SIGNAL, 以信号方式通知; SIGEV_THREAD, 以線程方式通知

如果以信号方式通知: 則需要設定一下兩個參數:

   sigev_signo: 信号的代碼

   sigev_value: 信号的附加資料(實時信号)

如果以線程方式通知: 則需要設定以下兩個參數:

   sigev_notify_function

   sigev_notify_attributes

/** Posix IPC所特有的功能, System V沒有 **/

mq_notify 注意點總結:

   1. 任何時刻隻能有一個程序可以被注冊為接收某個給定隊列的通知;

   2. 當有一個消息到達某個先前為空的隊列, 而且已有一個程序被注冊為接收該隊列的通知時, 隻有沒有任何線程阻塞在該隊列的mq_receive調用的前提下, 通知才會發出;

   3. 當通知被發送給它的注冊程序時, 該程序的注冊被撤銷. 程序必須再次調用mq_notify以重新注冊(如果需要的話),但是要注意: 重新注冊要放在從消息隊列讀出消息之前而不是之後(如同示例程式);

附-檢視已經成功建立的Posix消息隊列

#其存在與一個虛拟檔案系統中, 需要将其挂載到系統中才能檢視

  Mounting the message queue filesystem On Linux, message queues are created in a virtual filesystem.  

(Other implementations may also  provide such a feature, but the details are likely to differ.)  This 

file system can be mounted (by the superuser, 注意是使用root使用者才能成功) using the following commands:

mkdir /dev/mqueue

mount -t mqueue none /dev/mqueue

還可以使用cat檢視該消息隊列的狀态, rm删除:

cat /dev/mqueue/abc 

rm abc

還可umount該檔案系統

umount /dev/mqueue

附-Makefile

繼續閱讀