Как мне создать демона в uClinux с помощью vfork?
Вопрос
Это было бы легко с помощью 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.....
Решение
Похоже, нет никакого способа сделать это именно так, как у вас здесь. exec
или _exit
должны призвать к родителю продолжить выполнение. Либо поместите код демона в другой исполняемый файл и exec
Это или используйте ребенка, чтобы вызвать оригинальную задачу. Второй подход - это подлый путь, и описан здесь.
Другие советы
Daemon () Функция для систем UCLinux без MMU и FORK (), Jamie Lokier, в формате PATCH
Вы не можете сделать демон () с VFork (). Чтобы создать что-то похожее на демон на! ММУ с помощью VFORK (), родительский процесс не умирает (так что есть дополнительные процессы), и вы должны позвонить своему демону на фоне (т. Е. Применение и в командную строку на ракушка).
С другой стороны, Linux предоставляет клону (). Вооруженные с этим, знание и уход, можно реализовать демон () для! ММУ. Джейми Локье имеет функцию, чтобы сделать только что на ARM и I386, получите его здесь.
Редактировать: Сделал ссылку на демон Джейми Локье () для! MMU Linux более заметным.
Я бы подумал, что это будет проблема того типа, с которой многие другие сталкивались раньше, но мне было трудно найти кого-либо, кто говорил бы о проблемах "убить родителя".
Сначала я думал, что вы сможете сделать это с помощью (не совсем так, но вроде как) простого вызова 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 должен был бы быть обратным адресом из вызова clone, а 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
.
Если это не сработает (и вы не можете понять, как сделать что-то подобное), то вы можете использовать обычный вызов clone вместе с setjump
и longjmp
вызовы для его эмуляции, или, возможно, вам удастся обойти необходимость в семантике "return's twice" для fork
и vfork
.