[英]Launch execlp as background process
我正在尝试使用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为我正常工作。
我需要怎么做才能使外壳返回?
成功时, execve(2)系统调用不会返回 (只能在失败时返回)。 execlp(3)包装器也是如此。
通常你想execve
子进程中。 并且fork(2)可能会失败。 通常,应该在fork
ing之前调用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)来了解事物的工作方式。
如果我对您的理解正确,那么您想创建一个子流程,在该流程中运行一个程序, 然后等待它完成 。 当直接使用系统原语时,这三个步骤中的每一个都是在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
,而这通常不是您想要的-但在简单的情况下它们更易于使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.