Unix的管道真的是很方便,我们经常这样用:
$ls -l|wc -l
用于统计一个目录下的文件数。这里如果详细说起来,涉及了进程组,会话的概念。当然最显眼的就是符号 | ,这是就是管道,下面我们说说上面的这句shell如何用c语言来写。为了更能说明问题,我们把结果写入一个文件中。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
void error_quit(char *msg)
{
fprintf(stderr,"%s\n",msg);
exit(1);
}
int main(int argc, char *argv[])
{
int fd[2]; //存放管道读写的描述符
int new_fd;
if(pipe(fd)==-1) //使用pipe创建管道,错误返回-1
error_quit("pipe error");
//fork,dup和dup2都在 unistd.h 中申明
switch(fork()){ // 偶然看到的写法,觉得新鲜。fork返回pid_t类型
case -1: error_quit("fork error");
case 0: //子进程返回0
/*
close(1); //关闭标准输出,为了下一句能把子进程的管道写描述符复制到标准输出
dup(fd[1]); //把子进程管道写描述符复制到一个新的描述符中,由于上面关闭了标准输出,系统会选取最小的描述符作为新描述符 */
dup2(fd[1],1);//这是另外一种写法。上面注释部分由于不是原子操作,所以可以用dup2函数,实现上面注释块的功能。
close(fd[0]); //关闭掉不用的描述符
close(fd[1]);
execlp("ls","ls -l",0); //在子进程空间执行ls命令
error_quit("try to exec ls");
break;
default:
close(0);
dup(fd[0]); //可以用dup2代替
close(fd[0]);
close(fd[1]);
if((new_fd = open("result.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0)
//打开一个文件,使用系统调用open,在fcntl.h中申明
error_quit("open result.txt error");
close(1); //关闭标准输出
dup(new_fd); //标准输出变成文件result.txt
execlp("wc","wc","-l",0);
error_quit("try to wc");
break;
}
exit(0);
}
现在保存,编译文件 pipe_test.c
$gcc -c pipe_test.c
...
$gcc -g -o pt pipe_test.o
...
$./pt
$cat result.txt
$28
你也可以试试是不是和 ls -l|wc -l 一样呢?
注意,父子进程之间的通讯。如果我们的子进程没有准备好数据怎么办?
对于管道,如果写进程停止,那么读进程读到0,表示结束。
如果读进程先停止,那么写进程将会收到一个SIGPIPE的信号,并且wirte返回-1,把errno设置为 EPIPE。
这就是无名管道。当然还有更复杂的FIFO,有名管道。
这里主要是要注意 dup的使用,学习如何重定向。对了,这里还忘记说了,文件描述符,也就是上面的0,1,2,3这些,是进程表中的一个索引,他指向文件表,文件表说明了这个文件的各种属性。
分享到:
相关推荐
管道分类: 根据进程的相互关系,可以分为:匿名管道与命名管道。 1 匿名管道:管道是父进程和子进程间,或是子进程与子进程间单向的通讯机制,即一个进程发送数据到管道,另外一个进程从管道中读出数据。如果需要...
某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n 口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n口油井的位置,即它们的x 坐标(东西向)和y 坐标(南北...
其中管道和有名管道是最早的进程间通信机制之一,管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因 此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。 认清管道和有名管道...
命名管道命名管道命名管道命名管道命名管道命名管道命名管道命名管道命名管道命名管道命名管道命名管道
3 管道通信 利用UNIX系统提供的管道机制实现进程间的通信 1 管道通信 利用pipe 和lockf 系统调用 编写程序 实现同族进程间的通信 使用系统调用pipe 建立一条管道线;创建子进程P1 P2 … 子进程Pi分别向管道各写...
命名管道实例 命名管道实例 命名管道实例 命名管道实例
java管道通信java管道通信java管道通信java管道通信java管道通信java管道通信
管道阻力计算软件管道阻力计算软件管道阻力计算软件管道阻力计算软件
进程的管道通信 编制一段程序,实现进程的管道通信,使用系统调用pipe()建立一个管道文件;两个子进程P1和P2 分别向管道各写一句话: Child1 is sending a message! Child2 is sending a message! 而父进程则从...
管道流水效果/管道气体效果Shader
建筑工程小程序 管道保温计算小软件建筑工程小程序 管道保温计算小软件建筑工程小程序 管道保温计算小软件建筑工程小程序 管道保温计算小软件建筑工程小程序 管道保温计算小软件建筑工程小程序 管道保温计算小软件...
压力管道定期检验规则——公用管道.pdf
命名管道通信,与QT命名管道通信,C#与C#的通信
压力管道设计(工业管道、公用管道).doc
管道字体格式管道字体格式管道字体格式管道字体格式管道字体格式
压力管道材料的选择;压力管道的设计和计算;压力管道的制作和安装;压力管道的检验和试验;压力管道的安全防护。
管道的关闭和遍历管道的关闭和遍历管道的关闭和遍历管道的关闭和遍历
通信管道工程、线路工程Auto CAD图例(管道人孔、手孔、管道开挖、回填、包封工程量),包含各种杆路管道自动连画,钢绞线重量长度换算,经纬度转换,标准材料库等软件。
冬季消防管道防冻须知管道防寒防冻措施.docx