全部博文(2065)
分类: LINUX
2010-07-10 00:11:34
15.2 管道
局限性:
1、 它们是半双工的(数据只能在一个方向上流动)。现在某些系统提供了全双工管道,但是基于可移植的考虑一般的设计是不考虑这样做的。
2、 它们只能是在具有公共祖先的进程之间使用。一般的做法是这样的:进程先创建一个管道然后这个进程再fork出来子进程,这样父子进程之间就可以依据管道通讯。
如果用过shell中的管道可能理解起来要容易。像more a | grep test
即前一个命令进程的标准输出通过管道与后一条命令的标准输入相连接。
程序清单:通过管道父进程向子进程传送数据
#include "apue.h"
int main(void) {
int n;
int fd[2];
pid_t pid;
char line[MAXLINE];
if(pipe(fd) < 0) {
err_sys("pipe error");
} if((pid = fork()) < 0) {
err_sys("fork error");
} else if(pid > 0) {
close(fd[0]); //父进程关闭读
write(fd[1],"hello world\n",12);
} else {
close(fd[1]); //子进程关闭写
n = read(fd[0],line,MAXLINE);
write(STDOUT_FILENO,line,n);
}
}
15.3 popen和pclose函数
最常见的一种情况是:创建一个管道连接到另外一个进程,然后读其输出或向其输入端发送数据。这两个函数的操作其实是:创建一个管道,调用fork产生一个子进程,关闭管道的不使用端,执行一个shell以运行命令。
使用popen向分页程序传送文件
#include "apue.h"
#include
#define PAGER "${PAGER:-more}"//如果shell变量PAGER已经定义了且其值非空则用它否则使用more
int main(int argc,char *argv[]) {
char line[MAXLINE];
FILE *fpin,*fpout;
if(argv != 2)
err_quit("args length short!");
if((fpin = fopen(argv[1],"r")) == NULL)
err_sys("cant open file %s",argv[1]);
if((fpout = popen(PAGER,"w")) == NULL) //使用popen方法把数据传给SHELL处理
err_sys("popen error");
while(fgets(line,MAXLINE,fpin) != NULL) {
if(fputs(line,fpout) == EOF) {
err_sys("fputs error to pipe");
}
}
if(ferror(fpin))
err_sys("fgets error");
if(pclose(fpout) == -1)
err_sys("pclose error");
exit(0);
}
15.4 协同进程
定义:当一个程序产生某个过滤程序的输入,同时又读取该过滤程序的输出,则这个过滤程序就成为协同进程/
对于协同进程它有连接到另一个进程的两个单向管道----一个是接到其标准输入,另一个则是来自其标准输出。我们处理的流程是:先要将数据写入到标准输入处理完了之后再将其输出到读取数据。
程序:对两个数求和程序
#include "apue.h"
int main(int argc,char *argv[]) {
int n,int1,int2;
char line[MAXLINE];
while((n = read(STDIN_FILENO,line,MAXLNE)) > 0) {
line[n] = 0;
if(sscanf(line,"%d%d",&int1,&int2) == 2) { //读取用户输入
sprinf(line,"%d\n",int1+int2); //输出数据
n = strlen(line);
if(write(STDOUT_FILENO,line,n) != n) {
err_sys("write error");
}
} else {
if(write(STDOUT_FILENO,"invalid args\n",13) != 13)
err_sys("write error");
}
}
exit(0);
}
chinaunix网友2010-07-10 17:46:56
成熟的男人要知道哪些是要坚持的东西哪些是要放弃 的东西!有些东西要学会懂得放弃。把主要全部的精力放在自己最深入的领域里面去