Linux消息隊(duì)列實(shí)現(xiàn)進(jìn)程間通信實(shí)例詳解
Linux消息隊(duì)列實(shí)現(xiàn)進(jìn)程間通信實(shí)例詳解
一、什么是消息隊(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)。我們可以通過(guò)發(fā)送消息來(lái)避免命名管道的同步和阻塞問(wèn)題。但是消息隊(duì)列與命名管道一樣,每個(gè)數(shù)據(jù)塊都有一個(gè)最大長(zhǎng)度的限制。
Linux用宏MSGMAX和MSGMNB來(lái)限制一條消息的最大長(zhǎng)度和一個(gè)隊(duì)列的最大長(zhǎng)度。
二、在Linux中使用消息隊(duì)列
Linux提供了一系列消息隊(duì)列的函數(shù)接口來(lái)讓我們方便地使用它來(lái)實(shí)現(xiàn)進(jìn)程間的通信。它的用法與其他兩個(gè)System V PIC機(jī)制,即信號(hào)量和共享內(nèi)存相似。
進(jìn)程間通信(IPC):進(jìn)程間通信的本質(zhì)就是通過(guò)讓不同的進(jìn)程看到一份公共的資源來(lái)實(shí)現(xiàn)通信。
常用的進(jìn)程間通信的方式有兩種:通過(guò)管道和systemv標(biāo)準(zhǔn),今天我們來(lái)介紹systemv標(biāo)準(zhǔn)中的一種:消息隊(duì)列
消息隊(duì)列:消息隊(duì)列提供了一種從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送一個(gè)數(shù)據(jù)塊的方法,每個(gè)數(shù)據(jù)塊都認(rèn)為是有一個(gè)類型,接受者進(jìn)程接收的數(shù)據(jù)塊可以有不同的類型值。我們可以通過(guò)發(fā)送消息來(lái)避免命名管道的同步和阻塞問(wèn)題。
特點(diǎn):
(1)消息隊(duì)列可認(rèn)為是全局的一個(gè)鏈表,由消息隊(duì)列標(biāo)識(shí)符進(jìn)行標(biāo)識(shí)。
(2)消息隊(duì)列允許一個(gè)或多個(gè)進(jìn)程寫(xiě)入或讀取消息
(3)消息隊(duì)列的聲明周期隨內(nèi)核
(4)消息隊(duì)列可以實(shí)現(xiàn)雙向通信
創(chuàng)建一個(gè)消息隊(duì)列:msget()
第一個(gè)參數(shù):每一個(gè)消息隊(duì)列都有唯一的key值,可以由ftok()產(chǎn)生
第二個(gè)參數(shù):一般由兩個(gè)選項(xiàng)IPC_CREAT和IPC_EXCL,單獨(dú)使用ipc_creat時(shí),如果消息隊(duì)列不存在則創(chuàng)建一個(gè),如果存在則打開(kāi) IPC_EXCL 如果同時(shí)使用,如果消息隊(duì)列不存在則創(chuàng)建之,如果存在則出錯(cuò)返回。當(dāng)單獨(dú)使用IPC_EXCL時(shí),沒(méi)有意義。
ftok:
參數(shù)可由用戶指定。
下面用代碼實(shí)現(xiàn)消息隊(duì)列的創(chuàng)建:
在創(chuàng)建一個(gè)消息隊(duì)列(其他ipc相同)時(shí),需要先通過(guò)文件路徑名和項(xiàng)目ID獲取一個(gè)鍵值,然后通過(guò)此鍵值由內(nèi)核生成標(biāo)識(shí)符,在以后可通過(guò)此標(biāo)識(shí)符來(lái)使用此消息隊(duì)列。
為什么要有key值和標(biāo)識(shí)符兩個(gè)值呢?
描述符是對(duì)于用戶操作而言的,讓用戶感覺(jué)操作和對(duì)文件的操作相同,key是對(duì)于系統(tǒng)內(nèi)部說(shuō)的。
我們使用ftok來(lái)創(chuàng)建key值,具體可以man一下fotk函數(shù),大概是這樣的:按給定的路徑名取得其stat結(jié)構(gòu),從該結(jié)構(gòu)中取出部分st_dev和st_ino字段,然后再與項(xiàng)目id組合起來(lái),如果兩個(gè)路徑名引用兩個(gè)不同的文件,那么,對(duì)這兩個(gè)路徑名調(diào)用ftok通常返回不同的key值,但是,因?yàn)閕節(jié)點(diǎn)號(hào)和key通常都存放在長(zhǎng)整型中,于是創(chuàng)建key時(shí)可能會(huì)丟失信息,這意味著,如果使用同一項(xiàng)目id,那么對(duì)于不同文件的兩個(gè)路徑名可能產(chǎn)生相同的key值。而標(biāo)識(shí)符是唯一確定的,可以用來(lái)區(qū)別于其他ipc的。
刪除消息隊(duì)列:msgctl()
代碼實(shí)現(xiàn):
發(fā)送消息:msgsnd()
接收消息:magrcv(),這兩個(gè)函數(shù)實(shí)現(xiàn)進(jìn)程間的雙向通信
參數(shù):msqid-消息隊(duì)列標(biāo)識(shí)碼
msgp-指向消息緩沖區(qū)的指針,此位置是用來(lái)暫時(shí)存儲(chǔ)發(fā)送和接收的消息,是一個(gè)用戶可定義的通用結(jié)構(gòu)。
msgtyp-從消息隊(duì)列內(nèi)讀取的消息形態(tài)。如果值為0,則表示消息隊(duì)列中,所有消息被讀取。
msgsz:消息的大小
返回值:成功返回0,失敗則返回-1.
那么如何查看系統(tǒng)中正在運(yùn)行的消息隊(duì)列呢?
介紹兩個(gè)命令:ipcs -q 查看消息隊(duì)列
ipcrm -q msgid 刪除此消息隊(duì)列
相關(guān)文章
Shell腳本中$符號(hào)的嵌套使用方法小結(jié)
在編寫(xiě)Shell腳本時(shí),通過(guò)嵌套使用$符號(hào),間接獲取變量或表達(dá)式的值的具體方法,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2023-05-05Shell+Linux命令實(shí)現(xiàn)日志分析
這篇文章主要介紹了Shell+Linux命令實(shí)現(xiàn)日志分析,本文給出了結(jié)合grep命令、awk命令等實(shí)現(xiàn)了幾個(gè)常用的日志分析統(tǒng)計(jì)長(zhǎng)命令,需要的朋友可以參考下2014-08-08Linux 編程之進(jìn)程fork()詳解及實(shí)例
這篇文章主要介紹了Linux 編程之進(jìn)程fork()詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-03-03centos/rhel下實(shí)現(xiàn)nginx自啟動(dòng)腳本實(shí)例
這篇文章主要介紹了centos/rhel下實(shí)現(xiàn)nginx自啟動(dòng)腳本,需要的朋友可以參考下2014-07-07shell 提取文件名和目錄名的方法實(shí)現(xiàn)
本文主要介紹了shell 提取文件名和目錄名的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02