我尝试使用execlp
启动程序,继续执行该程序。然后控制回来。
这是我在SO的一些研究后所做的。
pid_t child;
pid_t sid;
child = fork();
if (!child) {
sid = setsid();
if(!sid) {
exit(1);
}
execlp(RUN_EXE, RUN_EXE, SPEC_RUN.run_args[j], (char *)0);
}
但我在execlp
之后无法打印任何内容。 execlp对我来说正常。
我需要做些什么让shell返回?
答案 0 :(得分:1)
成功后,execve(2)系统调用不会返回(只有在失败时才会返回)。 execlp(3)包装器也是如此。
您通常希望在子进程中execve
。而fork(2)可能会失败。您通常应在fork
之前致电fflush(3)。所以代码:
fflush(NULL);
pid_t p = fork();
if (p < 0) { perror("fork"); exit (EXIT_FAILURE); };
if (p == 0) { /* child process */
execlp(RUN_EXE, RUN_EXE, SPEC_RUN.run_args[j], (char *)0);
perror("execlp");
fflush(NULL);
_exit(EXIT_FAILURE);
}
/// continue in the parent process
printf("child process is %d\n", (int)p);
别忘了wait
孩子,例如使用waitpid(2)
另请参阅system(3),popen(3),daemon(3),posix_spawn和阅读Advanced Linux Programming(其中有一章很好解释这些内容)。
另外,使用strace(1)了解事情是如何运作的。
答案 1 :(得分:1)
如果我理解正确,你想创建一个子流程,在该流程中运行一个程序,然后等待它完成。当直接使用系统原语时,这三个步骤中的每一步都是在Unix上自己的操作。您已了解fork()和execlp();第三步,等待子进程完成,由waitpid()及其亲属完成。
在Basile写的基础上,这是缺失的部分:
#define _POSIX_C_SOURCE 200809L /* strsignal */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
void run_program(void)
{
int status;
pid_t pid;
fflush(0);
/* create the subprocess */
pid = fork();
if (p < 0) { /* fork failed */
perror("fork");
exit(1);
}
/* in the child only, execute a program */
if (p == 0) {
execlp(RUN_EXE, RUN_EXE, SPEC_RUN.run_args[j], (char *)0);
/* If execlp returns, it failed. It is unsafe to call `exit` if this
happens; you must instead use `_exit`. This means you have to flush
output manually. */
fprintf(stderr, "execlp: %s: %s\n", RUN_EXE, strerror(errno));
fflush(stderr);
_exit(1);
}
/* in the parent, wait for the child to finish */
if (waitpid(pid, &status, 0) != pid) {
perror("waitpid");
exit(1);
}
/* decode and report any failure of the child */
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) == 0)
return; /* success! */
fprintf(stderr, "%s: unsuccessful exit %d\n",
RUN_EXE, WEXITSTATUS(status));
exit(1);
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "%s: %s%s\n",
RUN_EXE,
strsignal(WTERMSIG(status)),
WCOREDUMP(status) ? " (core dumped)" : "");
exit(1);
}
fprintf(stderr, "%s: impossible exit status %04x\n",
RUN_EXE, status);
exit(1);
}
...如果这看起来像你想要处理的巨大头发,你应该考虑使用更高级别的库函数system()和/或popen()代替。他们有自己的缺陷 - 最重要的是,他们经历/bin/sh
,这通常不是你想要的 - 但在简单的情况下,它们更容易使用。