linux 子进程 重定向,在linux上 重定向 管道实现 (转)

管道和重定向

输入输出不仅可以重定向到文件,也可以通过管道传递到其他进程中。

基本思路:

linux:

1. 创建管道对

pipe(int pipefd[2])

2. 创建进程

首先fork,然后子进程用dup2把pipefd[0]复制到STDIN_FILENO(就是0),然后关闭pipefd[1],或者把pipefd[1]复制到STDOUT_FILENO(就是1),然后关闭pipefd[0]。

之后调用exec去载入要创建的进程。

3. 读或写

用read或者write。注意读写之前要把子进程使用的那一个用close函数关闭掉。

区别在*nix创建进程分两步,fork然后exec。windows只一步。

区别2,*nix要手工dup来复制文件描述符,windows在创建进程的API内部做好了这件事。

linux步骤多一些,但是灵活,可以变化出多种模式来,例如fork之后,不仅仅子进程可以exec,父进程也可以exec,完完全全实现像“ls|wc -l”这样的功能。也就是子进程用wc去替代,父进程用ls去替代。

windows步骤少,模式固定,它要实现上述功能,反而更加繁琐,需要创建两个进程,并把它们对接,然后等待两个进程结束

实例:

题目:通过管道模拟shell命令:catfile | sort

涉及主要知识点:未命名管道、重定向

题目描述:具体模拟一个shell命令:cat file | sort。具体的一些提示在后面。

提示:首先在当前目录下创建一个名为”file”的文件,里面的内容输入如下:

99

123

892

12

1342

89

32

76

通过执行”cat file | sort”后的结果如下:

12

123

1342

32

76

89

892

99

现在我们需要通过一个管道,将”cat file”的结果通过管道送给命令”sort”。其中,将”cat

file”命令的输出结果重定向到”sort”命令的输入是由包含在命令中的管道标志”|”来完成的。为了在程序当中实现类似的功能,需要用dup()或

者dup2()系统调用将标准输入和标准输出联系起来,具体的系统调用使用可以通过man手册来查,或者查阅群共享里面的函数手册。另外,这里的”cat

file”和”sort”命令不是自己来完成,而是通过调用exec函数族来实现的。

******************************************************************************************************************************************

******************************************************************************************************************************************

我的源代码如下:

1 #include 

2 #include

3 #include

4 #include

5 #include

6 #include

7

8 intmain(intarg,char*argv[],char**environ)

9 {

10     intfd[2];

11     pid_t pid;

12     intstat_val;

13

14     if(arg 

15     {

16         printf("wrong parameters\n");

17         exit(0);

18     }

19     if(pipe(fd))

20     {

21         printf("Create pipefailed!\n");

22         exit(1);

23     }

24

25     pid=fork();

26     switch(pid)

27     {

28         case-1:

29             perror("forkfailed!\n");

30             exit(1);

31         case0:

32             //close(0);

33             //dup(fd[0]);

34             dup2(fd[1],1);

35             close(fd[0]);

36             execlp("cat","cat","file",NULL);

37             exit(0);

38         default:

39             dup2(fd[0],0);

40             close(fd[1]);

41             execlp("sort","sort",NULL);

42             exit(0);

43     }

44     wait(&stat_val);

45     exit(0);

46     return0;

47 }

******************************************************************************************************************************************

******************************************************************************************************************************************

编译sort.c:

jingjing@jingjing-laptop:~/公共的$ gccsort.c -o sort

运行程序:

jingjing@jingjing-laptop:~/公共的$ ./sortcat file|sort

12

123

1342

32

76

89

892

99

*****

流程图:

40397419_1.gif

1』pipe()创建管道、fork()创建子进程

40397419_2.gif

这里,0-1-2分别表示标准输入,标准输出,标准错误。先创建管道,再由fork创建子进程,这里子进程是完全继承父进程的文件描述符表。

『2』父进程和子进程分别执行dup2()

40397419_3.gif

重定向以后,父进程的标准输入来自管道,子进程的标准输出到管道。也就是将父进程的文件描述符[3]处的指针拷贝到[0]对应的条目处;将子进程的文件描述符4处的指针拷贝到[1]对应的条目处。

『3』各自调用close以后

40397419_4.gif

调用close()关闭文件描述符,相当于删除文件描述符表的对应条目。

这里,close(fd[0])和close(fd[1])的操作是不可以省略的:执行了2个 close以后,参见图4,只有子进程的ls

-l才会像管道写数据,最终子进程终止,父进程会检测到文件结束;否则如果省略到close(),按照图3所示,子进程终止以后,父进程的文件描述符[4]仍然是为管道的写操作打开着,父进程将陷入无限期的阻塞,等待数据的写入。

注意: 关于这里 在父、子进程中都需要 close() 两次 有待验证!

心得:

原文:http://blog.csdn.net/markman101/article/details/7304979

1

子进程的功能是读出信息,而父进程的功能是写入信息;因此在子进程那里,要把管道的输入端复制到标准输出中,即dup2(fd[1],1)而父进程则要把管道写端复制到标准输入,即dup2(fd[0],0)。

2

dup()与dup2()的最大区别:

举例说明:

close(1); //关闭标准输出

dup(fd[1]); //把管道的输入端复制到标准输出

这两个语句等价于: dup2(fd[1],1);

所以dup2()是把close()和dup()这两个函数集成在了同一个函数里。这里特别要注意的是:dup2()的两个参数,是把前一个复制到后一个里面,所以书上的例子中写的是错误的。

3、还有就是exec()函数的用法,我一开始不知道“cat file“命令如何作为函数的参数,现在谈谈我的理解吧:

我的程序中execlp("cat","cat","file",NULL);第一个参数是为了指明该命令的路径,第二个和第三个参数是该命令

所包含的所有参数,即把他们一一罗列出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值