【问题标题】:How do I spawn a daemon in uClinux using vfork?如何使用 vfork 在 uClinux 中生成守护进程?
【发布时间】:2010-10-08 18:29:31
【问题描述】:

使用 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.....

【问题讨论】:

    标签: c linux fork uclinux


    【解决方案1】:

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

    【讨论】:

    【解决方案2】:

    daemon() function for uClinux systems without MMU and fork(), by Jamie Lokier, in patch format

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

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

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

    【讨论】:

      【解决方案3】:

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

      我最初认为您应该能够通过(不完全如此,但有点)简单地调用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

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

      【讨论】:

      猜你喜欢
      • 2021-06-06
      • 2011-04-25
      • 2019-08-03
      • 1970-01-01
      • 2012-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      相关资源
      最近更新 更多