【问题标题】:using exec to execute a system command in a new process使用 exec 在新进程中执行系统命令
【发布时间】:2011-04-12 06:32:05
【问题描述】:

我正在尝试生成一个执行系统命令的进程,而我自己的程序仍在继续,两个进程将并行运行。我正在研究Linux。

我在网上查了一下,听起来我应该使用 exec() 系列。但它并不像我预期的那样工作。例如,在下面的代码中,我只看到“之前”被打印,而不是“完成”。

我很好奇我是否在发什么东西?

#include <unistd.h>
#include <iostream>

using namespace std;

main()
{
   cout << "before" << endl;
   execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);
   cout << "done" << endl;
}

[更新]

感谢你们的 cmets。现在我的程序看起来像这样。一切正常,除了最后,我必须按 Enter 键才能完成程序。我不知道为什么我必须按最后一个输入?

#include <unistd.h>
#include <iostream>

using namespace std;

main()
{
   cout << "before" << endl;
   int pid = fork();
   cout << pid << endl;
   if (pid==0) {
      execl("/bin/ls", "ls", "-r", "-t", "-l", (char *) 0);
   }
   cout << "done" << endl;
}

【问题讨论】:

  • 你的主要应该是int main,最后你应该添加一个return 0;,你的编译器可能会填写最后,并添加“按任意按钮继续”最后

标签: c++ linux process parallel-processing exec


【解决方案1】:

您错过了对fork 的呼叫。 exec 所做的只是用新程序替换当前进程映像。使用fork 生成当前进程的副本。它的返回值会告诉你运行的是孩子还是原来的父母。如果是孩子,请致电exec


一旦您进行了更改,它只会显示您需要按 Enter 键才能完成程序。实际情况是这样的:父进程分叉并执行子进程。两个进程都运行,并且两个进程同时打印到标准输出。他们的输出是乱码。父进程比子进程要做的事少,所以它先终止。当它终止时,正在等待它的 shell 将唤醒并打印通常的提示。同时,子进程仍在运行。它打印更多的文件条目。最后,它终止。 shell 没有注意子进程(它的孙子进程),所以 shell 没有理由重新打印提示。仔细查看你得到的输出,你应该能够在上面的ls 输出中找到你常用的命令提示符。

光标出现正在等待您按下某个键。当你这样做时,shell 会打印一个提示,一切看起来都很正常。但就外壳而言,一切都已经正常了。您之前可以输入另一个命令。它看起来有点奇怪,但 shell 会正常执行它,因为它只接收来自键盘的输入,而不是来自向屏幕打印额外字符的子进程。

如果您在单独的控制台窗口中使用top 之类的程序,您可以观察并确认两个程序都已完成运行,然后再按 Enter。

【讨论】:

    【解决方案2】:

    Exec 系列函数将当前进程替换为新的可执行文件。

    要执行您需要的操作,请使用 fork() 函数之一并让子进程 exec 新图像。

    [响应更新]

    它完全按照你说的去做:你不必按“enter”来完成程序:它已经退出了。 shell已经给出了提示:

    [wally@zenetfedora ~]$ ./z
    before
    22397
    done
    [wally@zenetfedora ~]$ 0               << here is the prompt (as well as the pid)
    total 5102364
    drwxr-xr-x.  2 wally wally       4096 2011-01-31 16:22 Templates
    ...
    

    ls 的输出需要一段时间,所以它隐藏了提示。如果您希望输出以更合乎逻辑的顺序出现,请在“完成”之前添加sleep(1)(或更长)。

    【讨论】:

    • 应该为孩子添加一个wait,而不是sleep真的
    【解决方案3】:

    您错过了 execl() 将内存中的当前程序替换为 /bin/ls 的部分

    我建议查看popen(),它将分叉并执行一个新进程,然后让您通过管道读取或写入它。 (或者如果你需要读写,fork()自己,然后exec()

    【讨论】:

      猜你喜欢
      • 2016-05-31
      • 2011-03-12
      • 2011-03-29
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 2012-08-18
      • 2021-09-07
      相关资源
      最近更新 更多