Вопрос

Это было бы легко с помощью 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top