這樣做微信網(wǎng)站百度代理授權(quán)查詢
Linux下的進(jìn)程通信手段基本上是從Unix平臺上的進(jìn)程通信手段繼承而來的。 而對Unix發(fā)展做出重大貢獻(xiàn)的兩大主力AT&T的貝爾實(shí)驗(yàn)室 以及 BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心), 他們在進(jìn)程間通信方面的側(cè)重點(diǎn)有所不同;
-
前者對Unix早期的進(jìn)程間通信手段進(jìn)行了系統(tǒng)的改進(jìn)和擴(kuò)充, 形成了“system-V IPC”,通信進(jìn)程局限在單個(gè)計(jì)算機(jī)內(nèi)(同一個(gè)設(shè)備的不同進(jìn)程間通訊);
-
而后者則跳過了該限制,形成了基于套接字(socket)的進(jìn)程間通信機(jī)制(多用于不同設(shè)備的進(jìn)程間通訊)。 Linux則把兩者繼承了下來,所以說Linux才是最成功的,既有“system-V IPC”,又支持“socket”。
消息隊(duì)列、共享內(nèi)存 和 信號量?被統(tǒng)稱為 system-V IPC,V 是羅馬數(shù)字5, 是 Unix 的AT&T 分支的其中一個(gè)版本,一般習(xí)慣稱呼他們?yōu)?IPC對象,這些對象的操作接口都比較類似, 在系統(tǒng)中他們都使用一種叫做 key 的鍵值來唯一標(biāo)識,而且他們都是“持續(xù)性”資源——即他們被創(chuàng)建之后, 不會因?yàn)檫M(jìn)程的退出而消失,而會持續(xù)地存在,除非調(diào)用特殊的函數(shù)或者命令刪除他們。
Linux的IPC對象(包括消息隊(duì)列、共享內(nèi)存和信號量)在內(nèi)核內(nèi)部使用鏈表維護(hù), 不同的對象使用?IPC標(biāo)識符
?來標(biāo)識,如消息隊(duì)列標(biāo)識符 msqid、共享內(nèi)存標(biāo)識符 shmid,信號量標(biāo)識符 semid。
對于用戶來說,內(nèi)核提供了簡潔的接口,不同的進(jìn)程通過?IPC關(guān)鍵字(key)
?即可訪問具體的對象。
通過如下命令可以查看系統(tǒng)當(dāng)前的IPC對象,沒有使用的情況下可能為空:
1.?消息隊(duì)列的基本概念
消息隊(duì)列提供了一種從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送一個(gè)數(shù)據(jù)塊的方法。 每個(gè)數(shù)據(jù)塊都被認(rèn)為含有一個(gè)類型,接收進(jìn)程可以獨(dú)立地接收含有不同類型的數(shù)據(jù)結(jié)構(gòu)。 我們可以通過發(fā)送消息來避免命名管道的同步和阻塞問題。
2.?消息隊(duì)列與信號管道的對比
消息隊(duì)列與信號的對比:
-
信號承載的信息量少,而消息隊(duì)列可以承載大量自定義的數(shù)據(jù)。
消息隊(duì)列與管道的對比:
-
消息隊(duì)列跟命名管道有不少的相同之處,它與命名管道一樣,消息隊(duì)列進(jìn)行通信的進(jìn)程可以是不相關(guān)的進(jìn)程, 同時(shí)它們都是通過發(fā)送和接收的方式來傳遞數(shù)據(jù)的。在命名管道中,發(fā)送數(shù)據(jù)用write(),接收數(shù)據(jù)用read(), 則在消息隊(duì)列中,發(fā)送數(shù)據(jù)用msgsnd(),接收數(shù)據(jù)用msgrcv(),消息隊(duì)列對每個(gè)數(shù)據(jù)都有一個(gè)最大長度的限制。
-
消息隊(duì)列也可以獨(dú)立于發(fā)送和接收進(jìn)程而存在,在進(jìn)程終止時(shí),消息隊(duì)列及其內(nèi)容并不會被刪除。
-
管道只能承載無格式字節(jié)流,消息隊(duì)列提供有格式的字節(jié)流,可以減少了開發(fā)人員的工作量。
具體解釋如下:
????????管道是一種進(jìn)程間通信(IPC)機(jī)制,允許一個(gè)進(jìn)程將數(shù)據(jù)寫入管道,另一個(gè)進(jìn)程從管道讀取數(shù)據(jù)。管道只能承載無格式的字節(jié)流,這意味著管道中傳輸?shù)臄?shù)據(jù)是一個(gè)連續(xù)的字節(jié)序列,沒有內(nèi)在的結(jié)構(gòu)或格式信息。開發(fā)人員需要自己定義和解析數(shù)據(jù)的格式,這通常會增加額外的編程工作。
????????無格式字節(jié)流的特征
- 連續(xù)字節(jié)序列:管道中的數(shù)據(jù)只是簡單的字節(jié)流,沒有內(nèi)在的格式。
- 需要自定義協(xié)議:開發(fā)人員需要設(shè)計(jì)數(shù)據(jù)協(xié)議,確保寫入和讀取的數(shù)據(jù)能夠被正確解析。例如,定義消息的起始和結(jié)束標(biāo)記,或者使用固定長度的消息。
- 復(fù)雜性:對于復(fù)雜的通信場景,處理數(shù)據(jù)解析和錯(cuò)誤檢測的代碼會變得復(fù)雜。
????????消息隊(duì)列也是一種IPC機(jī)制,但與管道不同的是,消息隊(duì)列提供了有格式的字節(jié)流。消息隊(duì)列將數(shù)據(jù)組織成獨(dú)立的消息,每條消息都有自己的格式和邊界。操作系統(tǒng)或消息隊(duì)列實(shí)現(xiàn)會自動處理消息的邊界和格式,使得開發(fā)人員無需關(guān)心數(shù)據(jù)的分割和解析問題。
????????有格式字節(jié)流的特征
- 獨(dú)立消息:每條消息都是獨(dú)立的實(shí)體,有明確的邊界和格式。
- 自動處理:消息隊(duì)列系統(tǒng)會自動管理消息的邊界,確保發(fā)送和接收的是完整的消息。
- 簡化開發(fā):開發(fā)人員可以直接發(fā)送和接收完整的消息,無需處理字節(jié)流的分割和解析,減少了開發(fā)工作量。
-
消息隊(duì)列是面向記錄的,其中的消息具有特定的格式以及特定的優(yōu)先級,接收程序可以通過消息類型有選擇地接收數(shù)據(jù), 而不是像命名管道中那樣,只能默認(rèn)地接收。
-
消息隊(duì)列可以實(shí)現(xiàn)消息的隨機(jī)查詢,消息不一定要以先進(jìn)先出的順序接收,也可以按消息的類型接收。
消息隊(duì)列的實(shí)現(xiàn)包括創(chuàng)建或打開消息隊(duì)列、發(fā)送消息、接收消息和控制消息隊(duì)列這4 種操作。
3.?消息隊(duì)列函數(shù)說明
Linux內(nèi)核提供了一系列函數(shù)來使用消息隊(duì)列:
-
其中創(chuàng)建或打開消息隊(duì)列使用的函數(shù)是msgget(),這里創(chuàng)建的消息隊(duì)列的數(shù)量會受到系統(tǒng)可支持的消息隊(duì)列數(shù)量的限制;
-
發(fā)送消息使用的函數(shù)是msgsnd()函數(shù),它把消息發(fā)送到已打開的消息隊(duì)列末尾;
-
接收消息使用的函數(shù)是msgrcv(),它把消息從消息隊(duì)列中取走,與FIFO 不同的是,這里可以指定取走某一條消息;
-
最后控制消息隊(duì)列使用的函數(shù)是msgctl(),它可以完成多項(xiàng)功能。
3.1.?msgget()獲取函數(shù)
收發(fā)消息前需要具體的消息隊(duì)列對象,msgget()函數(shù)的作用是創(chuàng)建或獲取一個(gè)消息隊(duì)列對象, 并返回消息隊(duì)列標(biāo)識符。函數(shù)原型如下:
int msgget(key_t key, int msgflg);
若執(zhí)行成功返回隊(duì)列ID,失敗返回-1。 它的兩個(gè)輸入?yún)?shù)說明如下:
-
key:消息隊(duì)列的關(guān)鍵字值,多個(gè)進(jìn)程可以通過它訪問同一個(gè)消息隊(duì)列。 例如收發(fā)進(jìn)程都使用同一個(gè)鍵值即可使用同一個(gè)消息隊(duì)列進(jìn)行通訊。 其中有個(gè)特殊值IPC_PRIVATE,它用于創(chuàng)建當(dāng)前進(jìn)程的私有消息隊(duì)列。
-
msgflg:表示創(chuàng)建的消息隊(duì)列的模式標(biāo)志參數(shù),主要有IPC_CREAT,IPC_EXCL和權(quán)限mode
-
如果是?
IPC_CREAT
?為真表示:如果內(nèi)核中不存在關(guān)鍵字與key相等的消息隊(duì)列,則新建一個(gè)消息隊(duì)列; 如果存在這樣的消息隊(duì)列,返回此消息隊(duì)列的標(biāo)識符。 -
而如果為?
IPC_CREAT?|?IPC_EXCL
?表示如果內(nèi)核中不存在鍵值與key相等的消息隊(duì)列,則新建一個(gè)消息隊(duì)列; 如果存在這樣的消息隊(duì)列則報(bào)錯(cuò)。 -
mode指IPC對象存取權(quán)限,它使用Linux文件的數(shù)字權(quán)限表示方式,如0600,0666等。
這些參數(shù)是可以通過“|”運(yùn)算符聯(lián)合起來的,因?yàn)樗冀K是int類型的參數(shù)。如msgflag使用參數(shù)?
IPC_CREAT?|?0666
?時(shí)表示, 創(chuàng)建或返回已經(jīng)存在的消息隊(duì)列的標(biāo)識符,且該消息隊(duì)列的存取權(quán)限為0666, 即消息的所有者,所屬組用戶,其他用戶均可對該消息進(jìn)行讀寫。 -
? ? 注意:
選項(xiàng) msgflg 是一個(gè)位掩碼,因此 IPC_CREAT、IPC_EXCL 和權(quán)限 mode 可以用位或的方式疊加起來, 比如:?
msgget(key,?IPC_CREAT?|?0666);
?表示如果 key 對應(yīng)的消息隊(duì)列不存在就創(chuàng)建, 且權(quán)限指定為 0666,若已存在則直接獲取消息隊(duì)列ID,此處的0666使用的是Linux文件權(quán)限的數(shù)字表示方式。權(quán)限只有讀和寫,執(zhí)行權(quán)限是無效的,例如 0777 跟 0666 是等價(jià)的。
當(dāng) key 被指定為 IPC_PRIVATE 時(shí),系統(tǒng)會自動產(chǎn)生一個(gè)未用的 key 來對應(yīng)一個(gè)新的消息隊(duì)列對象, 這個(gè)消息隊(duì)列一般用于進(jìn)程內(nèi)部間的通信。
-
該函數(shù)可能返回以下錯(cuò)誤代碼:
-
EACCES:指定的消息隊(duì)列已存在,但調(diào)用進(jìn)程沒有權(quán)限訪問它
-
EEXIST:key指定的消息隊(duì)列已存在,而msgflg中同時(shí)指定IPC_CREAT和IPC_EXCL標(biāo)志
-
ENOENT:key指定的消息隊(duì)列不存在同時(shí)msgflg中沒有指定IPC_CREAT標(biāo)志
-
ENOMEM:需要建立消息隊(duì)列,但內(nèi)存不足
-
ENOSPC:需要建立消息隊(duì)列,但已達(dá)到系統(tǒng)的限制
-
4.?發(fā)送消息與接收消息
4.1.?msgsnd()發(fā)送函數(shù)
這個(gè)函數(shù)的主要作用就是將消息寫入到消息隊(duì)列,俗稱發(fā)送一個(gè)消息。函數(shù)原型如下:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
參數(shù)說明:
-
msqid:消息隊(duì)列標(biāo)識符。
-
msgp:發(fā)送給隊(duì)列的消息。msgp可以是任何類型的結(jié)構(gòu)體,但第一個(gè)字段必須為long類型, 即表明此發(fā)送消息的類型,msgrcv()函數(shù)則根據(jù)此接收消息。msgp定義的參照格式如下:
/*msgp定義的參照格式*/
struct s_msg{long type; /* 必須大于0,消息類型 */char mtext[1]; /* 消息正文,可以是其他任何類型 */
} msgp;
-
msgsz:要發(fā)送消息的大小,不包含消息類型占用的4個(gè)字節(jié),即mtext的長度。
-
msgflg:如果為0則表示:當(dāng)消息隊(duì)列滿時(shí),msgsnd()函數(shù)將會阻塞,直到消息能寫進(jìn)消息隊(duì)列; 如果為IPC_NOWAIT則表示:當(dāng)消息隊(duì)列已滿的時(shí)候,msgsnd()函數(shù)不等待立即返回; 如果為IPC_NOERROR:若發(fā)送的消息大于size字節(jié),則把該消息截?cái)?#xff0c;截?cái)嗖糠謱⒈粊G棄,且不通知發(fā)送進(jìn)程。
-
返回值:如果成功則返回0,如果失敗則返回-1,并且錯(cuò)誤原因存于error中。錯(cuò)誤代碼:
-
EAGAIN:參數(shù)msgflg設(shè)為IPC_NOWAIT,而消息隊(duì)列已滿。
-
EIDRM:標(biāo)識符為msqid的消息隊(duì)列已被刪除。
-
EACCESS:無權(quán)限寫入消息隊(duì)列。
-
EFAULT:參數(shù)msgp指向無效的內(nèi)存地址。
-
EINTR:隊(duì)列已滿而處于等待情況下被信號中斷。
-
EINVAL:無效的參數(shù)msqid、msgsz或參數(shù)消息類型type小于0。
-
msgsnd()為阻塞函數(shù),當(dāng)消息隊(duì)列容量滿或消息個(gè)數(shù)滿會阻塞。若消息隊(duì)列已被刪除,則返回EIDRM錯(cuò)誤; 若被信號中斷返回E_INTR錯(cuò)誤。
如果設(shè)置IPC_NOWAIT消息隊(duì)列滿或個(gè)數(shù)滿時(shí)會返回-1,并且置EAGAIN錯(cuò)誤。
msgsnd()解除阻塞的條件有以下三個(gè)條件:
-
消息隊(duì)列中有容納該消息的空間。
-
msqid代表的消息隊(duì)列被刪除。
-
調(diào)用msgsnd函數(shù)的進(jìn)程被信號中斷。
4.2.?msgrcv()接收函數(shù)
msgrcv()函數(shù)是從標(biāo)識符為msqid的消息隊(duì)列讀取消息并將消息存儲到msgp中, 讀取后把此消息從消息隊(duì)列中刪除,也就是俗話說的接收消息。函數(shù)原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
參數(shù)說明:
-
msqid:消息隊(duì)列標(biāo)識符。
-
msgp:存放消息的結(jié)構(gòu)體,結(jié)構(gòu)體類型要與msgsnd()函數(shù)發(fā)送的類型相同。
-
msgsz:要接收消息的大小,不包含消息類型占用的4個(gè)字節(jié)。
-
msgtyp有多個(gè)可選的值:如果為0則表示接收第一個(gè)消息,如果大于0則表示接收類型等于msgtyp的第一個(gè)消息, 而如果小于0則表示接收類型等于或者小于msgtyp絕對值的第一個(gè)消息。
-
msgflg用于設(shè)置接收的處理方式,取值情況如下:
-
0: 阻塞式接收消息,沒有該類型的消息msgrcv函數(shù)一直阻塞等待
-
IPC_NOWAIT:若在消息隊(duì)列中并沒有相應(yīng)類型的消息可以接收,則函數(shù)立即返回,此時(shí)錯(cuò)誤碼為ENOMSG
-
IPC_EXCEPT:與msgtype配合使用返回隊(duì)列中第一個(gè)類型不為msgtype的消息
-
IPC_NOERROR:如果隊(duì)列中滿足條件的消息內(nèi)容大于所請求的size字節(jié),則把該消息截?cái)?#xff0c;截?cái)嗖糠謱⒈粊G棄
-
-
返回值:msgrcv()函數(shù)如果接收消息成功則返回實(shí)際讀取到的消息數(shù)據(jù)長度,否則返回-1,錯(cuò)誤原因存于error中。錯(cuò)誤代碼:
-
E2BIG:消息數(shù)據(jù)長度大于msgsz而msgflag沒有設(shè)置IPC_NOERROR
-
EIDRM:標(biāo)識符為msqid的消息隊(duì)列已被刪除
-
EACCESS:無權(quán)限讀取該消息隊(duì)列
-
EFAULT:參數(shù)msgp指向無效的內(nèi)存地址
-
ENOMSG:參數(shù)msgflg設(shè)為IPC_NOWAIT,而消息隊(duì)列中無消息可讀
-
EINTR:等待讀取隊(duì)列內(nèi)的消息情況下被信號中斷
-
msgrcv()函數(shù)解除阻塞的條件也有三個(gè):
-
消息隊(duì)列中有了滿足條件的消息。
-
msqid代表的消息隊(duì)列被刪除。
-
調(diào)用msgrcv()函數(shù)的進(jìn)程被信號中斷。
4.3.?msgctl()操作消息隊(duì)列
消息隊(duì)列是可以被用戶操作的,比如設(shè)置或者獲取消息隊(duì)列的相關(guān)屬性,那么可以通過msgctl()函數(shù)去處理它。函數(shù)原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
參數(shù)說明:
-
msqid:消息隊(duì)列標(biāo)識符。
-
cmd 用于設(shè)置使用什么操作命令,它的取值有多個(gè):
-
IPC_STAT 獲取該 MSG 的信息,獲取到的信息會儲存在結(jié)構(gòu)體 msqid_ds類型的buf中。
-
IPC_SET 設(shè)置消息隊(duì)列的屬性,要設(shè)置的屬性需先存儲在結(jié)構(gòu)體msqid_ds類型的buf中, 可設(shè)置的屬性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,儲存在結(jié)構(gòu)體msqid_ds中。
-
IPC_RMID 立即刪除該 MSG,并且喚醒所有阻塞在該 MSG上的進(jìn)程,同時(shí)忽略第三個(gè)參數(shù)。
-
IPC_INFO 獲得關(guān)于當(dāng)前系統(tǒng)中 MSG 的限制值信息。
-
MSG_INFO 獲得關(guān)于當(dāng)前系統(tǒng)中 MSG 的相關(guān)資源消耗信息。
-
MSG_STAT 同 IPC_STAT,但 msgid為該消息隊(duì)列在內(nèi)核中記錄所有消息隊(duì)列信息的數(shù)組的下標(biāo), 因此通過迭代所有的下標(biāo)可以獲得系統(tǒng)中所有消息隊(duì)列的相關(guān)信息。
-
-
buf:相關(guān)信息結(jié)構(gòu)體緩沖區(qū)。
-
返回值:
-
成功:0
-
出錯(cuò):-1,錯(cuò)誤原因存于error中,錯(cuò)誤代碼:
-
EACCESS:參數(shù)cmd為IPC_STAT,卻無權(quán)限讀取該消息隊(duì)列。
-
EFAULT:參數(shù)buf指向無效的內(nèi)存地址。
-
EIDRM:標(biāo)識符為msqid的消息隊(duì)列已被刪除。
-
EINVAL:無效的參數(shù)cmd或msqid。
-
EPERM:參數(shù)cmd為IPC_SET或IPC_RMID,卻無足夠的權(quán)限執(zhí)行。
-
-
5.?消息隊(duì)列示例
接下來通過示例來講解消息隊(duì)列的使用,使用方法一般是:
發(fā)送者:
-
獲取消息隊(duì)列的 ID
-
將數(shù)據(jù)放入一個(gè)附帶有標(biāo)識的特殊的結(jié)構(gòu)體,發(fā)送給消息隊(duì)列。
接收者:
-
獲取消息隊(duì)列的 ID
-
將指定標(biāo)識的消息讀出。
當(dāng)發(fā)送者和接收者都不再使用消息隊(duì)列時(shí),及時(shí)刪除它以釋放系統(tǒng)資源。
本次實(shí)驗(yàn)主要是兩個(gè)進(jìn)程(無血緣關(guān)系的進(jìn)程)通過消息隊(duì)列進(jìn)行消息的傳遞, 一個(gè)進(jìn)程發(fā)送消息,一個(gè)進(jìn)程接收消息,并將其打印出來。
5.1.?發(fā)送進(jìn)程
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>#define BUFFER_SIZE 512struct message
{long msg_type;char msg_text[BUFFER_SIZE];
};
int main()
{int qid;struct message msg;/*創(chuàng)建消息隊(duì)列*/if ((qid = msgget((key_t)1234, IPC_CREAT|0666)) == -1){perror("msgget\n");exit(1);}printf("Open queue %d\n",qid);while(1){printf("Enter some message to the queue:");if ((fgets(msg.msg_text, BUFFER_SIZE, stdin)) == NULL){printf("\nGet message end.\n");exit(1);}msg.msg_type = getpid();/*添加消息到消息隊(duì)列*/if ((msgsnd(qid, &msg, strlen(msg.msg_text), 0)) < 0){perror("\nSend message error.\n");exit(1);}else{printf("Send message.\n");}if (strncmp(msg.msg_text, "quit", 4) == 0){printf("\nQuit get message.\n");break;}}exit(0);
}
本代碼重點(diǎn)說明如下:
-
第22行,調(diào)用msgget()函數(shù)創(chuàng)建/獲取了一個(gè)key值為1234的消息隊(duì)列,該隊(duì)列的屬性“0666”表示任何人都可讀寫, 創(chuàng)建/獲取到的隊(duì)列ID存儲在變量qid中。
-
第47行,調(diào)用msgsndb()函數(shù)把進(jìn)程號以及前面用戶輸入的字符串,通過msg結(jié)構(gòu)體添加到前面得到的qid隊(duì)列中。
-
第51行,若用戶發(fā)送的消息為quit,那么退出循環(huán)結(jié)束進(jìn)程。
5.2.?接收進(jìn)程
接收進(jìn)程示例如下:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>#define BUFFER_SIZE 512struct message
{long msg_type;char msg_text[BUFFER_SIZE];
};int main()
{int qid;struct message msg;/*創(chuàng)建消息隊(duì)列*/if ((qid = msgget((key_t)1234, IPC_CREAT|0666)) == -1){perror("msgget");exit(1);}printf("Open queue %d\n", qid);do{/*讀取消息隊(duì)列*/memset(msg.msg_text, 0, BUFFER_SIZE);if (msgrcv(qid, (void*)&msg, BUFFER_SIZE, 0, 0) < 0){perror("msgrcv");exit(1);}printf("The message from process %ld : %s", msg.msg_type, msg.msg_text);} while(strncmp(msg.msg_text, "quit", 4));/*從系統(tǒng)內(nèi)核中刪除消息隊(duì)列 */if ((msgctl(qid, IPC_RMID, NULL)) < 0){perror("msgctl");exit(1);}else{printf("Delete msg qid: %d.\n", qid);}exit(0);}
-
第23行,調(diào)用msgget()函數(shù)創(chuàng)建/獲取隊(duì)列qid??梢宰⒁獾?#xff0c;此處跟發(fā)送進(jìn)程是完全一樣的,無論哪個(gè)進(jìn)程先運(yùn)行, 若key值為1234的隊(duì)列不存在則創(chuàng)建,把以實(shí)驗(yàn)時(shí)兩個(gè)進(jìn)程并沒有先后啟動順序的要求。
-
第36行,在循環(huán)中調(diào)用msgrcv()函數(shù)接收qid隊(duì)列的msg結(jié)構(gòu)體消息,此處使用阻塞方式接收, 若隊(duì)列中沒有消息,會停留在本行代碼等待。
-
第47行,若前面接收到用戶的消息為quit,會退出循環(huán),在本行代碼調(diào)用msgctl()刪除消息隊(duì)列并退出本進(jìn)程。
5.3.?編譯及測試
示例代碼分別位于配套代碼倉庫/system_programing/msg/的msg_send及msg_recv目錄下, 將兩個(gè)進(jìn)程編譯出來,分別運(yùn)行即可,實(shí)驗(yàn)現(xiàn)象如下:
5.3.1.?發(fā)送進(jìn)程
在發(fā)送消息進(jìn)程運(yùn)行的時(shí)候,會提示讓你輸入要發(fā)送的消息,隨便什么消息都可以的,使用回車完成消息的輸入。 輸入quit或使用Ctrl+D、Ctrl+C可結(jié)束進(jìn)程。
# 以下操作在 system_programing/msg/msg_send 代碼目錄進(jìn)行
# 編譯X86版本程序發(fā)送進(jìn)程
make
# 運(yùn)行X86版本程序發(fā)送進(jìn)程
./build_x86/msg_send_demo# 輸入消息測試,
Open queue 98345
Enter some message to the queue:embedfire
Send message.
Enter some message to the queue:test
Send message.
Enter some message to the queue:hello world
Send message.
# 發(fā)送quit消息并結(jié)束進(jìn)程
Enter some message to the queue:quit
Send message.Quit get message.
5.3.2.查看消息隊(duì)列
可以通過 ipcs -q 命令來查看系統(tǒng)中存在的消息隊(duì)列,若以上隊(duì)列沒有關(guān)閉,它的查看結(jié)果如下:
# 查詢系統(tǒng)當(dāng)前存在的隊(duì)列
ipcs -q# 以下為輸出:
--------- 消息隊(duì)列 -----------
鍵 msqid 擁有者 權(quán)限 已用字節(jié)數(shù) 消息
0x000004d2 98345 flyleaf 666 0 0# 可查看到key鍵值 0x04d2(1234),qid 98345 與進(jìn)程中創(chuàng)建的一致。
5.3.3.?接收進(jìn)程
打開一個(gè)新終端,編譯及運(yùn)行接收消息進(jìn)程,當(dāng)你從發(fā)送消息進(jìn)程輸入消息時(shí)(按下回車鍵發(fā)送), 接收消息進(jìn)程會打印出你輸入的消息,若無消息則接收進(jìn)程會阻塞等待,接收到quit消息會退出進(jìn)程。
# 以下操作在 system_programing/msg/msg_recv 代碼目錄進(jìn)行
# 編譯X86版本程序發(fā)送進(jìn)程
make
# 運(yùn)行X86版本程序發(fā)送進(jìn)程
./build_x86/msg_recv_demo# 接收到的消息
Open queue 98345
The message from process 21023 : embedfire
The message from process 21023 : test
The message from process 21023 : hello world
The message from process 21023 : quit
Delete msg qid: 98345.
小提示:在本例子中,若發(fā)送進(jìn)程不是通過quit消息退出(如Ctrl+C或Ctrl+D),則不會觸發(fā)接收進(jìn)程主動刪除消息隊(duì)列, 在這種情況下可通過?
ipcs?-q
?命令查看到該消息隊(duì)列依然存在,通過?ipcrm?-q?[消息隊(duì)列qid]
?即可刪除。