Linux訊息佇列實踐(1),linux訊息佇列實踐
訊息佇列基本概念
訊息佇列提供了一個從一個進程向另外一個進程發送一塊資料的方法(僅局限與本機)
每個資料區塊都被認為是有一個類型,接收者進程接收的資料區塊可以有不同的類型值
訊息佇列也有管道一樣的不足,就是每個訊息的最大長度是有上限的(MSGMAX),每個訊息佇列的總的位元組數是有上限的(MSGMNB),系統上訊息佇列的總數也有一個上限(MSGMNI)
管道 vs. 訊息佇列:
管道:流管道 訊息:有邊界
先進先出 可以後進入、先出來
訊息佇列大小三大限制
cat /proc/sys/kernel/msgmax #最大訊息長度限制
cat /proc/sys/kernel/msgmnb #訊息佇列總的位元組數
cat /proc/sys/kernel/msgmni #訊息條目數
IPC對象資料結構
核心為每個IPC對象維護一個資料結構
[cpp] view plaincopy
- struct ipc_perm
- {
- key_t __key; /* Key supplied to msgget(2) */
- uid_t uid; /* Effective UID of owner */
- gid_t gid; /* Effective GID of owner */
- uid_t cuid; /* Effective UID of creator */
- gid_t cgid; /* Effective GID of creator */
- unsigned short mode; /* Permissions */
- unsigned short __seq; /* Sequence number */
- };
訊息佇列特有的結構
[cpp] view plaincopy
- struct msqid_ds
- {
- struct ipc_perm msg_perm; /* Ownership and permissions */
- time_t msg_stime; /* Time of last msgsnd(2) */
- time_t msg_rtime; /* Time of last msgrcv(2) */
- time_t msg_ctime; /* Time of last change */
- unsigned long __msg_cbytes; /* Current number of bytes in
- queue (nonstandard) */
- msgqnum_t msg_qnum; /* Current number of messages
- in queue */
- msglen_t msg_qbytes; /* Maximum number of bytes
- allowed in queue */
- pid_t msg_lspid; /* PID of last msgsnd(2) */
- pid_t msg_lrpid; /* PID of last msgrcv(2) */
- };
訊息佇列在核心中的表示
訊息佇列函數樣本
msgget函數
功能:用來建立和訪問一個訊息佇列
原型:
[cpp] view plaincopy
- int msgget(key_t key, int msgflg);
參數:
key: 某個訊息佇列的名字
msgflg:由九個許可權標誌構成,如0644,它們的用法和建立檔案時使用的mode模式標誌是一樣的(但是訊息佇列沒有x(執行)許可權)
傳回值:
成功返回訊息佇列編號,即該訊息佇列的標識碼;失敗返回-1
編程實踐
[cpp] view plaincopy
- //實踐1: IPC_PRIVATE:宏,值為0
- int main()
- {
- //IPC_PRIVATE每次建立的訊息佇列的描述符都是不同的!
- //因此,計時MessageID(key)傳送給其他進程(除非有關聯的進程),
- //其他進程也無法使用該訊息佇列(血緣fork除外)
- int msgid = msgget(IPC_PRIVATE,0666);
- if (msgid < 0)
- {
- //如果訊息佇列不存在,則開啟錯誤,errno=ENOENT
- if (errno == ENOENT)
- {
- cout << "ENOENT" << endl;
- }
- err_exit("mesget error");
- }
- else
- {
- cout << "msgid = " << msgid << endl;
- }
-
- return 0;
- }
- /**
- IPC_PRIVATE建立的訊息佇列,只能用在與當前進程有關係的進程中使用!
- */
[cpp] view plaincopy
- //實踐2: IPC_CREAT
- int main()
- {
- //指定IPC_CREAT,則一定會建立訊息佇列
- int msgid = msgget(0x1235,0666|IPC_CREAT);
- if (msgid < 0)
- {
- //如果訊息佇列不存在,則開啟錯誤,errno=ENOENT
- if (errno == ENOENT)
- {
- cout << "ENOENT" << endl;
- }
- err_exit("mesget error");
- }
- else
- {
- cout << "msgid = " << msgid << endl;
- }
-
- return 0;
- }
[cpp] view plaincopy
- //實踐3: IPC_CREAT|IPC_EXCL
- int main()
- {
- //指定IPC_EXCL, 如果已經存在,則報告檔案已經存在(錯誤)
- int msgid = msgget(0x1235,0666|IPC_CREAT|IPC_EXCL);
- if (msgid < 0)
- {
- err_exit("mesget error");
- }
- else
- {
- cout << "msgid = " << msgid << endl;
- }
-
- return 0;
- }
[cpp] view plaincopy
- //實踐4:低許可權建立,高許可權開啟
- int main()
- {
- //低許可權建立
- int msgid = msgget(0x255,0444 | IPC_CREAT);
- if (msgid < 0)
- {
- err_exit("mesget error");
- }
- else
- {
- cout << "Create Mes OK, msgid = " << msgid << endl;
- }
-
- //高許可權開啟
- msgid = msgget(0x255,0644 | IPC_CREAT);
- if (msgid < 0)
- {
- err_exit("mesget error");
- }
- else
- {
- cout << "Create Mes OK, msgid = " << msgid << endl;
- }
-
- return 0;
- }
msgget函數參數關係圖