進程間通信:
對於每個進程來說,都有一份屬於它自己的內存資源,並且獨佔這份內存資源。而進程間通信的目的就是讓不同的進程間能看到一份公共的資源。所有交換的數據必須通過內核來傳遞,在內核中開闢一塊緩衝區,通過這塊緩衝區來實現數據的傳遞,內核提供的這種機制稱爲進程間通信。
進程間通信的方法:1、管道 2、信號量 3、消息隊列 4、共享內存 5、套接字(只有套接字可以跨主機)
匿名管道:pipe(父子間進程的通信方式)
- 頭文件:#include <unsitd.h>
- 函數:int pipe(int fd[2]);
- 參數:fd:文件描述符數組,其中fd[0]指向讀端,fd[1]指向寫端。可以通過read(fd[0])或write(fd[1])操作。
- 返回值:成功返回0,失敗返回-1。
- 意義:調用這個函數,會在內核中開闢出一塊緩衝區來進行進程間的通信,這塊緩衝區稱之爲管道,有一個讀端和一個寫端。
具體步驟:
1、父進程創建管道
2、fork創建子進程,子進程也會得到這兩個文件描述符,指向同一管道
3、父進程關閉讀端(fd[0]),子進程關閉寫端(fd[1])。這樣父進程就可以往管道寫入,子進程可以從子進程讀取。
當進程結束,管道也會自動消失。
代碼實現:
有名管道:fifo
- 函數:int mkfifo(const char *filename,mode_t mode);//在程序裏創建調用函數
- 命令:mkfifo fifo(管道名)//在命令行直接創建
- 參數:文件名和權限
- 特點:不管是否寫入數據,大小均爲0,直接在內存中寫入。沒有數據會阻塞。
大體思路與匿名管道一致。這裏只展示代碼。
總結:
-
管道是半雙工方式(一個讀,一個寫),但管道分不清內容是誰寫的,所以一般固定傳遞方向。
-
管道爲空,read阻塞 管道滿,write阻塞。
-
進程退出,管道釋放,管道的生命週期隨進程。
-
管道的實現依賴於文件系統。管道是內存上的特殊文件。
-
管道的大小一般系統將其限制在最大長度爲4096字節的小型文件。
區分:
-
無名管道pipe()只能在父子進程中使用;有名管道可以在任意兩個進程中使用
-
無名管道:
1、如果寫端關閉,讀端read返回0
2、如果讀端關閉,寫異常,發送信號(write -> SIGPIPE),系統默認關閉寫端。
-
無名管道:優點:簡單方便;缺點:1)侷限於單向通信2)只能創建在它的進程以及其有親緣關係的進程之間;3)緩衝
區有限;
有名管道:優點:可以實現任意關係的進程間的通信;缺點:1)長期存於系統中,使用不當容易出錯;2)緩衝區有限