如何使用 vfork 在 uClinux 中生成守护进程?

发布于 2024-09-26 16:48:32 字数 367 浏览 2 评论 0原文

这对于 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.....

This would be easy with fork(), but I've got no MMU. I've heard that vfork() blocks the parent process until the child exits or executes exec(). How would I accomplish something like this?:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

椒妓 2024-10-03 16:48:32

似乎没有办法完全像你在这里那样做到这一点。必须调用 exec_exit 父级才能继续执行。将守护程序代码放入另一个可执行文件中并执行它,或者使用子进程生成原始任务。第二种方法是偷偷摸摸的方法,在这里进行了描述。

It seems there is no way to do this exactly as you have it here. exec or _exit have to get called for the parent to continue execution. Either put the daemon code into another executable and exec it, or use the child to spawn the original task. The second approach is the sneaky way, and is described here.

谁把谁当真 2024-10-03 16:48:32

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

您不能使用 vfork() 执行 daemon()。要使用 vfork() 在 !MMU 上创建类似于守护进程的东西,父进程不会终止(因此有额外的进程),并且您应该在后台调用您的守护进程(即通过将 & 附加到命令行上外壳)。

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

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

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

You can't do daemon() with vfork(). To create something similar to a daemon on !MMU using vfork(), the parent process doesn't die (so there are extra processes), and you should call your daemon on the background (i.e. by appending & to the command line on the shell).

On the other hand, Linux provides clone(). Armed with that, knowledge and care, it's possible to implement daemon() for !MMU. Jamie Lokier has a function to do just that on ARM and i386, get it from here.

Edit: made the link to Jamie Lokier's daemon() for !MMU Linux more prominent.

灰色世界里的红玫瑰 2024-10-03 16:48:32

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

我最初认为您应该能够通过(不完全如此,但有点)简单地调用 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 的“返回两次”语义的需要。

I would have thought that this would be the type of problem that many others had run into before, but I've had a hard time finding anyone talking about the "kill the parent" problems.

I initially thought that you should be able to do this with a (not quite so, but sort of) simple call to clone, like this:

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 */
}

Except that determining the child_stack and the child_func to work the way that it does with vfork is pretty difficult since child_func would need to be the return address from the clone call and the child_stack would need to be the top of the stack at the point that the actual system call (sys_clone) is made.

You could probably try to call sys_clone directly with

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

Which I think might get what you want. Passing NULL as the second argument, which is the child_stack pointer, causes the kernel to do the same thing as it does in vfork and fork, which is to use the same stack as the parent.

I've never used sys_clone directly and haven't tested this, but I think it should work. I believe that:

  sys_clone( SIGCHLD | CLONE_VM | CLONE_VFORK, NULL);

is equivalent to vfork.

If this doesn't work (and you can't figure out how to do something similar) then you may be able to use the regular clone call along with setjump and longjmp calls to emulate it, or you may be able to get around the need for the "return's twice" semantics of fork and vfork.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文