轉載自:https://blog.csdn.net/ifwecande/article/details/107470579
管道
操作系統分為內核態和用戶態,管道就是在內核中開辟一塊緩沖區,不同的進程通過對這個緩沖取進行讀寫操作實現IPC。
管道其實有三種不同的形式,
- 匿名管道,半雙工通信,只能在父子或者兄弟進程間使用.,
- 命令流管道s_pipe: 全雙工。父子兄弟間使用。
- 命名管道FIFO:半雙工通信。任意進程間使用。
下面對匿名管道和命名管道進行詳細介紹。
匿名管道
匿名管道是在內核中開辟一塊緩沖區,而這塊緩沖取沒有具體的標識符,因此只能用於具有親緣關系的進程間通信。
子進程可以通過復制父進程獲得這塊緩沖取(管道)的操作句柄,因為父進程創建管道的時候會接收到管道的操作句柄(文件描述符)。
這也是linux下一切皆文件的一種體現。
使用pipe函數進行創建:
int pipe(
由參數fd返回兩個文件描述符,fd[0]為讀而打開 fd[1]為寫而打開
通過這兩個讀寫的端口就輕松實現了同步與互斥。
關於匿名管道需要注意的是管道的讀寫特性:
- 管道無數據,調用read阻塞
- 管道數據滿了,調用write阻塞
- 管道所有讀端被關閉,繼續調用寫會導致異常進程退出
- 管道所有寫端被關閉,繼續調用讀,當讀完管道中數據的時候,會返回0
命名管道
命名管道也是內核中的一塊緩沖區,但是這塊緩沖區有具體的標識符,不同進程可以通過標識符來對管道進行操作,從而達到通信的目的。
可以通過命令 mkfifo創建管道文件。
也可以通過代碼 int mkfifo(char* filename , mode_t mode)
參數一是管道文件名,參數二是創建文件的一些權限,與IO操作類似
成功返回0,失敗返回-1.
注意:當我們通過open打開這個命名管道時,
- 若文件以只讀方式打開則會阻塞直到以只寫方式打開。
- 若文件以只寫方式打卡則會阻塞直到以只讀方式打卡。
總結管道特性。
- 管道是半雙工通信
- 匿名讀寫特性與命名管道的打開特性。
- 生命周期隨進程(當沒有手動釋放時)
- 管道提供字節傳輸服務 – 可靠,有序,基於連接的傳輸服務。
- 自帶同步與互斥。
同步:通過條件判斷實現對臨界資源操作的合理性。
互斥:通過唯一訪問實現對臨界資源操作的安全性。
共享內存
共享內存的最大特性: 最快的進程間通信方式。
共享內存的本質是直接在物理空間上開辟的一塊物理內存,而非pcb的虛擬內存,多個進程可以將自己的虛擬地址映射到這塊內存上面從而達到通信的目的,相比於其他方式,很明顯,這種方式有效的降低了輸入輸出數據的拷貝次數,從而降低了效率。
映射方式如圖: 中間是共享內存,兩邊分別是不同的進程通過頁表映射。
共享內存的操作流程:
- 創建共享內存 – 在物理內存上開辟空間。
- 進程將自己的共享內存映射到自己的虛擬地址空間。
- 進行基本的IO操作
- 操作完畢,接觸映射關系
- 釋放內存空間。
共享內存沒有同步與互斥,因此需要用戶手動去添加。否則多進程訪問時可能會出現安全問題。