Linux系統編程-進程間通信(消息隊列)

      網友投稿 1266 2022-05-30

      前面文章介紹了linux下進程的創建,管理,陸續介紹了進程間通信的方式:管道、內存映射、共享內存等。這篇文章繼續介紹Linux的進程間通信方式消息隊列。

      1. 消息隊列介紹

      消息隊列通過名字字面意思理解就是隊列排隊-和平常超市買東西排隊付款一樣結構,消息隊列與FIFO很相似,都是一個隊列結構,都可以有多個進程往隊列里面寫信息,多個進程從隊列中讀取信息。但FIFO需要讀、寫的兩端事先都打開,才能夠開始信息傳遞工作。而消息隊列可以事先往隊列中寫信息,需要時再打開讀取信息。

      注意事項:

      消息隊列屬于順序隊列形式的結構,向隊列里寫的每一條消息,會追加到隊列后面,讀取一個就從隊列里消除一個。

      寫函數不會阻塞,除非隊列里存放的消息數量已經滿了,才會導致寫阻塞。

      讀函數,從隊列里讀取不到數據時,會阻塞。

      Linux系統編程-進程間通信(消息隊列)

      查看當前系統所有的消息隊列:

      [root@wbyq 20181005]# ipcs -q ------ Message Queues -------- 鍵值 消息隊列ID 使用的字節數量 隊里現存的消息數量 key msqid owner perms used-bytes messages 0x000004d3 0 root 666 65532 192 0x00003044 32769 root 666 65424 564 0x0a120534 65538 root 0 2352 21 0x0a00000f 196611 root 0 65520 2730 0xffffffff 163844 root 0 0 0

      查看消息隊列的詳細信息:

      [root@wbyq 20181005]# ipcs -l ------ Shared Memory Limits -------- max number of segments = 4096 max seg size (kbytes) = 4194303 max total shared memory (kbytes) = 1073741824 min seg size (bytes) = 1 ------ Semaphore Limits -------- max number of arrays = 128 max semaphores per array = 250 max semaphores system wide = 32000 max ops per semop call = 32 semaphore max value = 32767 ------ Messages: Limits -------- max queues system wide = 1736 【系統最多的消息隊列數量(最多支持同時1736個消息隊列)】 max size of message (bytes) = 65536 【單個消息的最大字節數】 default max size of queue (bytes) = 65536 【默認的單個隊列的大小65536】 默認單個隊列總字節大小為: 65535字節。 消息隊列的最大字節數量和消息的最大條數加起來的總字節數不能超過65535字節。

      **System V IPC機制消息隊列相關的函數接口: ** 這里先列出所有函數,下面會詳細介紹每個函數的用法。

      #include #include #include int msgget(key_t key, int msgflg); int msgsnd(int msqid, struct msgbuf * msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, struct msgbuf * msgp, size_t msgsz, long msgtyp, int msgflg); int msgctl(int msqid, int cmd, struct msqid_ds * buf);

      2. 消息隊列相關函數介紹

      2.1 msgget函數

      函數原型:

      #include #include #include int msgget(key_t key, int msgflg);

      功能

      msgget用于創建和訪問一個消息隊列。

      參數

      (1) key:是唯一標識一個消息隊列的關鍵字,如果為IPC_PRIVATE(值為0,用創建一個只有創建者進程才可以訪問的消息隊列),表示創建一個只由調用進程使用的消息隊列,非0值的key(可以通過ftok函數獲得)表示創建一個可以被多個進程共享的消息隊列;

      (2) msgflg:指明隊列的訪問權限和創建標志,創建標志的可選值為IPC_CREAT和IPC_EXC,如果單獨指定IPC_CREAT,msgget要么返回新創建的消息隊列id,要么返回具有相同key值的消息隊列id;如果IPC_EXCL和IPC_CREAT同時指明,則要么創建新的消息隊列,要么當隊列存在時,調用失敗并返回-1。

      /*1. 創建消息隊列*/ int msgid = msgget((key_t)1235,0666 | IPC_CREAT);

      返回值

      成功執行時,返回消息隊列標識值(0也是成功的)。

      失敗返回-1,errno被設為以下的某個值。

      EACCES:指定的消息隊列已存在,但調用進程沒有權限訪問它,而且不擁有CAP_IPC_OWNER權能 EEXIST:key指定的消息隊列已存在,而msgflg中同時指定IPC_CREAT和IPC_EXCL標志 ENOENT:key指定的消息隊列不存在同時msgflg中不指定IPC_CREAT標志 ENOMEM:需要建立消息隊列,但內存不足 ENOSPC:需要建立消息隊列,但已達到系統的最大消息隊列容量

      2.2 msgsnd和msgrcy函數

      原型:

      #include #include #include 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);

      功能

      函數msgsnd和msgrcy用來將消息添加到消息隊列中和從一個消息隊列中獲取信息。

      參數

      (1)msgid:指明消息隊列的ID; 通常是msgget函數成功的返回值。

      (2)msgbuf:是消息結構體,它的長度必須小于系統規定的上限,必須以一個長整型成員變量開始,接收函數將用這個成員變量來確定消息的類型。必須重寫這個結構體,其中第一個參數類型不能改,其他可以自定義。

      如下:

      struct msgbuf { long mtype; /* type of message */ char mtext[1]; /* message text */ };

      字段mtype是用戶自己指定的消息類型(通常是1—5中的任意一個數值),該結構體第2個成員僅僅是一種說明性的結構,實際上用戶可以使用任何類型的數據,就是消息內容;

      (3)msgsz是消息體的大小,每個消息體最大不要超過4K; 不含消息類型占用的4個字節,即mtext的長度

      (4)msgtyp有3種選項:

      ```cpp

      msgtyp == 0 接收隊列中的第1個消息,不區分消息類型

      msgtyp > 0 接收對列中的第1個類型等于msgtyp的消息

      msgtyp < 0 接收其類型小于或等于msgtyp絕對值的第1個最低類型消息

      ```

      (5)msgflg有3種選項:

      0:當消息隊列滿時,msgsnd將會阻塞,直到消息能寫進消息隊列 IPC_NOWAIT:當消息隊列已滿的時候,msgsnd函數不等待立即返回 IPC_NOERROR:若發送的消息大于size字節,則把該消息截斷,截斷部分將被丟棄,且不通知發送進程。

      2.3 msgctl函數

      原型:

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

      功能

      msgctl是消息隊列的控制函數,常用來刪除消息隊列。

      參數

      (1)msqid:由msgget返回的消息隊列標識符。

      (2)cmd:通常為IPC_RMID表示刪除消息隊列。

      (3)參數buf通常為NULL。

      通過命令查看系統消息信息

      (1)ipcs -q 命令查看系統的消息隊列

      (2)ipcs -m查看系統的共享內存

      (3)ipcs -s 查看系統的信號量集。

      3. 案例代碼: 消息隊列示例1

      下面兩個程序分別編譯,依次運行,不分先后順序,就可以看到效果了。

      3.1 發送消息

      #include #include #include #include #include #include #include #include #define BUFFER 255 struct msgtype { //重新定義該結構體 long mtype; //第一個參數類型不變 char buf[BUFFER]; }; int main(int argc,char **argv) { if(argc!=3) { printf("./app <消息> <消息類型-整數>\n"); return 0; } /*1. 創建消息隊列*/ int msgid = msgget((key_t)1235,0666 | IPC_CREAT); /*2. 向消息隊列發送消息*/ struct msgtype msg; memset(&msg,0,sizeof(struct msgtype)); msg.mtype = atoi(argv[2]); //給結構體的成員賦值 strncpy(msg.buf,argv[1],BUFFER); msgsnd(msgid,&msg,sizeof(struct msgtype),0); return 0; }

      3.2 讀取消息

      #include #include #include #include #include #include #include #include #include #define BUFFER 255 struct msgtype { long mtype; char buf[BUFFER]; }; int main(int argc,char **argv) { if(argc!=2) { printf("./app <消息類型-整數>\n"); return 0; } /*1. 創建消息隊列-如果存在就打開消息隊列*/ int msgid = msgget((key_t)1235, 0666 | IPC_CREAT); //獲得消息隊列 struct msgtype msg; memset(&msg,0,sizeof(struct msgtype)); while(1) { /*2. 從消息隊列里讀取指定消息類型*/ msgrcv(msgid,&msg,sizeof(struct msgtype),atoi(argv[1]),0); printf("讀取的消息: %s\n", msg.buf); } return 0; }

      4. 案例代碼: 消息隊列基本使用

      下面兩個例子,一個例子用于創建隊列,并向隊列里寫數據,另一個例子從隊列里讀取數據。

      4.1 向隊列寫入消息

      程序運行需要傳入兩個額外的參數。一個是消息的類型,一個是具體的內容。

      ./app 1 hello ./app 2 123456789

      示例代碼:

      #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1024]; /* message data */ }; int main(int argc,char **argv) { if(argc!=3) { printf("./app <消息類型> <消息內容>\n"); return 0; } /*1. 創建消息隊列*/ int msqid=msgget(123456,0666|IPC_CREAT); /*2. 向消息隊列里加入數據*/ struct msgbuf msg_buf; msg_buf.mtype=atoi(argv[1]); //消息類型 1、2、3、4、5 strcpy(msg_buf.mtext,argv[2]); //消息內容 msgsnd(msqid,&msg_buf,sizeof(struct msgbuf),0); printf("消息發送成功:%s,%s\n",argv[1],argv[2]); return 0; }

      4.2 從隊列讀取消息

      #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1024]; /* message data */ }; int main(int argc,char **argv) { if(argc!=2) { printf("./app <消息類型>\n"); return 0; } /*1. 創建消息隊列*/ int msqid=msgget(123456,0666|IPC_CREAT); /*2. 從消息隊列里取出數據*/ struct msgbuf msg_buf; msgrcv(msqid,&msg_buf,sizeof(struct msgbuf),atoi(argv[1]),0); printf("消息讀取成功:%d,%s\n",msg_buf.mtype,msg_buf.mtext); return 0; }

      Linux 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Java內存區域
      下一篇:《TCP/IP詳解 卷2:實現》 —2.9 m_copy和簇引用計數
      相關文章
      亚洲综合精品一二三区在线| 亚洲黑人嫩小videos| 亚洲日本中文字幕天堂网| 亚洲人成在线播放| 国产亚洲高清不卡在线观看| 亚洲国产精品一区二区九九| 亚洲精品蜜夜内射| 国产亚洲精品成人AA片| 亚洲熟妇少妇任你躁在线观看| 亚洲国产韩国一区二区| 亚洲午夜电影在线观看| 亚洲一级片在线观看| 亚洲国产日韩综合久久精品| 亚洲日产乱码一二三区别| 亚洲国产精品无码久久98| MM1313亚洲国产精品| 亚洲AⅤ无码一区二区三区在线| 亚洲av色香蕉一区二区三区 | 亚洲天天在线日亚洲洲精| 亚洲精选在线观看| 亚洲精品视频专区| 亚洲国产精品久久网午夜| 亚洲sss综合天堂久久久| 亚洲愉拍一区二区三区| 亚洲AV噜噜一区二区三区| 亚洲精品国产精品国自产观看 | 亚洲日产2021三区在线 | 亚洲精品中文字幕乱码三区| 亚洲AV无码国产精品色午友在线 | 国产精品亚洲综合| 亚洲中文字幕无码专区| 国产精品亚洲片在线观看不卡| 亚洲AV区无码字幕中文色| 亚洲综合无码一区二区三区| 亚洲国产91在线| 久久精品熟女亚洲av麻豆| 国产精品亚洲综合一区| 亚洲av无码成人黄网站在线观看 | 亚洲一区二区视频在线观看| 日韩一卡2卡3卡4卡新区亚洲| 亚洲AV中文无码字幕色三|