您好,登錄后才能下訂單哦!
Linux系統(tǒng)進程通信的主要方式是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
進程間通信常見方式如下:
管道
FIFO
消息隊列
信號量
共享內存
UNXI域套接字
套接字(Socket)
管道是一種古老的IPC通信形式。它有兩個特點:
半雙工,即不能同時在兩個方向上傳輸數據。有的系統(tǒng)可能支持全雙工。
只能在父子進程間。經典的形式就是管道由父進程創(chuàng)建,進程fork子進程之后,就可以在父子進程之間使用了。
使用popen函數和pclose函數結合來執(zhí)行系統(tǒng)命令,就用到了管道,它們聲明如下:
FILE *popen(const char *command,const char *type); int pclose(FILE *stream);
system()函數雖然也能夠執(zhí)行系統(tǒng)命令,但是無法獲取執(zhí)行狀態(tài)碼,而執(zhí)行系統(tǒng)命令本質上就需要創(chuàng)建子進程來完成,因此利用管道可以很方便的獲取子進程的輸出內容。本文不詳細展開。
我們看一個簡單的使用管道的例子,這里使用了pipe函數來創(chuàng)建管道:
#include #include #include #define MAX_LEN 128 int main(void) { /*0為讀,1為寫*/ int fd[2] = {0}; //描述符 pid_t pid = 0; char line[MAX_LEN] = {0}; int n = 0; /*創(chuàng)建管道,需要傳入兩個文件描述符*/ if(pipe(fd) 0) { /*關閉管道的寫描述符*/ close(fd[1]); /*從管道讀取數據*/ n = read(fd[0],line,MAX_LEN); printf("read %d bytes from pipe :%s\n",n,line); } /*子進程*/ else { /*關閉管道的讀描述符*/ close(fd[0]); /*向管道寫入數據*/ write(fd[1],"www.yanbinghu.com",sizeof("www.yanbinghu.com")); } return 0; }
在程序中,我們創(chuàng)建了一個管道,父進程關閉了寫通道,子進程關閉讀通道;子進程向管道內寫入字符串,而父進程從管道中讀取字符串并輸出。
運行結果:
read 18 bytes from pipe :www.yanbinghu.com
FIFO也被稱為命名管道,與管道不同的是,不相關的進程也能夠進行數據交換。
涉及FIFO操作主要函數為:
int mkfifo(const char *path, mode_t mode);
而FIFO也常常有以下兩個用途:
無需創(chuàng)建中間臨時文件,復制輸出流
多客戶-服務進程應用中,通過FIFO作為匯聚點,傳輸客戶進程和服務進程之間的數據
我們看一個簡單的例子,寫進程代碼如下:
#include #include #include #include #include #include #define FIFO "/tmp/fifo" #define MAX_LEN 128 int main(void) { int writeFd; char line[MAX_LEN] = {0}; if(mkfifo(FIFO,S_IRUSR|S_IWUSR)它首先創(chuàng)建了一個FIFO,并且打開后,往里面寫入字符串,然后關閉退出。讀進程代碼如下: #include #include #include #include #include #include #define FIFO "/tmp/fifo" #define MAX_LEN 128 int main(void) { int readFd,n; char line[MAX_LEN] = {0}; /*打開FIFO,這里打開可能失敗,應該要對返回值處理*/ readFd = open(FIFO,O_RDONLY,0); /*從FIFO讀取數據*/ n = read(readFd,line,MAX_LEN); printf("read %d bytes from pipe :%s\n",n,line); close(readFd); /*刪除FIFO*/ unlink(FIFO); return 0; }它先打開一個已知的FIFO,然后從FIFO中讀取數據。 在一個終端先運行寫進程,然后運行讀進程。
兩個沒有親緣關系的進程可以通過FIFO進行通信。消息隊列消息隊列可以認為是一個消息鏈表,存儲在內核中,進程可以從中讀寫數據。與管道和FIFO不同,進程可以在沒有另外一個進程等待讀的情況下進行寫。另外一方面,管道和FIFO一旦相關進程都關閉并退出后,里面的數據也就沒有了,但是對于消息隊列,一個進程往消息隊列中寫入數據后退出,另外一個進程仍然可以打開并讀取消息。消息隊列與后面介紹的UNIX域套接字相比,在速度上沒有多少優(yōu)勢。信號量信號量是一個計數器,它主要用在多個進程需要對共享數據進行訪問的時候。
考慮這一的情況,不能同時有兩個進程對同一數據進行訪問,那么借助信號量就可以完成這樣的事情。它的主要流程如下:檢查控制該資源的信號量如果信號量值大于0,則資源可用,并且將其減1,表示當前已被使用如果信號量值為0,則進程休眠直至信號量值大于0也就是說,它實際上是提供了一個不同進程或者進程的不同線程之間訪問同步的手段。共享內存共享內存允許多個進程共享一個給定的存儲區(qū),由于它們是共享一塊內存數據,因此其速度非??臁5切枰硗馓峁┦侄蝸肀WC共享內存的同步訪問,例如它可以用到前面所提到的信號量來實現訪問同步。UNIX域套接字UNIX域套接字和套接字很相似,但是它有更高的效率,因為它不需要執(zhí)行協(xié)議處理,例如計算校驗和,發(fā)送確認報文等等,它僅僅復制數據。當然,它也只適用于同一臺計算機上的進程間通信。例如redis服務配置unixsocket啟動后,通過redis-cli的-s參數就可以指定UNIX域套接字,連接到redis服務器。 $ redis-cli -s /tmp/redis.sock
redis /tmp/redis.sock>它會比使用網絡套接字的速度要快。
網絡套接字這個不用多說,它利用網絡進行通信,與前面所提到的通信方式不同的是,它能用于不同計算機之間的不同進程間通信??偨Y本文簡單介紹了進程間通信的常見方式,其中對管道和命名管道我們使用了一個例子來簡單說明,因為我們可能會經常見到它。對于FIFO,最后一個引用它的進程終止時,留在FIFO的數據也將會被刪除,而對于消息隊列卻不是這樣,它會一直留到被顯示刪除或者系統(tǒng)自舉,另外消息隊列于其他方式相比并沒有特別的優(yōu)勢。而信號量實際上常用于共享數據的同步訪問。共享內存在進程間傳遞數據非常高效,但是系統(tǒng)沒有對訪問進行同步,因此還需要另外實現數據的訪問同步。套接字(socket)是應該目前應用最廣泛的進程間通信方式。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。