【问题标题】:My program does not stop running after finishing child process完成子进程后我的程序没有停止运行
【发布时间】:2020-10-28 18:55:20
【问题描述】:

我现在正在学习folk,exec等,我有这段代码:

#include    <stdio.h>
#include    <sys/types.h>
#include    <unistd.h>
#include    <string.h>
#include    <stdlib.h>

int main(int argc, char *argv[])
{
    pid_t childpid;
    int status;
    childpid=fork();
    if (childpid== -1){
        perror("Failed to fork\n");
        exit(1);
    }
    if (childpid==0) {
        printf("I am in child process with id = %lu\n", (long)getpid());
        execvp(argv[1], &argv[1]);
        perror("exec failure ");
        exit(1);
    }
    else {
        printf("I am in parent process with id = %lu\n", (long)getpid());
        exit(1);
    }

}

子进程工作正常,但之后由于某种原因程序继续运行而没有做任何事情。它从不打印“我在 id = .... 的子进程中”或“我在 id =... 的父进程中”。就像它永远不会进入父进程一样。你有什么想法为什么?提前致谢

【问题讨论】:

  • 你正在创建一个僵尸进程。这是因为父进程没有等待子进程完成。父进程将[相对]快速终止。因此,孩子失去了父母,变成了一个僵尸。僵尸将被内核重新设置为进程 1 的子进程(例如 systemdinitd)。要修复,请在最后的 printf 之后添加:wait(NULL);
  • 非常感谢!因此,我是否需要在这些类型的情况下始终放置 wait(NULL) ?
  • 您能否修正问题中的拼写,以便对其他人有用?

标签: c fork exec


【解决方案1】:

来自我的顶级评论...

你正在创建一个僵尸进程。这是因为父进程没有等待子进程完成。

父进程将[相对]快速终止。因此,孩子失去了父母,变成了僵尸。僵尸进程将被内核重新设置为进程 1 的子进程(例如 systemdinitd)。

要修复,请在最后的 printf 之后添加:wait(NULL);


更新:

因此我是否需要在这些类型的情况下始终放置 wait(NULL) ?

TL;DR 是……是的!

这是您通常希望对大多数程序执行的操作。

如果您是服务器程序(例如inetd),您创建僵尸的少数情况之一是(例如)。

服务器想要“分离”运行。也就是说,作为 init 进程的子进程(例如systemdinitd 等)。系统上只有一个 init 进程。

所有其他进程都是 init 的子进程,即使是间接的。例如,您的程序的进程层次结构类似于:

init -> window_manager -> xterm -> bash -> your_program

无论如何,如今大多数服务器程序都是由systemd 直接启动的。它检查一些配置文件并根据这些配置选项启动。所以,现在,大多数服务器程序都不需要做任何特别的事情了。

但是,如果您正在测试自己的服务器,从命令行调用它,并希望它在后台运行 [分离],您可以这样做:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>

int opt_d;

int
main(int argc, char **argv)
{
    char *cp;
    pid_t childpid;
    int status;

    // skip over program name
    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        cp += 2;
        switch (cp[-1]) {
        case 'd':
            opt_d = 1;
            break;
        }
    }

    // detach into background
    if (opt_d) {
        childpid = fork();

        if (childpid == -1) {
            perror("Failed to detach\n");
            exit(1);
        }

        // exit the parent -- child is now detached [and a zombie] and a child
        // of the init process
        if (childpid != 0)
            exit(0);
    }

    childpid = fork();

    if (childpid == -1) {
        perror("Failed to fork\n");
        exit(1);
    }

    if (childpid == 0) {
        printf("I am in child process with id = %lu\n", (long) getpid());
        execvp(*argv, argv);
        perror("exec failure ");
        exit(1);
    }

    printf("I am in parent process with id = %lu\n", (long) getpid());
    wait(&status);

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2010-10-25
    • 2020-11-17
    相关资源
    最近更新 更多