進程間通信1

管道

  管道由於傳遞數據只能單向傳遞,因此又稱半雙工管道,它是一種兩個進程間進行單向通信的機制.
  侷限性
   *數據只能由一個進程流向另一個進程,若要進行全雙工通信,則需建立兩個管道.
   *管道只能用於具有親緣關係的進程間通信.
   *管道無名字.
   *管道的緩衝區大小受限制.
   *管道所傳遞的是無格式的字節流,這就要求管道的輸入和輸出事先約定好數據格式.

  使用管道進行通信時,兩端的進程向管道讀寫數據是通過創建管道時,系統設置的文件描述符進行的.
  管道是一個特殊的文件,這個文件只存在於內存中.在創建管道時,系統爲管道分配一個頁面作爲數據緩衝區,進行管道通信的兩個進程通過讀寫這個緩衝區來進行通信.
  寫入的數據每次添加在管道緩衝區的末尾,讀數據時都是從緩衝區的頭部讀出數據.

管道的創建

 linux下創建管道可以通過函數pipe完成,該函數如果調用成功返回0,並且數組中將包含兩個新的文件描述符.如果有錯誤發生,則返回-1.
 
 這裏寫圖片描述
 
 管道兩端分別用描述符fd[0]及fd[1]來描述.
 管道兩端的任務固定.fd[0]爲管道讀端,fd[1]爲管道寫端.
 管道是一種文件,創建成功後就可以作爲一般文件來使用,因此對文件操作的I/O函數都可以用於管道,如read(),write()等.
 
 管道的一般用法
 進程在使用fork函數創建子進程前先創建一個管道,該管道用於在父子進程間通信.然後創建子進程,之後父進程關閉管道讀端,子進程關閉管道寫端,父進程負責向管道寫數據,子進程負責讀數據.也可以父進程關閉管道寫端,子進程關閉管道讀端.

管道的讀寫

從管道中讀數據

  要讀取管道中數據的進程要關閉管道寫端fd1,同時向管道寫數據的進程應關閉讀端fd0.(因爲是用於具有親緣關係的進程間通信,所以共享文件描述符).使用前,應及時關閉不需要的另一端,避免錯誤的發生.
  
進程在管道的讀端讀數據時
   1.如果管道寫端不存在,則讀進程認爲已經讀到數據的末尾,讀函數返回讀出的字節數爲.
   2.若管道寫端存在,
   (1)且請求讀取的字節數大於PIPE_BUF,則返回管道中所有數據,
   (2)如果不大於PIPE_BUF,則返回管道中現有的所有數據(管道中數據量小於請求的數據量). 或返回請求的字節數(管道中數據量大於等於請求的數據量)

向管道中寫數據

 如果某進程希望向管道中寫入數據,那麼該進程應關閉讀端fd0文件描述符,同時管道另一端的進程關閉fd1.
 向管道寫入數據時,linux不保證寫入的原子性.
 >原子性:操作在任何時候都不能被任何原因打斷,操作要麼不做要麼就一定完成.
 管道緩衝區一有空閒區域,寫進程就會試圖向管道寫入數據,若讀進程不讀走緩衝區的數據,則寫操作一直被阻塞等待.
  
  在寫管道時,如果請求的字節數小於等於PIPE_BUF,則多個進程對同一管道的寫操作不會交錯進行,但如果有多個進程同時寫一個管道,且某些進程要求寫的字節數超過PIPE_BUF所能容納時,則多個寫操作的數據可能會交錯.

  >只由管道讀端存在時,向管道中寫入數據纔有意義.否則,向管道中寫入數據的進程將收到內核傳來的SIGPIPE信號,如果忽略或撲捉該信號並從其處理程序返回,則write出錯,錯誤碼爲EPIPE.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章