La différence entre fork(), vfork(), exec() et clone()

j'ai été à la recherche pour trouver la différence entre ces quatre sur Google et je m'attendais à une énorme quantité d'informations, mais il n'était vraiment pas solide comparaison entre les quatre appels.

j'ai commencé à essayer de compiler une sorte de base en un coup d'oeil regardez les différences entre ces appels système et voici ce que j'ai obtenu. Cette information est correcte/suis-je raté quelque chose d'important ?

Fork : l'appel de la fourche essentiellement, fait un double de l'actuel processus, identique dans presque tous les sens (tout n'est pas copié, par exemple, les limites des ressources dans certaines implémentations, mais l'idée est de créer une copie du possible).

le nouveau processus (enfant) obtient un ID de processus différent (PID) et a le PID de l'ancien processus (parent) comme PID parent (PPID). Parce que les deux processus sont maintenant en cours d'exécution exactement le même code, ils peuvent dire qui est qui par le code de retour de fourchette - l'enfant obtient 0, le parent obtient le PID de l'enfant. C'est tout, bien sûr, en supposant que l'appel de fourche fonctionne - sinon, aucun enfant n'est créé et le parent obtient un code d'erreur.

Vfork : la différence fondamentale entre vfork et fork est que lorsqu'un nouveau processus est créé avec vfork(), le processus parent est temporairement suspendu, et le processus enfant peut emprunter l'espace d'adresse du parent. Cet étrange état de choses continue jusqu'à ce que l'enfant traite soit sort, ou appelle execve (), à quel point le parent le processus se poursuit.

cela signifie que le processus enfant d'une vfork() doit être prudent pour éviter de modifier de façon inattendue les variables du processus parent. En particulier, le processus enfant ne doit pas revenir de la fonction contenant l'appel vfork (), et il ne doit pas appeler exit() (s'il doit sortir, il doit utiliser _exit(); en fait, ceci est également vrai pour l'enfant d'un fork normal()).

Exec : l'appel exec est un moyen de remplacer fondamentalement l'ensemble du processus actuel par un nouveau programme. Il charge le programme dans l'espace de traitement actuel et l'exécute à partir du point d'entrée. exec () remplace le processus courant par un exécutable pointé par la fonction. Control ne retourne jamais au programme original à moins qu'il y ait une erreur exec ().

Clone : Clone, comme fourche, crée un nouveau processus. Contrairement à fork, ces appels permettent au processus enfant de partager des parties de son contexte d'exécution avec le processus d'appel, tel que l'espace mémoire, la table des descripteurs de fichiers, et la table des gestionnaires de signaux.

lorsque le processus enfant est créé avec clone, il exécute la fonction application fn (arg). (Cela diffère de fork, où l'exécution se poursuit chez l'enfant à partir du point de l'appel fork d'origine.) L'argument fn est un pointeur vers une fonction qui est appelée par le processus enfant au début de son exécution. L'argument arg passé à la fonction fn.

lorsque l'application de la fonction fn(arg) retourne, le processus enfant se termine. L'entier retourné par fn est le code de sortie du processus enfant. Le processus enfant peut aussi se terminer explicitement en appelant exit (2) ou après réception d'un signal fatal.

Information getted form :

  • différences entre fourche et fourche
  • http://www.allinterview.com/showanswers/59616.html
  • http://www.unixguide.net/unix/programming/1.1.2.shtml
  • http://linux.about.com/library/cmd/blcmdl2_clone.htm

Merci d'avoir pris le temps de lire ceci ! :)

171
demandé sur codeforester 2011-02-01 00:21:19

5 réponses

  • vfork() est une optimisation obsolète. Avant une bonne gestion de la mémoire, fork() a fait une copie complète de la mémoire du parent, il était donc assez cher. puisque dans de nombreux cas un fork() a été suivi par exec() , qui écarte la carte mémoire actuelle et en crée une nouvelle, il s'agissait d'une dépense inutile. De nos jours, fork() ne copie pas la mémoire; il est simplement défini comme "Copier sur Écrire", donc fork() + exec() est tout aussi efficace que vfork() + exec() .

  • clone() est le syscall utilisé par fork() . avec certains paramètres, il crée un nouveau processus, avec les autres, il crée un thread. la différence entre eux est de savoir quelles structures de données (espace mémoire, état du processeur, pile, PID, fichiers ouverts, etc.) sont partagées ou non.

134
répondu Javier 2011-01-31 21:42:05
  • execve() remplace l'image exécutable actuelle par une autre image chargée à partir d'un fichier exécutable.
  • fork() crée un processus enfant.
  • vfork() est une version optimisée de fork() , destinée à être utilisée lorsque execve() est appelé directement après fork() . Il s'est avéré bien fonctionner dans les systèmes non-MMU (où fork() ne peut pas fonctionner de manière efficace) et lorsque fork() ing processus avec une empreinte de mémoire énorme pour exécuter un petit programme (pensez à Runtime.exec() de Java ). POSIX a normalisé le posix_spawn() pour remplacer ces deux dernières utilisations plus modernes de vfork() .
  • posix_spawn() fait l'équivalent d'un fork()/execve() , et permet également un certain jonglage fd entre les deux. Il est supposé remplacer fork()/execve() , principalement pour les plates-formes non-MMU.
  • pthread_create() crée un nouveau fil.
  • clone() est un appel spécifique à Linux, qui peut être utilisé pour implémenter n'importe quoi de fork() à pthread_create() . Il donne beaucoup de contrôle. Inspiré sur rfork() .
  • rfork() est un Plan-9 appel spécifique. C'est supposé être un appel générique, permettant plusieurs degrés de partage, entre processus complets et threads.
67
répondu ninjalj 2011-07-12 18:49:58
  1. fork() - crée un nouveau processus enfant, qui est une copie complète du processus parent. Les processus enfant et parent utilisent des espaces d'adresses virtuels différents, qui sont initialement peuplés par les mêmes pages mémoire. Puis, au fur et à mesure que les deux processus sont exécutés, les espaces d'adresses virtuelles commencent à différer de plus en plus, parce que le système d'exploitation effectue une copie paresseuse des pages de mémoire qui sont écrites par l'un ou l'autre de ces deux processus et assigne une copie indépendante des pages de mémoire modifiées pour chaque processus. Cette technique est appelée copie-sur-écriture (vache).
  2. vfork() - crée un nouveau processus enfant, qui est un "rapide" copie du processus parent. Contrairement à l'appel système fork() , les processus enfant et parent partagent le même espace d'adresse virtuel. REMARQUE! En utilisant le même espace d'adresse virtuel, le parent et l'enfant utilisent la même pile, le pointeur de pile et le pointeur d'instruction, comme dans le cas du classic fork() ! Pour éviter les interférences indésirables entre le parent et l'enfant, qui utilisent la même pile, l'exécution du processus parent est gelée jusqu'à ce que l'enfant appelle soit exec() (créer un nouvel espace d'adresse virtuel et une transition vers une autre pile) ou _exit() (fin de l'exécution du processus). vfork() est l'optimisation de la fork() pour "fork et exec" modèle. Il peut être effectué 4-5 fois plus vite que le fork() , parce que contrairement au fork() (même avec COW keeped dans l'esprit), la mise en œuvre de vfork() appel système ne comprend pas la création d'un nouvel espace d'adresse (l'attribution et la mise en place de nouveaux répertoires de page).
  3. clone() - crée un nouveau processus enfant. Différents paramètres de cet appel système, spécifient quelles parties du processus parent doivent être copiées dans le processus enfant et quelles parties seront partagées entre eux. En conséquence, ce système d'appel peut être utilisé pour créer toutes sortes d'exécution entities, à partir de threads et de finition par des processus complètement indépendants. En fait, clone() appel système est la base qui est utilisé pour la mise en œuvre de pthread_create() et toute la famille de la fork() appels système.
  4. exec() - réinitialise toute la mémoire du processus, charge et analyse le binaire exécutable spécifié, établit une nouvelle pile et passe le contrôle au point d'entrée de l'exécutable chargé. Cet appel système ne renvoie jamais le contrôle au l'appelant et sert pour le chargement d'un nouveau programme du processus. Cet appel système avec fork() appel système forment ensemble un modèle classique de gestion de processus UNIX appelé "fork-and-exec".
28
répondu ZarathustrA 2014-08-12 00:13:33

Le fork(),vfork() et clone() appellent tous les do_fork() pour faire le vrai travail, mais avec des paramètres différents.

asmlinkage int sys_fork(struct pt_regs regs)
{
    return do_fork(SIGCHLD, regs.esp, &regs, 0);
}

asmlinkage int sys_clone(struct pt_regs regs)
{
    unsigned long clone_flags;
    unsigned long newsp;

    clone_flags = regs.ebx;
    newsp = regs.ecx;
    if (!newsp)
        newsp = regs.esp;
    return do_fork(clone_flags, newsp, &regs, 0);
}
asmlinkage int sys_vfork(struct pt_regs regs)
{
    return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
}
#define CLONE_VFORK 0x00004000  /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_VM    0x00000100  /* set if VM shared between processes */

SIGCHLD means the child should send this signal to its father when exit.

pour fork, l'enfant et le père a la table de page VM indépendante, mais depuis l'efficacité, fork ne copiera pas vraiment n'importe quelles pages, il a juste réglé toutes les pages écrivables à lire seulement pour le processus enfant. Ainsi, lorsque le processus enfant veux écrire quelque chose sur cette page, une page de l'exception arriver et le noyau alloue une nouvelle page cloné à partir de l'ancien page avec permission d'écriture. Ça s'appelle "copie sur écriture".

pour vfork, la mémoire virtuelle est exactement celle de l'enfant et du père---juste à cause de cela, le père et l'enfant ne peuvent pas être éveillés simultanément puisqu'ils vont s'influencer mutuellement. Ainsi le père dormira à la fin de "do_fork()" et se réveillera quand l'enfant appellera exit() ou execve() depuis lors il possédera une nouvelle table de page. Voici le code(dans do_fork()) que le père de sommeil.

if ((clone_flags & CLONE_VFORK) && (retval > 0))
down(&sem);
return retval;

voici le code(dans mm_release() appelée par un exit() et execve ()), qui a réveillé le père.

up(tsk->p_opptr->vfork_sem);

pour sys_clone (), il est plus flexible puisque vous pouvez y entrer n'importe quel clone_flags. Donc pthread_create () appelle cet appel système avec beaucoup de clone_flags:

int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM);

résumé: the fork (), vfork () et clone () va créer des processus enfants avec différents supports de partage de ressources avec le processus père. Nous pouvons aussi dire que les vfork () et clone () peuvent créer des threads (en fait ce sont des processus puisqu'ils ont des task_struct indépendants) puisqu'ils partagent la table de page VM avec le processus père.

5
répondu user991800 2014-08-09 10:58:55

fork(), que ce soit l'enfant ou le parent a lieu en fonction du processeur de sélection.. Mais dans vfork(), child exécutera en premier. après que l'enfant a terminé, le parent exécutera.

-3
répondu Raj Kannan B. 2013-07-09 04:23:27