管道
//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í)候,管道的使用效率是最高的潭千。
下面的程序就是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 获询。所有的連接涨岁、文件描述符 都會從父進(jìn)程傳遞給子進(jìn)程。它們也會在調(diào)用 exec 時(shí)被傳遞吉嚣。 ·創(chuàng)建文件描述符的系統(tǒng)調(dià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)程之間才可以用管道連接。