管道
//pipedemo
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
//管道有一个读取端一个写入端
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)){//进程从标准输入读数据,数据存在buf
len = strlen(buf);
printf("%d\n",len);
if(write(apipe[1],buf,len)!=len){//把数据写到管道的写入端
perror("writing to pipe");
break;
}
for(i = 0;i<len;i++)//清理buf
buf[i] = 'X';
len = read(apipe[0],buf,BUFSIZ);//从管道的读取端读取数据到buf
if(len == -1){
perror("reading from pipe");
break;
}
if(write(1,buf,len)!=len){//把buf的数据输出到标准输出
perror("writing to stdout");
break;
}
}
}
管道有一个读取端,一个写入端,当一个进程创建了一个管道之后,该进程就有了连向管道两端的连接。这个进程调用fork的时候,他的子进程也得到了这两个连向管道的连接,父进程和子进程都可以将数据写到管道的写数据端口,并从读数据端口将数据读出,两个进程都可以读写管道,但是当一个进程读,一个进程写的时候,管道的使用效率是最高的。
下面的程序就是pipe与fork结合起来,创建一堆通过管道来通信的进程。
#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);
}
}
}
总结
管道在许多方面类似于普通文件,进程使用write将数据写入管道,又通过read把数据读出来。像文件一样,管道是不带有任何结构的字节序列。另一方面,管道又与文件不同。
1.主要内容 ·输入/输出重定向允许完成特定功能的程序通过交换数据来进行相互协作。 • Unix 默认规定程序从文件描述符 0 读取数据,写数据到文件描述符1,将错误信息输 出到文件描述符 2 。这三个文件描述符称为标准输入、输出及标准错误输出。 ·当登录到 Unix 系统中,登录程序设置文件描述符 0 、 1 、 2 。所有的连接、文件描述符 都会从父进程传递给子进程。它们也会在调用 exec 时被传递。 ·创建文件描述符的系统调用总是使用最低可用文件描述符号。 • 322 • Unix/Linux 编程实践教程 ·重定向标准输入、输出以及错误输出意味着改变文件描述符 0 ,1- 2 的连接。有很多 种技术来重定向标准l/O 。 ·管道是内核中的一个数据队列,其每一端连接一个文件描述符。程序通过使用 plpe 系统调用创建管道。 .当父进程调用 fork 的时候,管道的两端都被复制到子进程中。 .只有有共同父进程的进程之间才可以用管道连接。