管道

管道

image.png
//pipedemo
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

//管道有一個(gè)讀取端一個(gè)寫入端

main()
{
    int len,i,apipe[2];
    char buf[BUFSIZ];
    
    if(pipe(apipe) == -1){
        perror("could not make pipe");
        exit(1);
    }
    printf("Got a pipe ! It is fiile descriptors:{%d %d}\n",apipe[0],apipe[1]);
    
    //read from stdin ,write into pipe ,read from pipe,print
    
    while(fgets(buf,BUFSIZ,stdin)){//進(jìn)程從標(biāo)準(zhǔn)輸入讀數(shù)據(jù),數(shù)據(jù)存在buf
        len = strlen(buf);
        printf("%d\n",len);
        if(write(apipe[1],buf,len)!=len){//把數(shù)據(jù)寫到管道的寫入端
            perror("writing to pipe");
            break;
        }
        
        for(i = 0;i<len;i++)//清理buf
            buf[i] = 'X';
        len = read(apipe[0],buf,BUFSIZ);//從管道的讀取端讀取數(shù)據(jù)到buf
        
        if(len == -1){
            perror("reading from pipe");
            break;
        }
        if(write(1,buf,len)!=len){//把buf的數(shù)據(jù)輸出到標(biāo)準(zhǔn)輸出
            perror("writing to stdout");
            break;
        }
    }
}

管道有一個(gè)讀取端,一個(gè)寫入端,當(dāng)一個(gè)進(jìn)程創(chuàng)建了一個(gè)管道之后,該進(jìn)程就有了連向管道兩端的連接。這個(gè)進(jìn)程調(diào)用fork的時(shí)候,他的子進(jìn)程也得到了這兩個(gè)連向管道的連接,父進(jìn)程和子進(jìn)程都可以將數(shù)據(jù)寫到管道的寫數(shù)據(jù)端口,并從讀數(shù)據(jù)端口將數(shù)據(jù)讀出,兩個(gè)進(jìn)程都可以讀寫管道,但是當(dāng)一個(gè)進(jìn)程讀,一個(gè)進(jìn)程寫的時(shí)候,管道的使用效率是最高的。

image.png

下面的程序就是pipe與fork結(jié)合起來,創(chuàng)建一堆通過管道來通信的進(jìn)程。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#define CHILD_MESS "I want a cookie\n"
#define PAR_MESS "testing..\n"
#define oops(m,x)   {perror(m);exit(x);}

main()
{
    int pipefd[2];
    int len;
    char buf[BUFSIZ];
    int read_len;
    
    if(pipe(pipefd) == -1)
        oops("cannot get a pipe",1);
    
    switch(fork()){
        case -1:
            oops("cannot fork",2);
        case 0:
            len = strlen(CHILD_MESS);
            while(1){
                if(write(pipefd[1],CHILD_MESS,len)!=len)
                    oops("write",3);
                sleep(5);
                
            }
            //parent reads from pipe and also writes to pipe
        default:
            len = strlen(PAR_MESS);
            while(1){
                if(write(pipefd[1],PAR_MESS,len)!=len)
                    oops("write",4);
                sleep(1);
                read_len = read(pipefd[0],buf,BUFSIZ);
                if(read_len <=0)
                    break;
                write(1,buf,read_len);
            }
    }
}

總結(jié)

管道在許多方面類似于普通文件,進(jìn)程使用write將數(shù)據(jù)寫入管道,又通過read把數(shù)據(jù)讀出來。像文件一樣,管道是不帶有任何結(jié)構(gòu)的字節(jié)序列。另一方面,管道又與文件不同。

1.主要內(nèi)容 ·輸入/輸出重定向允許完成特定功能的程序通過交換數(shù)據(jù)來進(jìn)行相互協(xié)作。 ? Unix 默認(rèn)規(guī)定程序從文件描述符 0 讀取數(shù)據(jù),寫數(shù)據(jù)到文件描述符1,將錯(cuò)誤信息輸 出到文件描述符 2 。這三個(gè)文件描述符稱為標(biāo)準(zhǔn)輸入、輸出及標(biāo)準(zhǔn)錯(cuò)誤輸出。 ·當(dāng)?shù)卿浀?Unix 系統(tǒng)中,登錄程序設(shè)置文件描述符 0 、 1 、 2 。所有的連接、文件描述符 都會(huì)從父進(jìn)程傳遞給子進(jìn)程。它們也會(huì)在調(diào)用 exec 時(shí)被傳遞。 ·創(chuàng)建文件描述符的系統(tǒng)調(diào)用總是使用最低可用文件描述符號(hào)。 ? 322 ? Unix/Linux 編程實(shí)踐教程 ·重定向標(biāo)準(zhǔn)輸入、輸出以及錯(cuò)誤輸出意味著改變文件描述符 0 ,1- 2 的連接。有很多 種技術(shù)來重定向標(biāo)準(zhǔn)l/O 。 ·管道是內(nèi)核中的一個(gè)數(shù)據(jù)隊(duì)列,其每一端連接一個(gè)文件描述符。程序通過使用 plpe 系統(tǒng)調(diào)用創(chuàng)建管道。 .當(dāng)父進(jìn)程調(diào)用 fork 的時(shí)候,管道的兩端都被復(fù)制到子進(jìn)程中。 .只有有共同父進(jìn)程的進(jìn)程之間才可以用管道連接。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容