2

我正在研究 Applepopen()https://opensource.apple.com/source/Libc/Libc-167/gen.subproj/popen.c.auto.html上的实施,并注意到他们这样做execl(_PATH_BSHELL, "sh", "-c", command, NULL)而不是execl(_PATH_BSHELL, command, NULL).

为什么您想要(或应该)执行一个可执行文件,例如a.out通过sh -c而不是可执行文件本身?

如果您执行sh -c a.out而不是仅执行a.out自身,那么实际a.out进程是否最终成为“孙”进程而不是进程?

4

2 回答 2

2

为什么您想要(或应该)执行一个可执行文件,例如a.out通过sh -c而不是可执行文件本身?

popen()旨在运行包含 shell 语法的 shell 命令,如>重定向、|管道和&&命令链。它需要传递字符串sh -c以支持这些构造。如果没有,这些句法特征将作为参数逐字传递给相关程序。

例如,popen("make clean && make")应该触发两次make调用。没有sh -c它会make用三个参数调用一次,就好像一个人输入了

$ make clean '&&' make

在终端。

如果您执行sh -c a.out而不是仅执行a.out自身,那么实际a.out进程是否最终成为“孙”进程而不是进程?

对,那是正确的。在sh当前进程和a.out.

于 2020-10-01T21:27:48.053 回答
0

他们这样做execl(_PATH_BSHELL, "sh", "-c", command, NULL)而不是execl(_PATH_BSHELL, command, NULL)

后者不会command直接执行,而是_PATH_BSHELL( /bin/sh)$0设置为command并且没有参数,导致 shell 期望来自其标准输入的命令。

此外,该语法依赖于NULL被定义为显式指针(例如((void*)0)),而不仅仅是0,在任何地方都不能保证。虽然他们可以在他们的实现中做到这一点(因为他们控制所有的标题),但这不是你应该在应用程序代码中做的。

不,execl(command, command, (void*)NULL)也不会command直接执行,除非commanda)完整路径和b)以可执行格式(二进制或以 she-bang 开头的脚本#!- 后者是非标准扩展名)。如果command是要在其中查找的简单命令名称PATH(如pwdor a.out)或不以 she-bang 开头的可执行脚本,则应该使用execlp而不是execl.

这些函数完成了shellexec[lv]p[e]所做的一些事情(比如查看. 请注意,使用 it's ,而不是用户的登录 shell 或使用的环境。PATHsystem(3)popen(3)/bin/sh -c/bin/sh$SHELL

如果您执行sh -c a.out而不是仅执行a.out自身,那么实际a.out进程是否最终成为“孙”进程而不是子进程?

只有一些像dash. 不使用bash, ksh93, mksh, zsh, yash,busybox等,它将a.out直接执行而不是分叉并等待它。

于 2020-10-02T02:08:35.013 回答