通过管道和重定向实现linux管道命令
2017-04-10 10:27
686 查看
下午查看了自己当初写的一个有关管道的一个题目,这个题目是带领3+1学习管道通信时写的。题目要求如下:
题目2:通过管道模拟shell命令:cat file | sort 涉及主要知识点:未命名管道、重定向 题目描述:具体模拟一个shell命令:cat file | sort。具体的一些提示在后面。 提示:首先在当前目录下创建一个名为”file”的文件,里面的内容输入如下:99123892121342893276 通过执行”cat file | sort”后的结果如下:12123134232768989299 现在我们需要通过一个管道,将”cat file”的结果通过管道送给命令”sort”。其中,将”cat file”命令的输出结果重定向到”sort”命令的输入是由包含在命令中的管道标志”|”来完成的。为了在程序当中实现类似的功能,需要用dup()或者dup2()系统调用将标准输入和标准输出联系起来,具体的系统调用使用可以通过man手册来查,或者查阅群共享里面的函数手册。另外,这里的”cat file”和”sort”命令不是自己来完成,而是通过调用exec函数族来实现的,具体的exec()函数族的使用不再啰嗦。扩展:实现两个管道
今天下午仔细一琢磨,发现这个题目当中,没有把创建进程说明,怪不得当初其他人做这个题目时,有许多疑问,原来是我的题目出现了问题。自己下午实现了一下,程序代码如下:#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
int main()
{
int fd[2], res;
pid_t pid;
res = pipe(fd);
if(res == -1) {
perror("Pipe error!");
exit(1);
}
pid = fork();
if(pid > 0) {
close(fd[1]);
dup2(fd[0], 0);
execl("/usr/bin/sort", "sort", (char *)0);
wait(NULL);
exit(0);
} else if(pid == 0) {
dup2(fd[1], 1);
close(fd[0]);
execl("/bin/cat", "cat", "file", NULL);
exit(0);
} else {
perror("Fork error!");
exit(2);
}
}
我当初出这个程序的目的主要是想把管道应用起来,然后想让大家能够把重定向带出来,而且我发现许多有关linux C语言的书上基本都有这种类似的题目,所以我觉得这个题目挺好的。 说一下我的思路吧,针对这个题,首先得把"cat file | sort"这个命令搞清楚,应该明确:这里有两个进程,而不是一个进程,其实我原先把题目在无意当中暗示了只有一个进程。在程序当中,创建一个进程之后,子进程将会执行“cat file”命令,而父进程会执行“sort”命令。在子进程当中,会通过重定向"dup2(fd[1], 1)",将标准输出重定向到管道的写端,说通俗一些,就是以后对于标准输出的操作都就改为对管道的写端的操作了,如果对这里还是不能够理解的话,请查看我的前一篇“通过文件共享来学习I/O重定向(下)——I/O重定向”。对于父进程而言,也是通关重定向“dup2(fd[0], 0)”,将标准输入重定向到管道的读端,以后对于标准输入的操作都就改为了对于fd[0]的操作了。通过这么解释,应该对于上面的程序清楚了吧,下面把我调试的过程当中发现的一些问题总结一下。 1.execl()函数执行之后,该进程成为什么进程了?对于这个问题的回答,我们可以通过修改上面的程序来实现,把父进程调用execl()函数之前加一个sleep(5)函数,即,if(pid > 0) {
close(fd[1]);
dup2(fd[0], 0); //修改的内容
execl("/usr/bin/sort", "sort", (char *)0);
wait(NULL);
exit(0);
} else if(pid == 0) {
在一个终端执行这个程序,在5秒之内打开另外一个终端,执行“ps -au”,并分析其结果,发现有这么几条记录:sunny 5107 0.0 0.0 1616 308 pts/0 S+ 21:36 0:00 ./a.outsunny 5108 0.0 0.0 0 0 pts/0 Z+ 21:36 0:00 [cat] sunny 5109 0.0 0.1 2716 1072 pts/2 R+ 21:37 0:00 ps -au 在其中有一个标识,说明出现了僵尸进程。 上面的测试,是让子进程去执行“execl()”函数的时候,父进程等待等待5s,然后在另外一个终端下查看子进程成了什么样的进程,结果是僵尸进程。等整个程序执行完毕之后,发现僵尸进程消失了,那么僵尸进程是如何消失的呢?这个目前我还没有弄明白,希望大家指教(对于popen()出现僵尸进程之后,会通过close()函数来退出,但是这里的话,好像没有close()函数调用,那它是如何退出呢?)。2.出现僵尸进程之后,那么下面的代码还执行吗?答案是不执行。这次我们修改子进程的代码:} else if(pid == 0) {
dup2(fd[1], 1);
close(fd[0]);
execl("/bin/cat", "cat", "file", NULL);
printf("fffffffffffffffffffffff"); //运行之后,发现这句没有执行
exit(0);
} else {
为什么会不执行了,我是这样猜想的,当子进程去执行“cat”命令时,执行完之 后,它成了僵尸进程,之后它退出了,但是如何退出的? 我在网上找到了有关进程一生的描述:随着一句fork,一个新进程呱呱落地,但它这时只是老进程的一个克隆。然后随着exec,新进程脱胎换骨,离家独立,开始了为人民服务的职业生涯。人有生老病死,进程也一样,它可以是自然死亡,即运行到main函数的最后一个”}”,从容地离我们而去;也可以是自杀,自杀有2种方式,一种是调用 exit函数,一种是在main函数内使用return,无论哪一种方式,它都可以留下遗书,放在返回值里保留下来;它还甚至能可被谋杀,被其它进程通过 另外一些方式结束他的生命。进程死掉以后,会留下一具僵尸,wait和waitpid充当了殓尸工,把僵尸推去火化,使其最终归于无形。这里遗书中的内容是在进程列表中保留一个位置,记载该进程的退出状态等信息供其他 进程收集,除此之外,僵尸进程不再占有任何内存空间。 看到这里,我明白了,子进程成为僵尸进程的原因是由于没有进行“遗书”回收造成的,为了证实我的想法,我们继续将父进程要执行的代码修改如下:if(pid > 0) {
close(fd[1]);
dup2(fd[0], 0);
wait(NULL);
sleep(3);
execl("/usr/bin/sort", "sort", (char *)0);
printf("ffffffffffffffff\n");
exit(0);
} else if(pid == 0) {
这时,当父进程等待3s的时候,在另外一个终端使用ps查看的时候,法相那个僵尸进程不见了,这说明我们对产生的僵尸进程进行了回收。但是,这时候,当sleep()执行完了之后,父进程自己又成了僵尸进程,它会被谁回收呢?当我们程序当中的父进程成为僵尸进程之后,它会把自己的遗书交给它的父进程,应该是在shell中执行那个程序的进程吧,所以,它应该是由执行它的那个shell进程回收的。
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(3988) | 评论(1) | 转发(0) |
0
上一篇:ubuntu中解压rar文件 及遇到乱码的解决方法
下一篇:linux(ubuntu)下外接投影仪或着显示器的方法
相关热门文章
strongswan 生成证书命令...
在uboot中添加自己的命令...
gcc编译时有卡住的现象,cc1占...
python subprocess Popen
Linux环境变量
test123
编写安全代码——小心有符号数...
彻底搞定C语言指针详解-完整版...
使用openssl api进行加密解密...
一段自己打印自己的c程序...
linux dhcp peizhi roc
关于Unix文件的软链接
求教这个命令什么意思,我是新...
sed -e "/grep/d" 是什么意思...
谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
sunjiangang-ok2011-07-01 08:31:20
有关僵尸进程的东西,可以参考
http://hi.baidu.com/wwang634/blog/item/340830f93e21425e252df27f.html
回复 | 举报
评论热议
题目2:通过管道模拟shell命令:cat file | sort 涉及主要知识点:未命名管道、重定向 题目描述:具体模拟一个shell命令:cat file | sort。具体的一些提示在后面。 提示:首先在当前目录下创建一个名为”file”的文件,里面的内容输入如下:99123892121342893276 通过执行”cat file | sort”后的结果如下:12123134232768989299 现在我们需要通过一个管道,将”cat file”的结果通过管道送给命令”sort”。其中,将”cat file”命令的输出结果重定向到”sort”命令的输入是由包含在命令中的管道标志”|”来完成的。为了在程序当中实现类似的功能,需要用dup()或者dup2()系统调用将标准输入和标准输出联系起来,具体的系统调用使用可以通过man手册来查,或者查阅群共享里面的函数手册。另外,这里的”cat file”和”sort”命令不是自己来完成,而是通过调用exec函数族来实现的,具体的exec()函数族的使用不再啰嗦。扩展:实现两个管道
今天下午仔细一琢磨,发现这个题目当中,没有把创建进程说明,怪不得当初其他人做这个题目时,有许多疑问,原来是我的题目出现了问题。自己下午实现了一下,程序代码如下:#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
int main()
{
int fd[2], res;
pid_t pid;
res = pipe(fd);
if(res == -1) {
perror("Pipe error!");
exit(1);
}
pid = fork();
if(pid > 0) {
close(fd[1]);
dup2(fd[0], 0);
execl("/usr/bin/sort", "sort", (char *)0);
wait(NULL);
exit(0);
} else if(pid == 0) {
dup2(fd[1], 1);
close(fd[0]);
execl("/bin/cat", "cat", "file", NULL);
exit(0);
} else {
perror("Fork error!");
exit(2);
}
}
我当初出这个程序的目的主要是想把管道应用起来,然后想让大家能够把重定向带出来,而且我发现许多有关linux C语言的书上基本都有这种类似的题目,所以我觉得这个题目挺好的。 说一下我的思路吧,针对这个题,首先得把"cat file | sort"这个命令搞清楚,应该明确:这里有两个进程,而不是一个进程,其实我原先把题目在无意当中暗示了只有一个进程。在程序当中,创建一个进程之后,子进程将会执行“cat file”命令,而父进程会执行“sort”命令。在子进程当中,会通过重定向"dup2(fd[1], 1)",将标准输出重定向到管道的写端,说通俗一些,就是以后对于标准输出的操作都就改为对管道的写端的操作了,如果对这里还是不能够理解的话,请查看我的前一篇“通过文件共享来学习I/O重定向(下)——I/O重定向”。对于父进程而言,也是通关重定向“dup2(fd[0], 0)”,将标准输入重定向到管道的读端,以后对于标准输入的操作都就改为了对于fd[0]的操作了。通过这么解释,应该对于上面的程序清楚了吧,下面把我调试的过程当中发现的一些问题总结一下。 1.execl()函数执行之后,该进程成为什么进程了?对于这个问题的回答,我们可以通过修改上面的程序来实现,把父进程调用execl()函数之前加一个sleep(5)函数,即,if(pid > 0) {
close(fd[1]);
dup2(fd[0], 0); //修改的内容
execl("/usr/bin/sort", "sort", (char *)0);
wait(NULL);
exit(0);
} else if(pid == 0) {
在一个终端执行这个程序,在5秒之内打开另外一个终端,执行“ps -au”,并分析其结果,发现有这么几条记录:sunny 5107 0.0 0.0 1616 308 pts/0 S+ 21:36 0:00 ./a.outsunny 5108 0.0 0.0 0 0 pts/0 Z+ 21:36 0:00 [cat] sunny 5109 0.0 0.1 2716 1072 pts/2 R+ 21:37 0:00 ps -au 在其中有一个标识,说明出现了僵尸进程。 上面的测试,是让子进程去执行“execl()”函数的时候,父进程等待等待5s,然后在另外一个终端下查看子进程成了什么样的进程,结果是僵尸进程。等整个程序执行完毕之后,发现僵尸进程消失了,那么僵尸进程是如何消失的呢?这个目前我还没有弄明白,希望大家指教(对于popen()出现僵尸进程之后,会通过close()函数来退出,但是这里的话,好像没有close()函数调用,那它是如何退出呢?)。2.出现僵尸进程之后,那么下面的代码还执行吗?答案是不执行。这次我们修改子进程的代码:} else if(pid == 0) {
dup2(fd[1], 1);
close(fd[0]);
execl("/bin/cat", "cat", "file", NULL);
printf("fffffffffffffffffffffff"); //运行之后,发现这句没有执行
exit(0);
} else {
为什么会不执行了,我是这样猜想的,当子进程去执行“cat”命令时,执行完之 后,它成了僵尸进程,之后它退出了,但是如何退出的? 我在网上找到了有关进程一生的描述:随着一句fork,一个新进程呱呱落地,但它这时只是老进程的一个克隆。然后随着exec,新进程脱胎换骨,离家独立,开始了为人民服务的职业生涯。人有生老病死,进程也一样,它可以是自然死亡,即运行到main函数的最后一个”}”,从容地离我们而去;也可以是自杀,自杀有2种方式,一种是调用 exit函数,一种是在main函数内使用return,无论哪一种方式,它都可以留下遗书,放在返回值里保留下来;它还甚至能可被谋杀,被其它进程通过 另外一些方式结束他的生命。进程死掉以后,会留下一具僵尸,wait和waitpid充当了殓尸工,把僵尸推去火化,使其最终归于无形。这里遗书中的内容是在进程列表中保留一个位置,记载该进程的退出状态等信息供其他 进程收集,除此之外,僵尸进程不再占有任何内存空间。 看到这里,我明白了,子进程成为僵尸进程的原因是由于没有进行“遗书”回收造成的,为了证实我的想法,我们继续将父进程要执行的代码修改如下:if(pid > 0) {
close(fd[1]);
dup2(fd[0], 0);
wait(NULL);
sleep(3);
execl("/usr/bin/sort", "sort", (char *)0);
printf("ffffffffffffffff\n");
exit(0);
} else if(pid == 0) {
这时,当父进程等待3s的时候,在另外一个终端使用ps查看的时候,法相那个僵尸进程不见了,这说明我们对产生的僵尸进程进行了回收。但是,这时候,当sleep()执行完了之后,父进程自己又成了僵尸进程,它会被谁回收呢?当我们程序当中的父进程成为僵尸进程之后,它会把自己的遗书交给它的父进程,应该是在shell中执行那个程序的进程吧,所以,它应该是由执行它的那个shell进程回收的。
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(3988) | 评论(1) | 转发(0) |
0
上一篇:ubuntu中解压rar文件 及遇到乱码的解决方法
下一篇:linux(ubuntu)下外接投影仪或着显示器的方法
相关热门文章
strongswan 生成证书命令...
在uboot中添加自己的命令...
gcc编译时有卡住的现象,cc1占...
python subprocess Popen
Linux环境变量
test123
编写安全代码——小心有符号数...
彻底搞定C语言指针详解-完整版...
使用openssl api进行加密解密...
一段自己打印自己的c程序...
linux dhcp peizhi roc
关于Unix文件的软链接
求教这个命令什么意思,我是新...
sed -e "/grep/d" 是什么意思...
谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
sunjiangang-ok2011-07-01 08:31:20
有关僵尸进程的东西,可以参考
http://hi.baidu.com/wwang634/blog/item/340830f93e21425e252df27f.html
回复 | 举报
评论热议
相关文章推荐
- 通过管道和重定向实现linux管道命令
- 通过管道和重定向实现linux管道命令(二)
- 通过管道和重定向实现linux管道命令(二)
- shell 之 tee 命令,实现重定向到文件的同时仍能 通过管道 (|)传给接下来的命令
- Linux中shell命令实现输出重定向
- Linux强大的IO重定向和管道功能(内含命令替换,实例:批量删除文件)
- LINUX常用命令--重定向、管道篇(四)
- linux进程间通过管道通信实现简单的tftp
- Linux中重定向及管道(ubuntu 终端命令)
- 【Linux常用指令整理8】别名、输入/输出重定向、管道、命令连接符、命令替换符
- Linux基本配置和管理 2 ---- Linux多命令协作----管道及重定向
- 【每天一个Linux命令】04. Linux中管道命令与重定向区别
- Linux多命令协作:管道及重定向
- linux下通过dup2标准输出重定向查看系统进程方法(也是popen函数实现的方法)
- Linux基本配置和管理 2 ---- Linux多命令协作----管道及重定向
- linux下通过字符模块实现类似ps命令的查看系统进程方法
- linux命令温故知新:输入输出重定向/管道
- Linux 变干边学 学习笔记之Linux进程、管道和重定向命令
- linux学习入门17——LINUX多命令协作、管道及重定向(linuxcast.net)
- Linux多命令协作:管道及重定向