【发布时间】:2022-01-20 07:24:10
【问题描述】:
我想在 C 程序中执行另一个程序。由于我想使用重定向,我使用 execl 函数来执行 /bin/sh 并将新命令传递给它。代码是这样的:
execl("/bin/sh", "/bin/sh", "-c", "/myprogram > a.out", NULL);
我知道 C 程序进程将在第一阶段变成 shell(/bin/sh) 进程。令我困惑的是,新的 shell 进程是 fork 一个新进程来执行“/myprogram > a.out” 还是 shell 进程本身解析并变成“/myprogram > a.出”。
我对此做了一个小测试。结果似乎支持后一种假设。测试是这样的:
-
我在我的电脑上启动了一个zsh,运行命令
echo $$,结果是56341。这个shell的pid是56341$ echo $$ 56341 -
然后在这个 shell 中运行命令
/bin/sh -c "/Users/Jack/dead_loop"。它不会返回,因为程序是一个永远循环。$ /bin/sh -c "/Users/Jack/dead_loop" █dead_loop源码为:
int main(){ while(1){ ; } } -
我启动一个新终端并运行命令
ps -ef|grep dead_loop。结果显示dead_loop程序的父进程是第一个shell进程。
我期望dead_loop 程序的父进程是另一个新的shell 进程。于是我想到了这个“shell进程本身解析并变成/myprogram > a.out”的想法。
【问题讨论】:
-
shell 将为
/myprogram创建一个新进程。你也可以在你的 C 程序中实现重定向,那么你就不需要 shell。 (见dup2或dup) -
由于shell本身不能运行二进制代码,所以除了fork之外别无选择。但是,如果您要执行
"exec /myprogram",它会替换一个运行/myprogram的新进程,并且不会创建子进程。 -
我相信一些 shell 实现了一种优化,它们也执行自己并且不会产生一个孩子,但你当然不应该依赖它。如果需要保证没有中间过程,自己做重定向就行了。实施这将是一个很好的练习。 (这很容易。)