3

使用 fork() 会很容易,但我没有 MMU。我听说 vfork() 会阻塞父进程,直到子进程退出或执行 exec()。我将如何完成这样的事情?:

pid_t pid = vfork();

if (pid == -1) {
    // fail
    exit(-1);
}

if (pid == 0) {
    // child
    while(1) {
        // Do my daemon stuff
    }

    // Let's pretend it exits sometime
    exit();
} 

// Continue execution in parent without blocking.....
4

3 回答 3

3

似乎没有办法完全按照您在此处的方式执行此操作。 exec或者_exit必须调用父级才能继续执行。要么将守护程序代码放入另一个可执行文件exec中,要么使用子进程生成原始任务。第二种方法是偷偷摸摸的方法,并在此处描述。

于 2010-10-08T18:51:30.133 回答
3

用于没有 MMU 和 fork() 的 uClinux 系统的 daemon() 函数,作者 Jamie Lokier,补丁格式

你不能用 vfork() 来做 daemon()。要使用 vfork() 在 !MMU 上创建类似于守护进程的东西,父进程不会死掉(所以有额外的进程),你应该在后台调用你的守护进程(即通过将 & 附加到贝壳)。

另一方面,Linux 提供了 clone()。有了这些知识和关心,就有可能为 !MMU 实现 daemon()。Jamie Lokier 在 ARM 和 i386 上具有执行此操作的功能,请从此处获取。

编辑:使 Jamie Lokier 的 !MMU Linux 的 daemon() 的链接更加突出。

于 2010-10-08T19:46:42.760 回答
1

我本以为这将是许多其他人以前遇到的问题类型,但我很难找到任何人谈论“杀死父母”问题。

我最初认为您应该能够通过(不完全如此,但有点)简单的调用来做到这一点clone,就像这样:

pid_t new_vfork(void) {
    return clone(child_func,        /* child function */
                 child_stack,          /* child stack    */
                 SIGCHLD | CLONE_VM,   /* flags */
                 NULL,                 /* argument to child */
                 NULL,                 /* pid of the child */
                 NULL,                 /* thread local storage for child */
                 NULL);                /* thread id of child in child's mem */
}

除了确定 child_stack 和 child_func 以使用 vfork 的方式工作非常困难,因为 child_func 需要是克隆调用的返回地址,而 child_stack 需要是堆栈的顶部进行实际的系统调用(sys_clone)。

您可能会尝试sys_clone直接致电

pid_t new_vfork(void) {
    return sys_clone( SIGCHLD | CLONE_VM, NULL);
}

我认为这可能会得到你想要的。传递 NULL 作为第二个参数,即 child_stack 指针,会导致内核执行与 vfork 和 fork 中相同的操作,即使用与父级相同的堆栈。

我从来没有sys_clone直接使用过,也没有测试过,但我认为它应该可以工作。我相信:

  sys_clone( SIGCHLD | CLONE_VM | CLONE_VFORK, NULL);

相当于vfork

如果这不起作用(并且您无法弄清楚如何做类似的事情),那么您可以使用常规克隆调用以及setjump调用longjmp来模拟它,或者您可以绕过需要fork和的“返回两次”语义vfork

于 2010-10-08T20:52:52.253 回答