Linux 使用 exec 在新进程中执行系统命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5631229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using exec to execute a system command in a new process
提问by Vendetta
I am trying to spawn a process that executes a system command, while my own program still proceeds and two processes will run in parallel. I am working on linux.
我正在尝试生成一个执行系统命令的进程,而我自己的程序仍在继续并且两个进程将并行运行。我在 linux 上工作。
I looked up online and sounds like I should use exec() family. But it doesn't work quite as what I expected. For example, in the following code, I only see "before" being printed, ,but not "done".
我在网上查了一下,听起来我应该使用 exec() 系列。但它并没有像我预期的那样工作。例如,在下面的代码中,我只看到“before”被打印,而不是“done”。
I am curious if I am issing anything?
我很好奇我有什么事情吗?
#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;
}
[UPDATE]
[更新]
Thank you for your guys comments. Now my program looks like this. Everything works fine except at the end, I have to press enter to finish the program. I am not sure why I have to press the last enter?
谢谢你们的评论。现在我的程序看起来像这样。一切正常,除了最后,我必须按 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;
}
采纳答案by Rob Kennedy
You're missing a call to fork
. All exec
does is replace the current process imagewith that of the new program. Use fork
to spawn a copy of your current process. Its return value will tell you whether it's the child or the original parent that's running. If it's the child, call exec
.
你错过了一个电话fork
。所有exec
做的是替换当前的进程映像与新方案。使用fork
产卵您的当前进程的副本。它的返回值会告诉您是正在运行的子进程还是原始父进程。如果是孩子,请致电exec
。
Once you've made that change, it only appearsthat you need to press Enter for the programs to finish. What's actually happening is this: The parent process forks and executes the child process. Both processes run, and both processes print to stdout at the same time. Their output is garbled. The parent process has less to do than the child, so it terminates first. When it terminates, your shell, which was waiting for it, wakes and prints the usual prompt. Meanwhile, the child process is still running. It prints more file entries. Finally, it terminates. The shell isn't paying attention to the child process (its grandchild), so the shell has no reason to re-print the prompt. Look more carefully at the output you get, and you should be able to find your usual command prompt buried in the ls
output above.
进行更改后,似乎只需要按 Enter 即可完成程序。实际发生的事情是这样的:父进程派生并执行子进程。两个进程都运行,并且两个进程同时打印到标准输出。他们的输出是乱码。父进程比子进程要做的事情少,所以它首先终止。当它终止时,等待它的 shell 会唤醒并打印通常的提示。同时,子进程仍在运行。它打印更多的文件条目。最后,它终止。shell 没有关注子进程(它的孙子进程),所以 shell 没有理由重新打印提示。更仔细地查看您得到的输出,您应该能够找到隐藏在ls
上面的输出。
The cursor appearsto be waiting for you to press a key. When you do, the shell prints a prompt, and all looks normal. But as far as the shell was concerned, all was already normal. You could have typed another command before. It would have looked a little strange, but the shell would have executed it normally because it only receives input from the keyboard, not from the child process printing additional characters to the screen.
光标似乎在等待您按下某个键。当你这样做时,shell 会打印一个提示,一切看起来都很正常。但就外壳而言,一切都已经正常了。您之前可以输入另一个命令。它看起来有点奇怪,但 shell 会正常执行它,因为它只接收来自键盘的输入,而不是来自将附加字符打印到屏幕的子进程。
If you use a program like top
in a separate console window, you can watch and confirm that both programs have already finished running before you have to press Enter.
如果您top
在单独的控制台窗口中使用程序,则可以在必须按 Enter 之前观察并确认两个程序都已完成运行。
回答by wallyk
The Exec
family of functions replaces the current process with the new executable.
该Exec
系列函数替换为新的执行当前进程。
To do what you need, use one of the fork()
functions and have the child process exec
the new image.
要执行您需要的操作,请使用其中一个fork()
函数并让子进程处理exec
新图像。
[response to update]
[对更新的回应]
It is doing exactly what you told it: You don't have to press "enter" to finish the program: It has already exited. The shell has already given a prompt:
它完全按照你说的做:你不必按“回车”来完成程序:它已经退出了。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
...
The output from ls
takes awhile so it buries the prompt. If you want output to appear in a more logical order, add sleep(1)
(or maybe longer) before the "done".
from 的输出ls
需要一段时间,因此它会隐藏提示。如果您希望输出以更合乎逻辑的顺序出现,请sleep(1)
在“完成”之前添加(或更长)。
回答by Brian Roach
You're missing the part where execl() replaces your current program in memory with /bin/ls
您缺少 execl() 将内存中的当前程序替换为 /bin/ls
I would suggest looking at popen()
which will fork and exec a new process, then let you read or write to it via a pipe. (Or if you need read and write, fork()
yourself, then exec()
)
我建议查看popen()
哪个将 fork 和 exec 一个新进程,然后让您通过管道读取或写入它。(或者,如果你需要阅读和写作,fork()
你自己,然后exec()
)