我的程序在完成子进程后没有停止 运行

My program does not stop running after finishing child process

我现在正在学习 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 = ... 的父进程中”。就像它永远不会进入父进程一样。你知道为什么吗?提前致谢

来自我的最高评论...

您正在创建一个僵尸进程。这是因为 parent 进程没有等待 child 完成。

parent 进程将[相对] 快速终止。因此,child 失去了它的 parent 并变成了僵尸。僵尸将被内核重新parent作为进程1的child(例如systemdinitd)。

要修复,请在最后的 printf

之后添加:wait(NULL);

更新:

Therefore do I need to always put wait(NULL) in these types of situations?

TL;DR 是......是的!

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

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

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

所有其他进程都是 children of 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;
}