Как создать демона в 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.....

person lxe    schedule 08.10.2010    source источник


Ответы (3)


Кажется, нет способа сделать это именно так, как у вас здесь. exec или _exit должны быть вызваны, чтобы родитель продолжил выполнение. Либо поместите код демона в другой исполняемый файл и exec, либо используйте дочерний процесс для создания исходной задачи. Второй подход — это скрытый способ, и он описан здесь.

person zdav    schedule 08.10.2010
comment
Изюминка заключается в использовании двоичного кода с несколькими вызовами, тогда вам не нужно помещать двоичный код в другой исполняемый файл. - person Prof. Falken; 09.10.2010
comment
Я считаю, что URL-адрес должен быть ucdot.org/article. pl?sid=03/12/12/0317219&mode=thread - person ninjalj; 09.10.2010

функция daemon() для систем uClinux без MMU и fork(), Джейми Локьер, в формате патча

Вы не можете использовать daemon() с vfork(). Чтобы создать что-то похожее на демона на !MMU с помощью vfork(), родительский процесс не умирает (поэтому есть дополнительные процессы), и вы должны вызывать своего демона в фоновом режиме (т.е. добавляя & к командной строке на оболочка).

С другой стороны, в Linux есть функция clone(). Вооружившись этим, знаниями и заботой, можно реализовать daemon() для !MMU. У Джейми Локиера есть функция, позволяющая сделать это на ARM и i386. ">здесь.

Изменить: ссылка на daemon() Джейми Локиера для !MMU Linux стала более заметной.

person ninjalj    schedule 08.10.2010

Я бы подумал, что это будет проблема, с которой многие сталкивались раньше, но мне было трудно найти кого-нибудь, говорящего о проблемах «убить родителя».

Сначала я думал, что вы сможете сделать это с помощью (не совсем так, но вроде) простого вызова 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.

Если это не работает (и вы не можете понять, как сделать что-то подобное), вы можете использовать обычный вызов clone вместе с вызовами setjump и longjmp для его эмуляции, или вы можете обойти потребность в семантике «возврата дважды» fork и vfork.

person nategoose    schedule 08.10.2010
comment
Интересно, пострадает ли это от проблемы, описанной здесь: mail- archive.com/[email protected]/msg01290.html - person ninjalj; 09.10.2010
comment
Наверное, был бы. Кроме того, я не смог найти библиотечную функцию sys_clone. Хотя, конечно, было бы неплохо. - person nategoose; 09.10.2010