繁体   English   中英

启动execlp作为后台进程

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM