为什么popen()调用Shell来执行进程? [英] Why does popen() invoke a shell to execute a process?

查看:211
本文介绍了为什么popen()调用Shell来执行进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在阅读并尝试从Linux上的C代码中运行程序的各种可能性.我的用例涵盖了所有可能的场景,从简单地运行和忘记流程,从写入到流程,到从写入到流程.

I'm currently reading up on and experimenting with the different possibilities of running programs from within C code on Linux. My use cases cover all possible scenarios, from simply running and forgetting about a process, reading from or writing to the process, to reading from and writing to it.

对于前两个,popen()非常易于使用并且运行良好.我知道它在内部使用了某些版本的fork()exec(),然后调用了一个shell来实际运行命令.

For the first two, popen() is very easy to use and works well. I understand that it uses some version of fork() and exec() internally, then invokes a shell to actually run the command.

在第三种情况下,popen()不是一个选项,因为它是单向的.可用的选项是:

For the third scenario, popen() is not an option, as it is unidirectional. Available options are:

  • 手动fork()exec(),以及pipe()dup2()用于输入/输出
  • posix_spawn(),根据需要在内部使用上述内容
  • Manually fork() and exec(), plus pipe() and dup2() for input/output
  • posix_spawn(), which internally uses the above as need be

我注意到这些可以实现与popen()相同的功能,但是我们可以完全避免调用其他sh.这听起来很合意,因为它似乎不太复杂.

What I noticed is that these can achieve the same that popen() does, but we can completely avoid the invoking of an additional sh. This sounds desirable, as it seems less complex.

但是,我注意到甚至posix_spawn() 上的示例确实调用了shell,因此看来它一定有好处.如果要解析命令行参数,wordexp()似乎同样出色.

However, I noticed that even examples on posix_spawn() that I found on the Internet do invoke a shell, so it would seem there must be a benefit to it. If it is about parsing command line arguments, wordexp() seems to do an equally good job.

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

What is the reason behind benefit of invoking a shell to run the desired process instead of running it directly?

编辑:我意识到我对这个问题的措词并不能完全反映我的实际兴趣-我对通过sh好处更加好奇比(历史上的)原因要好,尽管两者显然是相互联系的,所以两种变化的答案都是同等重要的.

Edit: I realized that my wording of the question didn't precisely reflect my actual interest - I was more curious about the benefits of going through sh rather than the (historical) reason, though both are obviously connected, so answers for both variations are equally relevant.

推荐答案

调用shell可以使您完成在shell中可以做的所有事情. 例如,

Invoking a shell allows you to do all the things that you can do in a shell. For example,

FILE *fp = popen("ls *", "r");

使用popen()可以使用

(扩展当前目录中的所有文件). 与以下内容进行比较:

is possible with popen() (expands all files in the current directory). Compare it with:

execvp("/bin/ls", (char *[]){"/bin/ls", "*", NULL});

您不能使用*作为参数执行ls,因为exec(2)将按字面意义解释*.

You can't exec ls with * as argument because exec(2) will interpret * literally.

类似地,popen也可以使用管道(|),重定向(><,...)等.

Similarly, pipes (|), redirection (>, <, ...), etc., are possible with popen.

否则,如果您不需要外壳,则没有理由使用popen-这是不必要的.您将最终获得一个额外的Shell进程,并且Shell中所有可能出错的事情都可能在您的程序中出错(例如,您传递的命令可能会被Shell错误地解释,并且是一个常见的安全问题). popen()是以此方式设计的. fork + exec解决方案更干净,没有与外壳相关的问题.

Otherwise, there's no reason to use popen if you don't need shell - it's unnecessary. You'll end up with an extra shell process and all the things that can go wrong in a shell go can wrong in your program (e.g., the command you pass could be incorrectly interpreted by the shell and a common security issue). popen() is designed that way. fork + exec solution is cleaner without the issues associated with a shell.

这篇关于为什么popen()调用Shell来执行进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆