溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Linux編程消息隊列相關(guān)的函數(shù)有哪些

發(fā)布時間:2022-01-27 14:38:41 來源:億速云 閱讀:115 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“Linux編程消息隊列相關(guān)的函數(shù)有哪些”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

1、消息隊列簡介

消息隊列本質(zhì)上是位于內(nèi)核空間的鏈表,鏈表的每個節(jié)點都是一條消息。每一條消息都有自己的消息類型,消息類型用整數(shù)來表示,而且必須大于 0。每種類型的消息都被對應(yīng)的鏈表所維護(hù):

Linux編程消息隊列相關(guān)的函數(shù)有哪些

其中數(shù)字 1 表示類型為 1 的消息,數(shù)字2、3、4 類似。彩色塊表示消息數(shù)據(jù),它們被掛在對應(yīng)類型的鏈表上。

值得注意的是,剛剛說過沒有消息類型為 0 的消息,實際上,消息類型為 0 的鏈表記錄了所有消息加入隊列的順序,其中紅色箭頭表示消息加入的順序。

2、消息隊列相關(guān)的函數(shù)

 // 創(chuàng)建和獲取 ipc 內(nèi)核對象
 int msgget(key_t key, int flags);
 // 將消息發(fā)送到消息隊列
 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);
 // 查看、設(shè)置、刪除 ipc 內(nèi)核對象(用法和 shmctl 一樣)
 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
3、消息數(shù)據(jù)格式

無論你是發(fā)送還是接收消息,消息的格式都必須按照規(guī)范來。簡單的說,它一般長成下面這個樣子:

 struct Msg{
     long type; // 消息類型。這個是必須的,而且值必須 > 0,這個值被系統(tǒng)使用
     // 消息正文,多少字節(jié)隨你而定
     // ...
 };

所以,只要你保證首4字節(jié)(32 位 linux 下的 long)是一個整數(shù)就行了。 舉個例子:

 struct Msg {
     long type;
     char name[20];
     int age;
 } msg;
 
 struct Msg {
     long type;
     int start;
     int end;
 } msg;

從上面可以看出,正文部分是什么數(shù)據(jù)類型都沒關(guān)系,因為消息隊列傳遞的是 2 進(jìn)制數(shù)據(jù),不一定非得是文本。

4、msgsnd 函數(shù)

msgsnd 函數(shù)用于將數(shù)據(jù)發(fā)送到消息隊列。如果該函數(shù)被信號打斷,會設(shè)置 errno 為 EINTR。

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

參數(shù) msqid:ipc 內(nèi)核對象 id 參數(shù) msgp:消息數(shù)據(jù)地址 參數(shù) msgsz:消息正文部分的大?。ú话㈩愋停?參數(shù) msgflg:可選項 該值為 0:如果消息隊列空間不夠,msgsnd 會阻塞。 IPC_NOWAIT:直接返回,如果空間不夠,會設(shè)置 errno 為 EAGIN.

返回值:0 表示成功,-1 失敗并設(shè)置 errno。

5、msgrcv 函數(shù)

msgrcv 函數(shù)從消息隊列取出消息后,并將其從消息隊列里刪除。

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

參數(shù) msqid:ipc 內(nèi)核對象 id 參數(shù) msgp:用來接收消息數(shù)據(jù)地址 參數(shù) msgsz:消息正文部分的大?。ú话㈩愋停?參數(shù) msgtyp:指定獲取哪種類型的消息

msgtyp = 0:獲取消息隊列中的第一條消息 msgtyp > 0:獲取類型為 msgtyp 的第一條消息,除非指定了 msgflg 為MSG_EXCEPT,這表示獲取除了 msgtyp 類型以外的第一條消息。 msgtyp  0 的情況。表示獲取類型不為 msgtyp 的消息 MSG_NOERROR:如果消息數(shù)據(jù)正文內(nèi)容大于 msgsz,就將消息數(shù)據(jù)截斷為 msgsz

6、實例

程序 msg_send 和 msg_recv 分別用于向消息隊列發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。

6.1 msg_send

msg_send 程序定義了一個結(jié)構(gòu)體 Msg,消息正文部分是結(jié)構(gòu)體 Person。該程序向消息隊列發(fā)送了 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 第一次運行完后,內(nèi)核中的消息隊列大概像下面這樣:6.2 msg_recvmsg_recv 程序接收一個參數(shù),表示接收哪種類型的消息。比如./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 內(nèi)核對象 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函數(shù)獲取和設(shè)置消息隊列的屬性 int msgctl(int msqid, int cmd, struct msqid_ds *buf);msqid:消息隊列標(biāo)識符 cmd:控制指令 IPC_STAT:獲得msgid的消息隊列頭數(shù)據(jù)到buf中 IPC_SET:設(shè)置消息隊列的屬性,要設(shè)置的屬性需先存儲在buf中,可設(shè)置的屬性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes buf:消息隊列管理結(jié)構(gòu)體。返回值: 成功:0 出錯:-1,錯誤原因存于error中 EACCESS:參數(shù)cmd為IPC_STAT,確無權(quán)限讀取該消息隊列 EFAULT:參數(shù)buf指向無效的內(nèi)存地址 EIDRM:標(biāo)識符為msqid的消息隊列已被刪除 EINVAL:無效的參數(shù)cmd或msqid EPERM:參數(shù)cmd為IPC_SET或IPC_RMID,卻無足夠的權(quán)限執(zhí)行實例 #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編程消息隊列相關(guān)的函數(shù)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI