您好,登錄后才能下訂單哦!
本篇內容介紹了“Linux編程消息隊列相關的函數有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
消息隊列本質上是位于內核空間的鏈表,鏈表的每個節點都是一條消息。每一條消息都有自己的消息類型,消息類型用整數來表示,而且必須大于 0。每種類型的消息都被對應的鏈表所維護:
其中數字 1 表示類型為 1 的消息,數字2、3、4 類似。彩色塊表示消息數據,它們被掛在對應類型的鏈表上。
值得注意的是,剛剛說過沒有消息類型為 0 的消息,實際上,消息類型為 0 的鏈表記錄了所有消息加入隊列的順序,其中紅色箭頭表示消息加入的順序。
// 創建和獲取 ipc 內核對象 int msgget(key_t key, int flags); // 將消息發送到消息隊列 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); // 從消息隊列獲取消息 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); // 查看、設置、刪除 ipc 內核對象(用法和 shmctl 一樣) int msgctl(int msqid, int cmd, struct msqid_ds *buf);
無論你是發送還是接收消息,消息的格式都必須按照規范來。簡單的說,它一般長成下面這個樣子:
struct Msg{ long type; // 消息類型。這個是必須的,而且值必須 > 0,這個值被系統使用 // 消息正文,多少字節隨你而定 // ... };
所以,只要你保證首4字節(32 位 linux 下的 long)是一個整數就行了。 舉個例子:
struct Msg { long type; char name[20]; int age; } msg; struct Msg { long type; int start; int end; } msg;
從上面可以看出,正文部分是什么數據類型都沒關系,因為消息隊列傳遞的是 2 進制數據,不一定非得是文本。
msgsnd 函數用于將數據發送到消息隊列。如果該函數被信號打斷,會設置 errno 為 EINTR。
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
參數 msqid:ipc 內核對象 id 參數 msgp:消息數據地址 參數 msgsz:消息正文部分的大小(不包含消息類型) 參數 msgflg:可選項 該值為 0:如果消息隊列空間不夠,msgsnd 會阻塞。 IPC_NOWAIT:直接返回,如果空間不夠,會設置 errno 為 EAGIN.
返回值:0 表示成功,-1 失敗并設置 errno。
msgrcv 函數從消息隊列取出消息后,并將其從消息隊列里刪除。
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
參數 msqid:ipc 內核對象 id 參數 msgp:用來接收消息數據地址 參數 msgsz:消息正文部分的大小(不包含消息類型) 參數 msgtyp:指定獲取哪種類型的消息
msgtyp = 0:獲取消息隊列中的第一條消息 msgtyp > 0:獲取類型為 msgtyp 的第一條消息,除非指定了 msgflg 為MSG_EXCEPT,這表示獲取除了 msgtyp 類型以外的第一條消息。 msgtyp 0 的情況。表示獲取類型不為 msgtyp 的消息 MSG_NOERROR:如果消息數據正文內容大于 msgsz,就將消息數據截斷為 msgsz
程序 msg_send 和 msg_recv 分別用于向消息隊列發送數據和接收數據。
msg_send 程序定義了一個結構體 Msg,消息正文部分是結構體 Person。該程序向消息隊列發送了 10 條消息。 msg_send.c
#include #include #include #include #include typedef struct { char name[20]; int age; }Person; typedef struct { long type; Person person; }Msg; int main(int argc, char *argv) { int id = msgget(0x8888, IPC_CREAT | 0664); Msg msg[10] = { {1, {"Luffy", 17}}, {1, {"Zoro", 19}}, {2, {"Nami", 18}}, {2, {"Usopo", 17}}, {1, {"Sanji", 19}}, {3, {"Chopper", 15}}, {4, {"Robin", 28}}, {4, {"Franky", 34}}, {5, {"Brook", 88}}, {6, {"Sunny", 2}} }; int i; for (i = 0; i 程序 msg_send 第一次運行完后,內核中的消息隊列大概像下面這樣:6.2 msg_recvmsg_recv 程序接收一個參數,表示接收哪種類型的消息。比如./msg_recv 4 表示接收類型為 4 的消息,并打印在屏幕。 #include #include #include #include #include #include #include typedef struct { char name[20]; int age; }Person; typedef struct { long type; Person person; }Msg; void printMsg(Msg *msg) { printf("{ type = %ld, name = %s, age = %d }\n", msg->type, msg->person.name, msg->person.age); } int main(int argc, char *argv[]) { if (argc \n", argv[0]); return -1; } // 要獲取的消息類型 long type = atol(argv[1]); // 獲取 ipc 內核對象 id int id = msgget(0x8888, 0); Msg msg; int res; while(1) { // 以非阻塞的方式接收類型為 type 的消息 res = msgrcv(id, &msg, sizeof(Person), type, IPC_NOWAIT); if (res 6.3 編譯 [root@localhost ~]# gcc msg_send.c -o msg_send [root@localhost ~]# gcc msg_recv.c -o msg_recv6.4 運行先運行 msg_send,再運行 msg_recv。 接收所有消息image.png接收類型為 4 的消息image.pngmsgctl函數獲取和設置消息隊列的屬性 int msgctl(int msqid, int cmd, struct msqid_ds *buf);msqid:消息隊列標識符 cmd:控制指令 IPC_STAT:獲得msgid的消息隊列頭數據到buf中 IPC_SET:設置消息隊列的屬性,要設置的屬性需先存儲在buf中,可設置的屬性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes buf:消息隊列管理結構體。返回值: 成功:0 出錯:-1,錯誤原因存于error中 EACCESS:參數cmd為IPC_STAT,確無權限讀取該消息隊列 EFAULT:參數buf指向無效的內存地址 EIDRM:標識符為msqid的消息隊列已被刪除 EINVAL:無效的參數cmd或msqid EPERM:參數cmd為IPC_SET或IPC_RMID,卻無足夠的權限執行實例 #include #include #include #include #include #include struct msgbuf{ long mtype ; char mtext[] ; } ; int main(int argc, char **argv){ int msqid ; struct msqid_ds info ; struct msgbuf buf ; struct msgbuf buf1 ; int flag ; int sendlength, recvlength ; msqid = msgget( IPC_PRIVATE, 0666 ) ; if ( msqid
“Linux編程消息隊列相關的函數有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。