消息隊列
概述
$消息隊列是消息的鏈接表,包括Posix 消息隊列systemV 消息隊列。系統V消息隊列是隨內核持續的,只有在內核重起或人工刪除時,該消息隊列才會被刪除。目前被大量使
用。
$用戶可以從消息隊列中添加和讀取消息。具有一定的FIFO特性,但可以實現消息的隨機查詢
$這些消息存在于內核中,由“隊列ID”來標識
¨消息隊列的實現
$消息隊列的實現包括創建和打開消息隊列、添加消息、讀取消息和控制消息隊列
$創建或打開消息隊列:msgget。這里創建的消息隊列的數量會受到消息隊列數量的
限制
$添加消息:msgsnd函數,它把消息添加到已打開的消息隊列末尾
$讀取消息:msgrcv,它把消息從隊列中取走,與FIFO不同的是,這里可以指定取走
某一條消息
$控制消息隊列:msgctl
有關的數據結構:
Øipc_perm:IPC對象的訪問權限
Ømsgbuf:消息的數據類型
Ømsg:消息鏈表的節點結構
Ømsgqid_ds:消息隊列對象的結構
消息隊列相關函數: *****
#include
#include
#include
int msgget(key_t key, int flg);
入參: key:和消息隊列關聯的key值
flg:消息隊列的訪問權限
IPC_CREAT、創建新的消息隊列
IPC_EXCL,與IPC_CREAT一起使用;如果要創建的消息隊列已經存在,則返
回錯誤
IPC_NOWAIT讀寫消息隊列要求無法得到滿足時,不阻塞。
返回值: 成功 返回消息隊列 ID
失敗 -1
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息隊列發送消息
入參: msqid:消息隊列的ID 即msgget的返回值
msgp:指向消息的指針。常用消息結構msgbuf如下:
struct msgbuf
{
long mtype;
//消息類型
char mtext[N]
//消息正文
};
msgsz:發送的消息正文的字節數
msgflg: IPC_NOWAIT 消息沒發送完立即返回
0 消息發送完成函數才會返回
返回值:
成功 0
失敗 -1
int msgrcv(int msgid, void* msgp, size_t size, long msgtype, int flag); 功能: 從msqid代表的消息隊列中讀取一個msgtyp類型的消息,并把消息存儲在msgp指向的msgbuf結構中。在成功讀取了一條消息以后,隊列中的這條消息將被刪除入參: msqid:消息隊列的ID
msgp:接收消息的緩沖區
size:要接收的消息的正文字節數
msgtype: 0 :接收消息隊列中第一個消息
>0: 接收mtype為msgtype第一個消息
<0: 接收消息隊列中mtype不小于msgtype的絕對值,
且mtype最小的消息
flag: 0: 沒有收到消息就會一直阻塞
IPC_NOWAIT :沒有收到消息會立即返回
返回值: 成功:接收到的消息的長度
失敗:-1
int msgctl ( int msgqid, int cmd, struct msqid_ds *buf ); 入參: msqid:消息隊列的隊列ID
cmd: IPC_STAT:讀取消息隊列的屬性,并將其保存在buf指向的緩
沖區中。
IPC_SET:設置消息隊列的屬性。這個值取自buf參數
IPC_RMID:從系統中刪除消息隊列。,buf 填NULL
buf:消息隊列緩沖區
返回值: 成功 0
失敗 -1
信號燈集(signal set):由一個或多個信號量構成的集合
#include
#include
#include
int semget(key_t key, int nsems, int semflg);//創建信號量入參: key ftok獲取的key值
nsems 信號燈集中包含的信號燈數目
semflg:同消息隊列
返回值: 成功:信號燈集的ID號(IPC標識符)
失敗 -1
int semop ( int semid, struct sembuf *opsptr, size_t nops); 入參: semid semget的返回值,ID號
opsptr :結構體指針,指明對哪個信號燈進行操作 nops: 要操作的信號燈的個數
struct sembuf
{
short
sem_num;
//
要操作的信號燈的編號
short
sem_op;
0 :
等待,直到信號燈的值變成0
1 : 釋放資源,V操作
short
sem_flg;
// 0,
-1 : 分配資源,P操作
IPC_NOWAIT, SEM_UNDO
};
返回值:
成功 0
失敗 -1
int semctl ( int semid, int semnum, int cmd…/*union semun arg*/); 入參: semid: 信號燈集的ID號
semnum: 要修改的信號燈編號
cmd: GETVAL:獲取信號燈的值
SETVAL:設置信號燈的值
IPC_RMID:從系統中刪除信號燈集合
注意:semctl是可變參數函數:cmd為GETVAL或SETVAL時,需要傳遞第四個參數。參數類型為union semun
成功: 0 失敗 : -1
union semun
{
int val; /* value for SETVAL */
structsemid_ds *buf;/* buffer for IPC_STAT & IPC_SET */
unsigned short*array;/* array for GETALL & SETALL */
structseminfo*__buf;/* buffer for IPC_INFO */
void *__pad;
};
頭文件中的#ifndef
千萬不要忽略了頭件的中的#ifndef,這是一個很關鍵的東西。比如你有兩個C文件,這兩個C文件都include了同一個頭文件。而編譯時,這兩個C文件要一同編譯成一個可運行文件,于是問題來了,大量的聲明沖突。
還是把頭文件的內容都放在#ifndef和#endif中吧。不管你的頭文件會不會被多個文件引用,你都要加上這個。一般格式是這樣的:
#ifndef <標識>
#define <標識>
......
......
#endif