分叉在linux中

时间:2014-02-12 10:56:33

标签: c linux exec fork

我在linux中了解fork()时遇到了一些问题。

让我感到困惑的是,如果父母提出了一个子进程并且该孩子正在调用execl()

execl()没有返回,父进程等待子进程退出,系统会不会

挂?

提前感谢您的帮助。

这是mdadm的代码示例。因此,在execl()之后的子进程中有exit(1)。 如果execl()没有返回,那么exit(0)会执行吗?如果没有那么父母会无限期地等待?我在这儿吗?

if (!check_env("MDADM_NO_SYSTEMCTL"))
    switch(fork()) {
    case 0:
        /* FIXME yuk. CLOSE_EXEC?? */
        skipped = 0;
        for (i = 3; skipped < 20; i++)
            if (close(i) < 0)
                skipped++;
            else
                skipped = 0;

        /* Don't want to see error messages from
         * systemctl.  If the service doesn't exist,
         * we start mdmon ourselves.
         */
        close(2);
        open("/dev/null", O_WRONLY);
        snprintf(pathbuf, sizeof(pathbuf), "mdmon@%s.service",
             devnm);
        status = execl("/usr/bin/systemctl", "systemctl",
                   "start",
                   pathbuf, NULL);
        status = execl("/bin/systemctl", "systemctl", "start",
                   pathbuf, NULL);
        exit(1);
    case -1: pr_err("cannot run mdmon. "
            "Array remains readonly\n");
        return -1;
    default: /* parent - good */
        pid = wait(&status);
        if (pid >= 0 && status == 0)
            return 0;
    }

4 个答案:

答案 0 :(得分:2)

首先,请注意execl永远不会返回(除非有错误,这意味着execl失败,即它确实“没有” - 子进程仍然在同一个模块中执行)。

如果父进程等待子进程退出,那么它显然会阻止这样做。然而,这是预期的行为,它与“系统挂起”不同。系统不会挂起。

修改
关于编辑问题中发布的代码:首先,使用fork创建[几乎]完全相同的流程副本。实际上,人们并不关心创建副本,但是人们真的想创建一个 new 进程。但是,在Unix下,新进程是 forked ,而不是创建从头开始。
然后跟两个电话execl。通常情况下,第一个应该永远不会返回。相反,将加载可执行文件systemctl以替换子进程,并且子进程将从systemctl的入口点继续运行(这是一个非常简化的描述,但它基本上就是这样)。登记/> 因此systemctl将作为一个“新”独立进程运行(实际上,它“偷走”分叉进程!),它(希望)最终会退出,这会导致父进程从{{1 }}

然而,wait中可能无法找到systemctl(或发生其他错误)。对于这种情况,上述代码的程序员再次尝试从/usr/bin加载systemctl。同样,如果这样做,/bin将不会返回,但execl中的代码将执行并最终退出。然后,父进程将从systemctl取消阻止。

最后,如果对wait 的第二次调用也失败(即返回),则作者放弃并简单地调用execl,这将返回非零“错误“父母从exit(1)醒来的代码。

答案 1 :(得分:2)

如果exec未返回,则表示该进程正在执行某些(新)代码。新代码完全取代旧代码,因此从成功的exec返回是无稽之谈,因为对exec的调用在旧代码中。

在此期间,父进程wait结束其子进程。因此父母将被阻止,直到孩子终止。

答案 2 :(得分:1)

如果某个进程正在等待另一个进程,并且其他进程正在调用exec(),那么获取exec的进程现在是第一个进程正在等待的进程。因此系统不会挂起,如果/当exec'd进程退出时,第一个进程将继续执行。

答案 3 :(得分:0)

没有。每个进程都使用fork()调用启动,然后子进行exec()系列调用{参见man for execl,execlp,execle,execv,execvp,execvpe}。启动后启动的第一个进程是“init”,所有进程都可以使用“ppid”追溯到“init”。