Как мне создать демона в uClinux с помощью vfork? - PullRequest
3 голосов
/ 08 октября 2010

Это было бы легко с 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.....

Ответы [ 3 ]

3 голосов
/ 08 октября 2010

функция daemon () для систем uClinux без MMU и fork () от Jamie Lokier в формате патча

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

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

Edit: сделал ссылку на демон Jamie Lokier () для!MMU Linux более заметен.

3 голосов
/ 08 октября 2010

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

1 голос
/ 09 октября 2010

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

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

...