1. 程式人生 > >Linux環境程序間通訊(一) 管道及有名管道(轉)

Linux環境程序間通訊(一) 管道及有名管道(轉)

管道是Linux支援的最初Unix IPC形式之一,具有以下特點:

  • 管道是半雙工的,資料只能向一個方向流動;需要雙方通訊時,需要建立起兩個管道;
  • 只能用於父子程序或者兄弟程序之間(具有親緣關係的程序);
  • 單獨構成一種獨立的檔案系統:管道對於管道兩端的程序而言,就是一個檔案,但它不是普通的檔案,它不屬於某種檔案系統,而是自立門戶,單獨構成一種檔案系統,並且只存在與記憶體中。
  • 資料的讀出和寫入:一個程序向管道中寫的內容被管道另一端的程序讀出。寫入的內容每次都新增在管道緩衝區的末尾,並且每次都是從緩衝區的頭部讀出資料。

  1. #include <unistd.h>
  2. int pipe(int fd[2])

該函式建立的管道的兩端處於一個程序中間,在實際應用中沒有太大意義,因此,一個程序在由pipe()建立管道後,一般再fork一個 子程序,然後通過管道實現父子程序間的通訊(因此也不難推出,只要兩個程序中存在親緣關係,這裡的親緣關係指的是具有共同的祖先,都可以採用管道方式來進 行通訊)。

管道兩端可分別用描述字fd[0]以及fd[1]來描述,需要注意的是,管道的兩端是固定了任務的。即一端只能用於讀,由描述字 fd[0]表示,稱其為管道讀端;另一端則只能用於寫,由描述字fd[1]來表示,稱其為管道寫端。如果試圖從管道寫端讀取資料,或者向管道讀端寫入資料 都將導致錯誤發生。一般檔案的I/O函式都可以用於管道,如close、read、write等等。

從管道中讀取資料:

  • 如果管道的寫端不存在,則認為已經讀到了資料的末尾,讀函式返回的讀出位元組數為0;
  • 當管道的寫端存在時,如果請求的位元組數目大於PIPE_BUF,則返回管道中現有的資料位元組數,如果請求的位元組數目不大於 PIPE_BUF,則返回管道中現有資料位元組數(此時,管道中資料量小於請求的資料量);或者返回請求的位元組數(此時,管道中資料量不小於請求的資料 量)。注:(PIPE_BUF在include/linux/limits.h中定義,不同的核心版本可能會有所不同。Posix.1要求 PIPE_BUF至少為512位元組,red hat 7.2中為4096)。

關於管道的讀規則驗證:


  1. /**************
  2.  * readtest.*
  3.  **************/
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <errno.h>
  7. main()
  8. {
  9.     int pipe_fd[2];
  10.     pid_t pid;
  11.     char r_buf[100];
  12.     char w_buf[4];
  13.     char* p_wbuf;
  14.     int r_num;
  15.     int cmd;
  16.     memset(r_buf,0,sizeof(r_buf));
  17.     memset(w_buf,
    0,sizeof(r_buf));
  18.     p_wbuf=w_buf;
  19.     if(pipe(pipe_fd)<0)
  20.     {
  21.         printf("pipe create error\n");
  22.         return -1;
  23.     }
  24.     if((pid=fork())==0)
  25.     {
  26.         printf("\n");
  27.         close(pipe_fd[1]);
  28.         sleep(3);//確保父程序關閉讀端
  29.      r_num=read(pipe_fd[0],r_buf,100);
  30.         printf(    "read num is %d the data read from the pipe is %d\n",r_num,atoi(r_buf));
  31.         close(pipe_fd[0]);
  32.         exit(1);
  33.     }
  34.     else if(pid>0)
  35.     {
  36.         close(pipe_fd[0]);//read
  37.         strcpy(w_buf,"111");
  38.         if(write(pipe_fd[1],w_buf,4)!=-1)
  39.             printf("parent write over\n");
  40.         close(pipe_fd[1]);//write
  41.             printf("parent close fd[1] over\n");
  42.         sleep(10);
  43.     }    
  44. }
  45.  /**************************************************
  46.  * 程式輸出結果:
  47.  * parent write over
  48.  * parent close fd[1] over
  49.  * read num is 4 the data read from the pipe is 111
  50.  * 附加結論:
  51.  * 管道寫端關閉後,寫入的資料將一直存在,直到讀出為止.
  52.  ****************************************************/

向管道中寫入資料:

  • 向管道中寫入資料時,linux將不保證寫入的原子性,管道緩衝區一有空閒區域,寫程序就會試圖向管道寫入資料。如果讀程序不讀走管道緩衝區中的資料,那麼寫操作將一直阻塞。 
    注:只有在管道的讀端存在時,向管道中寫入資料才有意義。否則,向管道中寫入資料的程序將收到核心傳來的SIFPIPE訊號,應用程式可以處理該訊號,也可以忽略(預設動作則是應用程式終止)。

對管道的寫規則的驗證1:寫端對讀端存在的依賴性


  1. #include <unistd.h>
  2. #include <sys/types.h>
  3. main()
  4. {
  5.     int pipe_fd[2];
  6.     pid_t pid;
  7.     char r_buf[4];
  8.     char* w_buf;
  9.     int writenum;
  10.     int cmd;
  11.     memset(r_buf,0,sizeof(r_buf));
  12.     if(pipe(pipe_fd)<0)
  13.     {
  14.         printf("pipe create error\n");
  15.         return -1;
  16.     }
  17.     if((pid=fork())==0)
  18.     {
  19.         close(pipe_fd[0]);
  20.         close(pipe_fd[1]);
  21.         sleep(10);    
  22.         exit(1);
  23.     }
  24.     else if(pid>0)
  25.     {
  26.         sleep(1); //等待子程序完成關閉讀端的操作
  27.         close(pipe_fd[0]);//write
  28.         w_buf="111";
  29.         if((writenum=write(pipe_fd[1],w_buf,4))==-1)
  30.             printf("write to pipe error\n");
  31.         else    
  32.             printf("the bytes write to pipe is %d \n", writenum);
  33.         close(pipe_fd[1]);
  34.     }    
  35. }

則輸出結果為: Broken pipe,原因就是該管道以及它的所有fork()產物的讀端都已經被關閉。如果在父程序中保留讀端,即在寫完pipe後,再關閉父程序的讀端,也會正常 寫入pipe,讀者可自己驗證一下該結論。因此,在向管道寫入資料時,至少應該存在某一個程序,其中管道讀端沒有被關閉,否則就會出現上述錯誤(管道斷 裂,程序收到了SIGPIPE訊號,預設動作是程序終止)

對管道的寫規則的驗證2:linux不保證寫管道的原子性驗證


  1. #include <unistd.h>
  2. #include <sys/types.h>
  3. #include <errno.h>
  4. main(int argc,char**argv)
  5. {
  6.     int pipe_fd[2];
  7.     pid_t pid;
  8.     char r_buf[4096];
  9.     char w_buf[4096*2]

    相關推薦

    Linux環境程序通訊 管道有名管道()

    管道是Linux支援的最初Unix IPC形式之一,具有以下特點:管道是半雙工的,資料只能向一個方向流動;需要雙方通訊時,需要建立起兩個管道;只能用於父子程序或者兄弟程序之間(具有親緣關係的程序);單獨構成一種獨立的檔案系統:管道對於管道兩端的程序而言,就是一個檔案,但它不是普通的檔案,它不屬於某種檔案系統,

    Linux環境程序通訊: 共享記憶體()

    轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html, 作者:鄭彥興系統呼叫mmap()通過對映一個普通檔案實現共享記憶體。系統V則是通過對映特殊檔案系統shm中的檔案實現程序間的共享記憶體通訊。也就是說,每個共享記憶體區域對

    Linux環境程序通訊: 共享記憶體()

    轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html, 作者:鄭彥興採用共享記憶體通訊的一個顯而易見的好處是效率高,因為程序可以直接讀寫記憶體,而不需要任何資料的拷貝。對於像管道和訊息佇列等通訊方式,則需要在內 核和使用者空間

    Linux環境程序通訊: 訊號()

    訊號本質訊號是在軟體層次上對中斷機制的一種模擬,在原理上,一個程序收到一個訊號與處理器收到一箇中斷請求可以說是一樣的。訊號是非同步的,一個程序不必通過任何操作來等待訊號的到達,事實上,程序也不知道訊號到底什麼時候到達。訊號是程序間通訊機制中唯一的非同步通訊機制,可以看作是非同步通知,通知接收訊號的程序有哪些事

    Linux 環境程序通訊 套介面()

    轉自https://www.ibm.com/developerworks/cn/linux/l-ipc/part6/, 作者:鄭彥興一個套介面可以看作是程序間通訊的端點(endpoint),每個套介面的名字都是唯一的(唯一的含義是不言而喻的),其他程序可以發現、連線並且 與之通訊。通訊域用來說明套介面通訊的協

    Linux環境程序通訊 訊息佇列()

    轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part3/, 作者:鄭彥興訊息佇列(也叫做報文佇列)能夠克服早期unix通訊機制的一些缺點。作為早期unix通訊機制之一的訊號能夠傳送的資訊量有限,後來雖然 POSIX 1003.1b在訊號的實時性方面作了

    Linux環境程序通訊 訊號燈()

    轉自http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/, 作者:鄭彥興訊號燈與其他程序間通訊方式不大相同,它主要提供對程序間共享資源訪問控制機制。相當於記憶體中的標誌,程序可以根據它判定是否能夠訪問某些共享資源,同時,程序也可以修改該標誌。除了用於訪

    Linux環境程序通訊: 訊號()

    從訊號傳送到訊號處理函式的執行完畢對於一個完整的訊號生命週期(從訊號傳送到相應的處理函式執行完畢)來說,可以分為三個重要的階段,這三個階段由四個重要事件來刻畫:訊號誕生;訊號在程序中註冊完畢;訊號在程序中的登出完畢;訊號處理函式執行完畢。相鄰兩個事件的時間間隔構成訊號生命週期的一個階段。 下面闡述四個事件的實

    Linux環境程序通訊 訊號燈

    一、訊號燈概述訊號燈與其他程序間通訊方式不大相同,它主要提供對程序間共享資源訪問控制機制。相當於記憶體中的標誌,程序可以根據它判定是否能夠訪問某些共享資源,同時,程序也可以修改該標誌。除了用於訪問控制外,還可用於程序同步。訊號燈有以下兩種型別:二值訊號燈:最簡單的訊號燈形式,

    Linux環境程序通訊 共享記憶體

    系統呼叫mmap()通過對映一個普通檔案實現共享記憶體。系統V則是通過對映特殊檔案系統shm中的檔案實現程序間的共享記憶體通訊。也就是說,每個共享記憶體區域對應特殊檔案系統shm中的一個檔案(這是通過shmid_kernel結構聯絡起來的),後面還將闡述。 1、系統V共

    Linux程序通訊——管道、訊號量

    一、Linux程序間通訊方式 :有六種方式在兩個程式間傳遞資訊         1、訊號( Singal )         2、管道 ( Pipe ) 及有名管道         3、訊號量 (

    Android IPC程序通訊檔案共享

    IPC程序間通訊簡介 1.在AndroidManifest.xml中宣告元件android:process屬性。 不指定process屬性,則預設執行在主程序中,主程序名字為包名。 android:process = package:remote,將執行在package:remote程序

    Android 8.0系統原始碼分析--Binder程序通訊

     開始我們的沉澱之路,老羅的書中第二章講的是Android HAL層的知識,而且直接自己實現了一個虛擬的freg驅動程式,後面的幾節是分別從native、java層如何訪問這個虛擬的驅動程式介面,我這裡沒有這樣的環境,所以就不分析這節了,第三章的智慧指標我對比8.0系統原

    Linux程序通訊IPC之訊號量詳解與測試用例

    學習環境centos6.5 Linux核心2.6 程序間通訊概述 1. 程序通訊機制 一般情況下,系統中執行著大量的程序,而每個程序之間並不是相互獨立的,有些程序之間經常需要互相傳遞訊息。但是每個程序在系統中都有自己的地址空間,作業系統通過頁表

    Linux程序通訊IPC之訊息佇列詳解測試用例

    學習環境 Centos6.5 Linux 核心 2.6 什麼是訊息佇列? 訊息佇列是SystemV版本中三種程序通訊機制之一,另外兩種是訊號量和共享儲存段。訊息佇列提供了程序間傳送資料塊的方法,而且每個資料塊都有一個型別標識。訊息佇列是基於訊息的,而管

    Qt程序通訊--------QProcess

           Qt提供了一個QProcess類用於啟動一個外部程式並與之通訊。啟動一個新程序的操作十分簡單,只需要將待啟動的程式名稱和啟動引數傳遞給start()函式即可。 m_pPro = new

    Linux程序通訊IPC之共享記憶體詳解與測試用例

    學習環境centos6.5 Linux核心2.6 什麼是共享記憶體 共享記憶體允許兩個或更多程序訪問同一塊記憶體。當一個程序改變了這塊記憶體中的內容的的時候,其他程序都會察覺到這個更改。 效率: 因為所有程序共享同一塊記憶體,共享記憶體在各種程序

    細說linux IPC:基於socket的程序通訊

        【版權宣告:尊重原創,轉載請保留出處:blog.csdn.net/shallnet 或 .../gentleliu,文章僅供學習交流,請勿用於商業用途】     在一個較大的工程當中,一般都會有多個程序構成,各個功能是一個獨立的程序在執行。既然多個程序構成一個工程,

    Linux程序通訊IPC方式總結

    程序間通訊概述 程序通訊的目的 資料傳輸  一個程序需要將它的資料傳送給另一個程序,傳送的資料量在一個位元組到幾M位元組之間 共享資料  多個程序想要操作共享資料,一個程序對共享資料 通知事件 一個程序需要向另一個或一組程序傳送訊息,通知它(它們)

    Linux程序通訊匿名管道命名管道共享記憶體,訊息佇列,訊號量

    目錄 程序間通訊的介紹 管道 匿名管道 原理: 程式碼實現 匿名管道特性 實現管道符 |  命名管道 命名管道特性 程式碼實現 管道讀寫規則 作業系統中ipc的相關命令 共享記憶體(重點) 生命週期: 程式碼實現 程式碼實現獲