关于system的一个疑问
时间:2011-08-09
来源:互联网
最近研究unix环境高级编程,看到信号这一章,书中关于system函数的说明,有一点颇为费解
按照书中所述,system的实现,是一个fork->exec的标准流程,而在system函数的代码清单中可以看到,exec的实现大致如下
execl("/bin/sh","sh","-c",cmdstring,(char *)0)
cmdstring即向system传入的命令字符串
现在我们假设程序A调用了system,此时A fork出了子进程,称之为B吧,B执行execl,启动shell,然后由shell来fork和exec我们的cmdstring命令,因此,实际上执行cmdstring命令的进程应该是shell进程-B的子进程,而不是A的子进程,把这个进程称之为C吧.按照这个想法,A的system返回值应该是B(shell)的结束状态,而不是C的结束状态
下面是一段试验代码
C/C++ code
程序名为tsys,执行tsys "sleep 30",随后键入中断符和退出符,结果分别为
abnormal termination, signal number = 2
abnormal termination, signal number = 3
直接打印出了SIGINT和SIGQUIT的信号编号,而不是Bourne shell在终止状态上会在信号编号加上128的结果
再执行tsys "sleep 30" &,转为后台执行,然后 ps -f 打印进程间关系,结果如下
UID PID PPID C STIME TTY TIME CMD
1013 7500 7498 0 14:34 pts/2 00:00:00 -bash
1013 25506 7500 0 16:58 pts/2 00:00:00 ./tsys sleep 30
1013 25507 25506 0 16:58 pts/2 00:00:00 sleep 30
1013 25527 7500 0 16:58 pts/2 00:00:00 ps -f
可以看到进程C-sleep(25507)的父进程直接就是进程A-tsys(25506),并没有找到预期的进程B-shell进程
跟书上讲的不一致,这下就彻底迷茫了,求大佬指点
按照书中所述,system的实现,是一个fork->exec的标准流程,而在system函数的代码清单中可以看到,exec的实现大致如下
execl("/bin/sh","sh","-c",cmdstring,(char *)0)
cmdstring即向system传入的命令字符串
现在我们假设程序A调用了system,此时A fork出了子进程,称之为B吧,B执行execl,启动shell,然后由shell来fork和exec我们的cmdstring命令,因此,实际上执行cmdstring命令的进程应该是shell进程-B的子进程,而不是A的子进程,把这个进程称之为C吧.按照这个想法,A的system返回值应该是B(shell)的结束状态,而不是C的结束状态
下面是一段试验代码
C/C++ code
#include "apue.h" #include <sys/wait.h> int main(int argc, char *argv[]) { int status; if(argc < 2) err_quit("command-line argument required"); if((status = system(argv[1])) < 0) err_sys("system() error"); pr_exit(status); exit(0); }
程序名为tsys,执行tsys "sleep 30",随后键入中断符和退出符,结果分别为
abnormal termination, signal number = 2
abnormal termination, signal number = 3
直接打印出了SIGINT和SIGQUIT的信号编号,而不是Bourne shell在终止状态上会在信号编号加上128的结果
再执行tsys "sleep 30" &,转为后台执行,然后 ps -f 打印进程间关系,结果如下
UID PID PPID C STIME TTY TIME CMD
1013 7500 7498 0 14:34 pts/2 00:00:00 -bash
1013 25506 7500 0 16:58 pts/2 00:00:00 ./tsys sleep 30
1013 25507 25506 0 16:58 pts/2 00:00:00 sleep 30
1013 25527 7500 0 16:58 pts/2 00:00:00 ps -f
可以看到进程C-sleep(25507)的父进程直接就是进程A-tsys(25506),并没有找到预期的进程B-shell进程
跟书上讲的不一致,这下就彻底迷茫了,求大佬指点
作者: naruto2202 发布时间: 2011-08-09
应该没有B这个过程吧,fork出新的进程空间,直接execl加载进去命令就可以执行了,不需要新启动一个shell。
execl("/bin/sh","sh","-c",cmdstring,(char *)0)
这个只是表示用/bin/sh来解释这个命令而已。
execl("/bin/sh","sh","-c",cmdstring,(char *)0)
这个只是表示用/bin/sh来解释这个命令而已。
作者: louyong0571 发布时间: 2011-08-09
书上讲的是先fork,然后子进程中execl。
但是execl并不是创建新的进程,execl只是以一个新的进程“代替”之前的子进程。所以说execl出来的进程代替了你的A创建的子进程。所以它的父进程就是A
但是execl并不是创建新的进程,execl只是以一个新的进程“代替”之前的子进程。所以说execl出来的进程代替了你的A创建的子进程。所以它的父进程就是A
作者: dongjiawei316 发布时间: 2011-08-09
多谢楼上两位的解答,其实之前也有这样想过,可能execl出来的直接就是cmdstring命令表示的进程,但是这样的话,execl的第一个参数直接赋成cmdstring岂不是更简洁?何必再多调一层"/bin/sh"
另外,书上有几句原话,也是写的比较明显的
p279:
还有,关于几个进程的关系-p280:
可以看到进程C-sleep(9259)的父进程就是进程B-sh(9258),而非进程A-tsys(9257)
另外,书上有几句原话,也是写的比较明显的
p279:
还有,关于几个进程的关系-p280:
可以看到进程C-sleep(9259)的父进程就是进程B-sh(9258),而非进程A-tsys(9257)
作者: naruto2202 发布时间: 2011-08-09
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28