管道的創建與讀寫pipe


1、管道的創建

#include <unistd.h>

int pipe(int pipefd[2]);

linux下創建管道可以通過函數pipe來完成。該函數如果調用成功,數組中將包含兩個新的文件描述符。

管道兩端可分別用描述符fd[0] 以及fd[1]來描述。需要注意的是,管道兩端的任務是固定的,一端只能用於讀,由描述符fd[0]表示,稱其為管道讀端;

另一端只能用於寫,由描述符fd[1]來表示,稱其為管道寫端。如果試圖從管道寫端讀數據,或者向管道讀端寫數據都將導致出錯。

管道是一種文件,因此對文件操作的I/O函數都可以用於管道,如read,write等。

管道一旦創建成功,就可以作為一般的文件來使用,對一般文件進行操作的I/O函數也適用於管道文件。

------------------------------------------------------------------------------------------

管道的一般用法是,進程在使用fork函數創建子進程前先創建一個管道,該管道用於在父子進程間通信,然后創建子進程,

之后父進程關閉管道的讀端,子進程關閉管道的寫端。父進程負責向管道寫數據而子進程負責讀數據。當然父進程可以關閉管道的寫端而子進程關閉管道的讀端。

這樣管道就可以用於父子進程間的通信,也可以用於兄弟進程間的通信。

 

2、從管道中讀數據

如果某個進程要讀取管道中的數據,那么該進程應當關閉fd[1],同時向管道寫數據的進程應當關閉fd[0]。因為管道只能用於具有親緣關系的進程間的通信,在各個程進行通信時,

他們共享文件描述符。在使用前,應及時地關閉不需要的管道的另一端,以避免意外錯誤的發生。

進程在管道的讀端讀數據時,如果管道的寫端不存在,則讀進程認為已經讀到了數據的末尾,讀函數返回讀出的字節數為0;管道的寫端如果存在,且請求讀取的字節數大於

PIPE_BUF,則返回管道中現有的所有數據;如果請求的字節數不大於PIPE_BUF,則返回管道中現有的所有數據(此時,管道中數據量小於請求的數據量),或者返回請求的

字節數(此時,管道中數據量大於等於請求的數據量)。

注意:PIPE_BUF在/usr/include/linux/limits.h中定義,不同的內核版本可能會有所不同。

 

3、向管道寫數據

如果某進程希望向管道中寫入數據,那么該進程應當關閉fd[0]文件描述符,同時管道另一端的進程關閉fd[1]。向管道中寫入數據時,linux不保證寫入的原子性(原子性是指操作在

任何時候都不能被任何原因所打斷,操作要么不做要么就一定完成)。管道緩沖區一有空閑區域,寫進程就會試圖向管道寫入數據。如果讀進程不讀走管道緩沖區中的數據,那么

寫操作將一直被阻塞等待。

在寫管道時,如果要求寫的字節數小於等於PIPE_BUF,則多個進程對同一管道的寫操作不會交錯進行。但是,如果有多個進程同時寫一個管道,而且某些進程要求寫入的字節數超過

PIPE_BUF所能容納時,則多個寫操作的數據可能會交錯。

注意:

只有在管道的讀端存在時,向管道中寫入數據才有意義。否則,向管道寫入數據的進程將收到內核傳來的SIGPIPE信號。應用程序可以處理也可以忽略該信號,如果忽略該信號或者

從其處理程序返回,則write出錯,錯誤碼為EPIPE。

必須在系統調用fork之前調用pipe,否則子進程將不會繼承管道的文件描述符。

 

#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>



int main()
{
    char* str = "i am parent";
    char buf[4];
    bzero(buf, sizeof(buf));
    pid_t pid;
    int fd[2];

    pipe(fd);

    pid = fork();
    if(0 == pid)//child read
    {
        sleep(1);//等待父進程向管道寫入數據
        printf("i am child, read to read\n");
        close(fd[1]);

        while(read(fd[0], buf, sizeof(buf)-1) > 0)
        {
            //printf("len=%d, %s\n", strlen(buf), buf);
            write(STDOUT_FILENO, buf, strlen(buf));
            bzero(buf, sizeof(buf));
        }

        write(STDOUT_FILENO, "\n", 1);
        close(fd[0]);
        
        exit(0);
        

    }
    else//parent write
    {
        printf("i am parent, read to read\n");
        close(fd[0]);
        
        write(fd[1], str, strlen(str));

        close(fd[1]);

        wait(NULL);//

        exit(0);

    }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM