【问题标题】:Launch execlp as background process启动 execlp 作为后台进程
【发布时间】:2014-07-07 08:22:18
【问题描述】:

我正在尝试使用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 返回?

【问题讨论】:

  • http://stackoverflow.com/questions/10315240/background-process-daemon-in-c-not-execvp-ing 这是我使用的链接之一。

标签: c exec


【解决方案1】:

成功时,execve(2) 系统调用不会返回(它只能在失败时返回)。 execlp(3) 包装器也是如此。

您通常希望在 child 进程中 execvefork(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) 了解事情的运作方式。

【讨论】:

  • 那么,有没有办法退货?我需要调试其余代码,而 gdb 对我没有帮助 print or getchar
  • 从什么返回? execlp 除非失败,否则不会返回!
  • 你和我做的一样。但是通过错误检查,对吗?我可以尝试妖魔化这个过程吗?就像python中的subprocess.Popen
  • “返回”是什么意思?请理解execve无法返回成功!!!
  • 好的,除了execve还有其他方法吗?
【解决方案2】:

如果我理解正确,您想创建一个子进程,在该进程中运行一个程序,然后等待它完成。当直接使用系统原语时,这三个步骤中的每一个都是在 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,这通常不是你想要的——但在简单的情况下它们更容易使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    相关资源
    最近更新 更多