为什么popen()调用shell来执行进程?

dom*_*son 9 c linux popen sh

我正在阅读并尝试在Linux上使用C代码运行程序的不同可能性.我的用例涵盖了所有可能的场景,从简单的运行和忘记过程,阅读或写入过程,到阅读和写入过程.

对于前三个,popen()非常容易使用并且运行良好.据我所知,它使用的一些版本fork()和exec()内部,然后调用一个shell实际运行命令.

对于第三种情况,popen()不是一种选择,因为它是单向的.可用选项包括:

  • 手动fork()和exec(),再加上pipe()和dup2()输入/输出
  • posix_spawn(),根据需要在内部使用上述内容

我注意到的是,这些可以达到相同的效果popen(),但我们可以完全避免调用其他内容sh.这听起来很可取,因为它似乎不那么复杂.

但是,我注意到,即使我在Internet 上posix_spawn()找到的示例也会调用shell,因此看起来必须有一个好处.如果它是关于解析命令行参数,wordexp()似乎做同样好的工作.

是什么 背后的原因 调用shell来运行所需进程而不是直接运行它的好处?


编辑:我意识到我的问题措辞没有准确地反映我的实际兴趣 - 我对通过而不是(历史)原因的好处更加好奇,尽管两者显然是相关的,所以两种变化的答案都是一样的相关.sh

P.P*_*.P. 6

调用shell允许您执行在shell中可以执行的所有操作.例如,

FILE *fp = popen("ls *", "r");
Run Code Online (Sandbox Code Playgroud)

可以使用popen()(展开当前目录中的所有文件).比较它:

execvp("/bin/ls", (char *[]){"/bin/ls", "*", NULL});
Run Code Online (Sandbox Code Playgroud)

你不能作为参数执行ls,*因为它exec(2)会按*字面解释.

同样,管(|),重定向(>,<,...),等等,都是可能的popen.

否则,popen如果你不需要shell ,就没有理由使用它 - 这是不必要的.你最终会得到一个额外的shell进程,所有在shell中出错的东西都可能在你的程序中出错(例如,你传递的命令可能被shell错误地解释并且存在常见的安全问题).popen()是这样设计的.fork+ exec解决方案更清晰,没有与shell相关的问题.

  • 为方便起见,请参阅`popen`.它被设计(并且由POSIX***)来调用shell.所以,它和标准的`popen`函数不会改变它的行为.如果您的要求不同,您可以自定义实现自定义要求.但是如果你不需要shell功能,那么使用fork + exec总是更好. (3认同)