免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Minsic
打印 上一主题 下一主题

关于subshell和child process的问题 [复制链接]

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015年亚洲杯之朝鲜
日期:2015-03-13 22:47:33IT运维版块每日发帖之星
日期:2016-01-09 06:20:00IT运维版块每周发帖之星
日期:2016-03-07 16:27:44
21 [报告]
发表于 2009-07-23 18:26 |只看该作者

回复 #19 Minsic 的帖子

没有export的变量后续非nested subshell是看不到的。

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015年亚洲杯之朝鲜
日期:2015-03-13 22:47:33IT运维版块每日发帖之星
日期:2016-01-09 06:20:00IT运维版块每周发帖之星
日期:2016-03-07 16:27:44
22 [报告]
发表于 2009-07-23 18:31 |只看该作者

回复 #16 Minsic 的帖子

更正:fork 和 exec是两个独立的系统调用,通常配合使用,但也可单独调用。

越搞越复杂了。

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-01-24 06:20:00
23 [报告]
发表于 2009-07-23 18:40 |只看该作者

回复 #20 ILoveMK 的帖子

看了,看到一半就找到了答案,我晕啊~~

code inside a nested subshell obeys the above rules of subshell inheritance, except that it knows about variables defined in the surrounding shell


我搞了一天,要的就是这么一句话啊,这话现在说可能会让人觉得恬不知耻:其实我一开始就想这么认为——就是说()和script subshell对变量的处理不一样,忽悠自己过去的,但是思前想后啊,又想到fork和exec上面去了,也好,顺便把这两个也理个顺

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-01-24 06:20:00
24 [报告]
发表于 2009-07-23 18:46 |只看该作者
原帖由 blackold 于 2009-7-23 18:26 发表
没有export的变量后续非nested subshell是看不到的。


恩,谢猫头鹰的链接。以前学bourne shell的时候,很少有书讲到nested subshell,所以根本就没注意到过这个问题,subshell要用的变量一律export的,学习bash的时候经常看到(),对它和它能继承父shell的非环境变量处理很奇怪,现在终于明白了 ~~

原帖由 blackold 于 2009-7-23 18:31 发表
更正:fork 和 exec是两个独立的系统调用,通常配合使用,但也可单独调用。

越搞越复杂了。


这个,我是说nested subshell和script subshell都需要fork-exec的,又不对了?

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015年亚洲杯之朝鲜
日期:2015-03-13 22:47:33IT运维版块每日发帖之星
日期:2016-01-09 06:20:00IT运维版块每周发帖之星
日期:2016-03-07 16:27:44
25 [报告]
发表于 2009-07-24 08:25 |只看该作者
对,这两种情况都是fork-exec啊。

论坛徽章:
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
26 [报告]
发表于 2009-07-24 08:42 |只看该作者

回复 #24 Minsic 的帖子

一个命令不一定要fork,也不一定要exec,俺的回帖不是都穷举过了么?

对于
a=2
echo $a
(echo $a)
里面的两个$a为什么是两个变量,俺是这么理解的,这是逻辑上的,
() fork了一个subshell,()里的$a是从父里程克隆来的,你把一头羊克隆了,你认为现在一共是一头羊还是两头羊?现在一共有一条羊尾巴还是两条羊尾巴?喏,进程就是羊,$a就是羊尾巴


nestsubshell就是显式的fork一个子进程(subshell),至于这个子进程里再干什么是subshell自己的事

至于./script中没有$a的原因,从逻辑上讲,注意是逻辑上的,
./script是个外部命令,它的实现过程是fork一个subshell,然后 exec ./script,在exec时进程的数据和代码都会被外存中的程序代替,非初始化数据也会被清空,你说还有没有$a?但是exec不会影响环境变量的储存区(这块高端的区域用来储存环境表和位置参数),如果你想在exec后保留

论坛徽章:
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
27 [报告]
发表于 2009-07-24 08:45 |只看该作者
如果你想在exec后保留$a,那就把它放到环境表里,shell中的操作就是export a

如果你想在./script中拥有和父shell不同的环境变量,那就用 a=xxx ./script
这时候的逻辑步骤就是
fork > setenv > exec

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-01-24 06:20:00
28 [报告]
发表于 2009-07-24 09:47 |只看该作者
原帖由 waker 于 2009-7-24 08:42 发表
对于
a=2
echo $a
(echo $a)
里面的两个$a为什么是两个变量,俺是这么理解的,这是逻辑上的,
() fork了一个subshell,()里的$a是从父里程克隆来的,你把一头羊克隆了,你认为现在一共是一头羊还是两头羊?现在一共有一条羊尾巴还是两条羊尾巴?喏,进程就是羊,$a就是羊尾巴


我被绕晕了 -_____-

我想先把fork-exec的事情和父子进程间的变量处理分两件不相干的事情来说吧(即使他们有关系),先来说说变量吧:

根据http://www.sch239.spb.ru:8000/info/oreilly/unix/ksh/ch08_06.htm里的说法,()除了继承环境变量外,与一般的subshell不同的是,还能够能够继承父shell的一般变量,那么
a=2
echo $a
(echo $a)

里面的a显然都是同一个变量。

至于waker在27楼提到的:
如果你想在./script中拥有和父shell不同的环境变量,那就用 a=xxx ./script
这时候的逻辑步骤就是
fork > setenv > exec

我倒是有几点不明:
1、如果想要让环境变量a在script subshell中拥有不同的值,那在script中直接重新赋值不就行了么?这么做的意义何在?
2、a=xxx ./script让我想起这个讨论:http://bbs.chinaunix.net/viewthr ... p;extra=&page=1
,这个帖子让我相信:a=b被当做echo命令的一个类似为参数赋值一样的行为,只影响了命令运行的环境而不影响当前的shell;那个帖子也有这个说法:bash在处理a=b echo $a这样的命令时,是在一个subshell中进行的,因此不会影响到当前的shell。同时我习惯性地去bourne shell上去验证这个命令,但结果却是让我大跌眼镜,和bash完全不同的表现:
oracle>uname -a
SunOS sun4800 5.8 Generic_108528-19 sun4u sparc SUNW,Sun-Fire
oracle>ps
   PID TTY      TIME CMD
14922 pts/30   0:00 sh
15416 pts/30   0:00 ps
oracle>a=b echo $a

oracle>echo $a
b
oracle>

看来bourne shell就是在当前shell运行了这条命令的。

下面来说说fork和exec,waker之所以在26楼说这段话:
nestsubshell就是显式的fork一个子进程(subshell),至于这个子进程里再干什么是subshell自己的事

是不是我说的“无论nested subshell和script subshell都需要fork-exec的”这话错了?比如(echo $a)这句话是只有fork的,因为echo(不是/bin/echo)是内部命令,而(/bin/echo $a)是fork-exec,因为/bin/echo是外部命令。如果说是(echo $a;/bin/echo $a),那么先是fork一个nested subshell,然后echo $a就在这个shell上运行,而/bin/echo再fork-exec一个这个nested subshell的subshell,来运行这句/bin/echo $a。那也说明http://bbs.chinaunix.net/viewthr ... ;page=4#pid10717253这个图是正确的吧——不知道是第几次问这张图是否正确了 - -

分别说完前面提到的变量和fork-exec,waker这句话又让我陷入不小的混乱:
./script是个外部命令,它的实现过程是fork一个subshell,然后 exec ./script,在exec时进程的数据和代码都会被外存中的程序代替,非初始化数据也会被清空,你说还有没有$a?但是exec不会影响环境变量的储存区(这块高端的区域用来储存环境表和位置参数),如果你想在exec后保留

waker意思是exec会清除非环境变量?那么你在前面11楼举的这个例子:
(/bin/echo;/bin/echo)首先shell fork一个subshell(子进程一代),由于/bin/echo;/bin/echo不是个简单命令,那就不能节省了,子进程一代fork出子进程二代A,去exec第一个/bin/echo,等它结束后,再fork出子进程二代B,去exec第二条/bin/echo,而命令行的那个shell在等待fork出子进程一代的结束

如果修改一下,改成(/bin/echo $a;/bin/echo $b),你认为在其父shell定义的a和b变量不能被这个nested subshell继承,从而会显示两个空行吗?或许我理解错了26楼关于“exec会清除数据”的那段话?

[ 本帖最后由 Minsic 于 2009-7-24 09:52 编辑 ]

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-01-24 06:20:00
29 [报告]
发表于 2009-07-24 09:58 |只看该作者
一个请求:

能否直接指出我回帖中的错误,让我不要在牛角尖上不停的绕圈子了……

thx~~

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015年亚洲杯之朝鲜
日期:2015-03-13 22:47:33IT运维版块每日发帖之星
日期:2016-01-09 06:20:00IT运维版块每周发帖之星
日期:2016-03-07 16:27:44
30 [报告]
发表于 2009-07-24 10:01 |只看该作者

回复 #28 Minsic 的帖子

长篇?

搞得太乱了,不知从何说起。

不同的shell的处理是不同的,这点必须要清楚。

在bash下: $ a=b echo $a就是在当前shell下执行,怎么又跑到subshell下执行了?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP