+ -
当前位置:首页 → 问答吧 → 关于system的一个疑问

关于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
#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来解释这个命令而已。

作者: louyong0571   发布时间: 2011-08-09

书上讲的是先fork,然后子进程中execl。
但是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)

作者: naruto2202   发布时间: 2011-08-09