使用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.....
答案 0 :(得分:3)
似乎没有办法像你在这里完全一样。必须调用exec
或_exit
以便父级继续执行。将守护进程代码放入另一个可执行文件并exec
,或者使用子进程生成原始任务。第二种方法是偷偷摸摸的方式,并在这里描述。
答案 1 :(得分:3)
daemon() function for uClinux systems without MMU and fork(), by Jamie Lokier, in patch format
你不能用vfork()做守护进程()。要使用vfork()在MMU上创建类似于守护进程的东西,父进程不会死(因此有额外的进程),你应该在后台调用你的守护进程(即通过在命令行中附加&)壳)。
另一方面,Linux提供clone()。有了这些,知识和关心,就可以为!MMU实现守护进程()。 Jamie Lokier可以在ARM和i386上实现这一功能,从here获取。
编辑:为Jamie Lokier的守护进程()提供了链接!MMU Linux更为突出。
答案 2 :(得分: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
的“返回两次”语义的需要。