免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 19727 | 回复: 20
打印 上一主题 下一主题

[woodie等兄惠存]关于bash的管道与进程的几个知识点 [复制链接]

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-04-07 09:14 |只看该作者 |倒序浏览
几个知识点
1.Bash在实现pipeline(管道|)时会发起两个subshell(子shell)来运行|两边的命令,对于系统来说就是发起两个childprocess(子进程)

2.fork是产生process的唯一途径,exec*是执行程序的唯一途径

3.子进程会完全复制父进程,除了$PID与$PPID

4.fork子进程时继承父进程的进程名,在exec*执行命令时才由exec*替换为子进程对应的命令,同一进程的命令名可以由一个个exec*任意多次的改变



[注]对于linux平台,JB上就是这样的,其它平台不好发表意见,当然对于2中的两个唯一有一个例外,就是在kenerl  init的初期;
暂时找不到相关参考,也没有功力读源码,所以此论是道听途说级别,错误之处请指出改正,如果没有改正的价值可一笑而过


[ 本帖最后由 waker 于 2006-4-7 09:17 编辑 ]

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
2 [报告]
发表于 2006-04-07 09:15 |只看该作者

问题的发生

当时的情况是:大家在讨论一个与进程统计的问题
http://bbs.chinaunix.net/viewthread.php?tid=731435&extra=page%3D1
思考了一刻钟后我作了一个习惯性的决定:简化一下这个问题
下面的脚本 get_process

  1. #!/bin/bash
  2. ps -ef|grep get_process
复制代码

运行./get_process后会得到什么结果

结果有三种

  1. waker     3260  3193  0 08:47 pts/1    00:00:00 /bin/bash ./get_process
复制代码

  1. waker     3290  3193  0 08:48 pts/1    00:00:00 /bin/bash ./get_process
  2. waker     3292  3290  0 08:48 pts/1    00:00:00 /bin/bash ./get_process
复制代码

  1. waker     3263  3193  0 08:48 pts/1    00:00:00 /bin/bash ./get_process
  2. waker     3265  3263  0 08:48 pts/1    00:00:00 grep get_process
复制代码

大家产生了种种解释
其实大家离真相只有0.01mm的距离
让我来提示一下
观察三种结果,都有一个共同的进程,就是PPID 是3193的 /bin/bash ./get_process
那么3193是什么
只要echo $$就可以看出3193就是我们键入 ./get_process的shell

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
3 [报告]
发表于 2006-04-07 09:15 |只看该作者

我的解释

让我们参照四个知识点来解释这个现象
首先当前shell 3193发起一个subshell来执行脚本./get_process
这个进程pid 3290 进程名 /bin/bash ./get_process
然后当它遇到管道,将发起两个子进程 3291(用来执行ps) 3192(用来执行grep),这两个进程是并行的
让我们给3192来个慢镜头


  1.            史前时代                   fork                                       exec*(grep.*)
  2. pid          N/A                               3192
  3. 进程名       N/A        /bin/bash ./get_process                  grep get_process
  4. 说明         N/A       这个进程名继承自父进程                          exec*将进程名替换
复制代码


而用3291中的ps来观察这个进程的时候,由于两个子进程的并行,每一种状态都可能被ps看到,当然每次只能看到一种状态
所以结果会有三种情况
进程3290(/bin/bash ./get_process)
与下面三种可能的组合
1.空
2.子进程3292 进程名 /bin/bash ./get_process
3.子进程3292 进程名 grep get_process

[ 本帖最后由 waker 于 2006-4-7 09:18 编辑 ]

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
4 [报告]
发表于 2006-04-07 09:20 |只看该作者

作业

1.如何避免发起不想要的subshell?
2.如果在kornshell中,这种情况会发生么?

论坛徽章:
7
荣誉版主
日期:2011-11-23 16:44:17子鼠
日期:2014-07-24 15:38:07狮子座
日期:2014-07-24 11:00:54巨蟹座
日期:2014-07-21 19:03:10双子座
日期:2014-05-22 12:00:09卯兔
日期:2014-05-08 19:43:17卯兔
日期:2014-08-22 13:39:09
5 [报告]
发表于 2006-04-07 10:49 |只看该作者
2.如果在kornshell中,这种情况会发生么?
依然会发生,除非管道中最后一个命令时内部命令。

论坛徽章:
0
6 [报告]
发表于 2006-04-07 11:05 |只看该作者
1.如何避免发起不想要的subshell?
定义变量,虽然很笨但应该可以解决问题

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
7 [报告]
发表于 2006-04-07 11:26 |只看该作者
to 7兄:
我在kornshell中测试的结果是永远都ps出两个进程
get_process与grep

论坛徽章:
7
荣誉版主
日期:2011-11-23 16:44:17子鼠
日期:2014-07-24 15:38:07狮子座
日期:2014-07-24 11:00:54巨蟹座
日期:2014-07-21 19:03:10双子座
日期:2014-05-22 12:00:09卯兔
日期:2014-05-08 19:43:17卯兔
日期:2014-08-22 13:39:09
8 [报告]
发表于 2006-04-07 12:14 |只看该作者
我的回复就是指进程数没有区别,为什么总是出现grep,可能是概率问题,也可能是ksh的机理造成的永远都是grep。

论坛徽章:
0
9 [报告]
发表于 2006-11-20 10:36 |只看该作者
ksh下没看到
waker     3292  3290  0 08:48 pts/1    00:00:00 /bin/bash ./get_process
这个进程的原因大概是因为此进程的cmd被写成了ps -ef吧
由于shell脚本本身必然会fork process,就不必监控了,可以改成
  1. #!/bin/bash
  2. ps -ef|grep -w ps
复制代码

这样来看,应该更清楚。
在我的环境
FC6
bash(GNU bash, version 3.1.17(1)-release (i686-redhat-linux-gnu))
ksh(  version         sh (AT&T Labs Research) 1993-12-28 r)
下测试获得完全一样的结论

论坛徽章:
0
10 [报告]
发表于 2008-09-12 18:58 |只看该作者
原帖由 waker 于 2006-4-7 09:14 发表
几个知识点
1.Bash在实现pipeline(管道|)时会发起两个subshell(子shell)来运行|两边的命令,对于系统来说就是发起两个childprocess(子进程)

2.fork是产生process的唯一途径,exec*是执行程序的唯一途径

...



这第三条太武断了,除了PID和PPID外,还有好多不同
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP