Question

Ce serait facile avec une fourchette (), mais je n'ai pas de MMU. J'ai entendu dire que les blocs vfork () le processus parent jusqu'à ce que les sorties de l'enfant ou exécute exec (). Comment pourrais-je accomplir quelque chose comme ceci:

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.....
Était-ce utile?

La solution

Il semble qu'il n'y a aucun moyen de le faire exactement comme vous l'avez ici. exec ou _exit doivent obtenir appelé pour le parent de poursuivre l'exécution. Soit mettre le code du démon dans un autre exécutable et exec, ou utiliser l'enfant pour frayer la tâche d'origine. La seconde approche est la façon sournoise, et est décrite ici.

Autres conseils

fonction pour les systèmes sans MMU uClinux et une fourchette

démon () ( ), par Jamie Lokier, au format patch

Vous ne pouvez pas faire daemon () avec vfork (). Pour créer quelque chose de semblable à un démon sur! MMU en utilisant vfork (), le processus parent ne meurt pas (donc il y a des processus supplémentaires), et vous devriez appeler votre démon sur le fond (c.-en annexant et à la ligne de commande sur la shell).

D'autre part, Linux fournit clone (). Armé de cette connaissance et de soins, il est possible de mettre en œuvre le démon () pour! MMU. Jamie Lokier a une fonction pour le faire que sur ARM et i386, faites-le

J'aurais pensé que ce serait le type de problème que beaucoup d'autres se sont heurtées, mais je l'ai eu du mal à trouver quelqu'un parler des problèmes « tuer le parent ».

Je pensais d'abord que vous devriez être en mesure de le faire avec un (pas tout à fait, mais en quelque sorte) simple appel à clone, comme ceci:

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 */
}

Sauf que la détermination du pile_fils et la child_func de travailler la manière dont il le fait avec vfork est assez difficile car child_func devrait être l'adresse de retour de l'appel clone et le pile_fils devrait être le sommet de la pile au point de l'appel système réel (sys_clone) est réalisée.

Vous pouvez probablement essayer d'appeler sys_clone directement avec

pid_t new_vfork(void) {
    return sys_clone( SIGCHLD | CLONE_VM, NULL);
}

Ce que je pense pourrait obtenir ce que vous voulez. NULL comme passage second argument, qui est le pointeur pile_fils, provoque le noyau à faire la même chose comme dans vfork et une fourchette, ce qui est d'utiliser la même pile que le parent.

Je ne l'ai jamais utilisé sys_clone directement et n'a pas testé, mais je pense que cela devrait fonctionner. Je crois que:

  sys_clone( SIGCHLD | CLONE_VM | CLONE_VFORK, NULL);

est équivalent à vfork.

Si cela ne fonctionne pas (et vous ne pouvez pas savoir comment faire quelque chose de similaire), vous pourriez être en mesure d'utiliser l'appel clone régulier avec les appels setjump et longjmp à imiter, ou vous pourrez peut-être contourner la nécessité de la sémantique « de retour deux fois » de fork et vfork.

scroll top