在之前的總結中我們已經總結了線程間通信的方式和提點,下面這篇博文我們來總結下進程間通信的方式方法和特點。同樣我們不把函數作為重點,重點在于對特征的中介。
進程間通信(IPC)的方式很多。下面進行歸類總結。
在傳統的進程間通信中有 無名管道,有名管道,信號通信。后來system v 退出了自己的IPC 方式 消息隊列,共享內存和信號燈集合但是system v的通信方式也存在自己的缺點。POSIX 在此基礎上退出了自己的posix的消息隊列,共享內存和信號燈集。另外,進程間還可以通過對文件的操作實現溝通,這里用到了文件鎖。還有后期的內存映射方式。在網絡上BSD率先提出了socket的方法,成為后來為流行的套接字通信方式,這種方式既可以在本機上的進程間,也可以在網絡上。
IPC 通信工具分類
下面對我們常用的集中進程間通信方式的特征進行總結
pipe
1.32位linux系統下默認大小為64M
2.如果寫滿會阻塞知道有人讀走再寫
3.如果讀寫都有那么寫不會影響,讀的話會阻塞
4.如果沒有讀端那么管道寫入后會管道破裂發送一個信號SIGPIPE導致進程結束
5.如果沒有寫端那么管道讀取會退出,如果管道里有東西那么會先讀出來然后退出
6.fd[0]為讀端 fd[1]為寫端是固定的
7.Pipe創建之后,在內核中。當所有的讀端和寫端都關閉的時候,pipe將被釋放掉
fifo
mkfifo既是函數又是命令
1.fifo不能用標準IO操作。適用于非親緣關系的進程間,大為64M
2.fifo的打開有只讀只寫方式
如果只讀方式打開沒有寫端會阻塞,如果只寫方式沒有讀端會阻塞這種阻塞是以open處阻塞。
如果以讀寫方式打開則不會阻塞,但是我們一般不會這樣做,用fifo更多用來多個進程間進行單向的通信
3.fifo 文件不能通過lseek函數進行操作,管道屬于 內核空間開辟,如果讀寫端都關閉那么內容會被清除
4.可以通過打開時候設置全新啊O_NONBLOCK 將打開方式設置為非阻塞模式,這種模式打開的時候如果另一端已經打開那么沒有影響
如果非阻塞為讀,而寫段沒打開,那么讀同樣會成功(就是不會open處阻塞)
如果非阻塞為寫,而讀端沒有打開,那么會返回一個錯誤信號管道破裂ENXIO open調用失敗
信號
1.引起內核產生信號的事件 硬件異常 終端輸入特殊字符 軟件事件如定時器到期,窗口改變
2.信號的默認操作 :忽略信號 終止進程 暫停進程 對之前暫停的進程重新啟動
3.信號是一種異步行為
共享內存
1.共享內存是一種為高效的進程間通信方式,內核專門留出的一塊內存區域,這塊內存可以由需要的訪問的進程將其映射到自己的私有空間,因此進程可以直接讀取數據不需要復制,所以提高了效率
2.key值是一個非負整數,通常生成的方法是有ftok生成(傳入一個文件,和一個整數,通過inod節點結合算法)。這樣同樣的參數確保生成的key一樣,而不同的傳入產生不同的key。這樣可以確保打開相同的key即指向相同的共享內存(或者消息隊列或者信號量)。這是一種成熟的技術
3.共享內存多個進程可以對其操作,因此需要同步互斥機制
4.生成key---創建或打開---映射---解除映射----刪除 這是共享內存使用的一般步驟
5.映射后一個參數可設置只讀,0表示可讀可寫
6.創建時候key如果設置成私有的,那么只有在這個進程中可用,對進程間通信沒有多大意義
7.共享內存的大小限制: usr/include/linux/shm.h中
#define SHMMAX 0x2000000 大32MB
#define SHMMIN 1 小1個字節
消息隊列
1.消息隊列中一次只能讀取一條消息,不能一次讀取多條或者不到一條
2.消息隊列中的消息既可以按照先進先出讀取也可以按照類型
3.msgsnd 發送消息事后,第三個參數為消息的字節數,一次發送一個消息所以返回為0,而不需要為發送的字節數,
第四個參數可以設置為非阻塞模式IPC_NOWAIT,這樣當消息隊列滿的時候會立即返回EAGAIN錯誤
4 msgrcv 也可以設置非阻塞模式,,如果阻塞那么消息隊列中沒有消息會阻塞,如果設置為非阻塞則立即返回ENOMSG錯誤
5.消息隊列和共享內存如果不手動釋放不會隨進程結束,除非系統重啟
6.消息隊列結構體重的消息類型項必須為第一項
信號
1.信號量更多是用來同步進程間資源的,如共享內存。也可以同步父子進程的執行
2信號燈限制: usr/include/linux/sem.h中
semget申請的信號燈的編號從0開始
semctl中的cmd 命令的常用用法
另外在poxis中也有消息隊列,共享內存和信號量的機制
消息隊列中system v 的移植性比較好,可以選擇消息類型,但是poxis 的消息隊列可以被poll select 等進行監聽
共享內存中system v 的支持范圍比較廣泛,但是poxis 不必再創建時候就定下共享內存的大小
信號量中 poxis 有些像線程的信號量,通過相互通知的機制進行pv操作,相對而言不那么復雜。system v中是定義一個信號量的集合