管道使用
$ ls |wc
管道的C代码
#include <unistd.h>
int fd[2];
void run_ls()
{
dup2(fd[1],1); #dup2调用
close(fd[0]);
close(fd[1]);
execve("/bin/ls",NULL,NULL);
}
void run_wc()
{
dup2(fd[0],0);
close(fd[0]);
close(fd[1]);
execve("/usr/bin/wc",NULL,NULL);
}
int main()
{
pipe(fd); #调用pipe创建管道
if(fork()==0) #这是子进程
run_ls();
else
run_wc(); #这是父进程
return 0;
}
此程序执行结果与 ls | wc等效,对fd[1]进行写入操作时会把数据写入内核中的pipe对应的buffer中,而对fd[0]进行读取操作时,从pipe的buf中读取数据,把fd[0]和fd[1]连接成一个管道
main中,fork调用创建出子程序,子程序会继承父进程的文件描述符表
子进程关闭fd[1],父进程关闭fd[0]后子父进程建立管道,子进程向fd[1]写入的数据,父进程可以通过fd[0]读取。
dup2调用,父进程把标准输入对应的文件结构体复制成了fd[0]对应的,子进程中把标准输入对应的文件结构体复制成了fd[1]对应的,此结构体包含了对文件的操作函数。这样子进程中写0号文件描述符的数据实际会写入内核pipe中的buf中,父进程从1这个文件描述符对应的文件中读取数据,1不再指向标准输出而是指向pipe的buf
可以看出,linux中创建进程是从父进程“fork”出来,再execve,而不是创建时就指定要运行的函数