【问题标题】:If execv launches a process using "/bin/sh -c", will there be a new process?如果 execv 使用“/bin/sh -c”启动一个进程,会不会有一个新进程?
【发布时间】: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.出”

我对此做了一个小测试。结果似乎支持后一种假设。测试是这样的:

  1. 我在我的电脑上启动了一个zsh,运行命令echo $$,结果是56341。这个shell的pid是56341

    $ echo $$
    56341
    
  2. 然后在这个 shell 中运行命令/bin/sh -c "/Users/Jack/dead_loop"。它不会返回,因为程序是一个永远循环。

    $ /bin/sh -c "/Users/Jack/dead_loop"
    █
    

    dead_loop源码为:

    int main(){
        while(1){
            ;
        }
    }
    
  3. 我启动一个新终端并运行命令ps -ef|grep dead_loop。结果显示dead_loop程序的父进程是第一个shell进程。

我期望dead_loop 程序的父进程是另一个新的shell 进程。于是我想到了这个“shell进程本身解析并变成/myprogram > a.out”的想法。

【问题讨论】:

  • shell 将为/myprogram 创建一个新进程。你也可以在你的 C 程序中实现重定向,那么你就不需要 shell。 (见dup2dup
  • 由于shell本身不能运行二进制代码,所以除了fork之外别无选择。但是,如果您要执行"exec /myprogram",它会替换一个运行/myprogram 的新进程,并且不会创建子进程。
  • 我相信一些 shell 实现了一种优化,它们也执行自己并且不会产生一个孩子,但你当然不应该依赖它。如果需要保证没有中间过程,自己做重定向就行了。实施这将是一个很好的练习。 (这很容易。)

标签: c shell exec


【解决方案1】:

请记住,exec 系列函数替换当前进程。

您必须使用fork 创建一个新进程来运行exec(如果您希望程序继续运行)。

shell 也一样:它还必须fork 一个新进程来为它运行的程序调用exec

【讨论】:

  • 我用一个可能不同意你意见的小测试更新了我的问题。
  • @jack William Pursell 有一条评论(对您的问题),它解释了正在发生的事情。您的测试确实与此答案相矛盾,但它无法支持您得出的结论(这是不正确的)。您提到的两种可能的机制并不详尽。还有第三种可能性,就是威廉提到的那个。
猜你喜欢
  • 1970-01-01
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多