web-dev-qa-db-fra.com

Quel est le but de fork ()?

Dans de nombreux programmes et pages de manuel de Linux, j'ai vu du code utilisant fork(). Pourquoi avons-nous besoin d'utiliser fork() et quel est son but?

79
kar

fork() est comment vous créez de nouveaux processus dans Unix. Lorsque vous appelez fork, vous créez une copie de votre propre processus qui possède son propre espace adresse . Cela permet à plusieurs tâches de s'exécuter indépendamment les unes des autres, comme si chacune d'entre elles disposait de la mémoire complète de la machine.

Voici quelques exemples d'utilisation de fork:

  1. Votre Shell utilise fork pour exécuter les programmes que vous appelez à partir de la ligne de commande.
  2. Les serveurs Web tels que Apache utilisent fork pour créer plusieurs processus serveur, chacun gérant les demandes dans son propre espace d'adressage. Si une personne meurt ou perd de la mémoire, les autres ne sont pas affectées et fonctionne donc comme un mécanisme de tolérance aux pannes.
  3. Google Chrome _ utilise fork pour gérer chaque page dans un processus distinct. Cela empêchera le code côté client sur une page de bloquer tout votre navigateur.
  4. fork est utilisé pour générer des processus dans certains programmes parallèles (comme ceux écrits avec MPI ). Notez que cela diffère de l'utilisation de threads , qui n'ont pas leur propre espace d'adressage et existent dans un processus.
  5. Les langages de script utilisent fork indirectement pour démarrer les processus enfants. Par exemple, chaque fois que vous utilisez une commande telle que subprocess.Popen en Python, vous fork un processus enfant et lisez sa sortie. Cela permet aux programmes de fonctionner ensemble.

L'utilisation typique de fork dans un shell pourrait ressembler à ceci:

int child_process_id = fork();
if (child_process_id) {
    // Fork returns a valid pid in the parent process.  Parent executes this.

    // wait for the child process to complete
    waitpid(child_process_id, ...);  // omitted extra args for brevity

    // child process finished!
} else {
    // Fork returns 0 in the child process.  Child executes this.

    // new argv array for the child process
    const char *argv[] = {"arg1", "arg2", "arg3", NULL};

    // now start executing some other program
    exec("/path/to/a/program", argv);
}

Le shell génère un processus enfant à l'aide de exec et attend sa fin, puis continue avec sa propre exécution. Notez que vous ne devez pas utiliser fork de cette façon. Vous pouvez toujours générer de nombreux processus enfants, comme le ferait un programme parallèle, chacun pouvant exécuter un programme simultanément. En gros, chaque fois que vous créez de nouveaux processus dans un système Unix, vous utilisez fork(). Pour l'équivalent Windows, consultez CreateProcess .

Si vous voulez plus d'exemples et une explication plus longue, _ { Wikipedia } _ a un résumé correct. Et voici quelques diapositives } ici sur le fonctionnement des processus, des threads et de la simultanéité dans les systèmes d'exploitation modernes.

100
Todd Gamblin

fork () est la façon dont Unix crée de nouveaux processus. Au moment où vous avez appelé fork (), votre processus est cloné et deux processus différents continuent l'exécution à partir de là. L'un d'eux, l'enfant, aura fork () retournera 0. L'autre, le parent, aura fork () retournera le PID (ID de processus) de l'enfant.

Par exemple, si vous tapez ce qui suit dans un shell, le programme shell appellera fork (), puis exécutera la commande que vous avez passée (telnetd, dans ce cas) dans l'enfant, tandis que le parent affichera à nouveau l'invite sous forme de message indiquant le PID du processus en arrière-plan.

$ telnetd &

En ce qui concerne la raison pour laquelle vous créez de nouveaux processus, votre système d’exploitation peut faire beaucoup de choses en même temps. C'est pourquoi vous pouvez exécuter un programme et, pendant qu'il est en cours d'exécution, basculer vers une autre fenêtre et effectuer autre chose.

12
Daniel C. Sobral

fork () est utilisé pour créer un processus enfant. Lorsqu'une fonction fork () est appelée, un nouveau processus est généré et l'appel de la fonction fork () renvoie une valeur différente pour l'enfant et le parent. 

Si la valeur de retour est 0, vous savez que vous êtes le processus enfant et si la valeur de retour est un nombre (qui correspond à l'identifiant du processus enfant), vous savez que vous êtes le parent. (et s'il s'agit d'un nombre négatif, la fourchette a échoué et aucun processus enfant n'a été créé)

http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

9
Wadih M.

fork () créera un nouveau processus enfant identique au parent. Ainsi, tout ce que vous exécuterez dans le code par la suite sera exécuté par les deux processus - très utile si vous avez par exemple un serveur et que vous souhaitez gérer plusieurs requêtes.

6
cloudhead

fork () est essentiellement utilisé pour créer un processus enfant pour le processus dans lequel vous appelez cette fonction. Chaque fois que vous appelez un fork (), il retourne un zéro pour l'ID enfant.

pid=fork()
if pid==0
//this is the child process
else if pid!=0
//this is the parent process

ainsi, vous pouvez fournir différentes actions pour le parent et l’enfant et utiliser la fonctionnalité multithreading.

6
Nave

L'appel système fork () est utilisé pour créer des processus. Il ne prend aucun argument et retourne un ID de processus. Fork () a pour but de créer un nouveau processus, qui devient le processus enfant de l'appelant. Après la création d’un nouveau processus enfant, les deux processus exécuteront l’instruction suivante à la suite de l’appel système fork (). Par conséquent, nous devons distinguer le parent de l'enfant. Cela peut être fait en testant la valeur retournée de fork ():

Si fork () renvoie une valeur négative, la création d'un processus enfant a échoué . Fork () renvoie un zéro au processus enfant nouvellement créé . Fork () renvoie une valeur positive, l'ID de processus du processus enfant, au parent. L'ID de processus renvoyé est de type pid_t défini dans sys/types.h. Normalement, l'ID de processus est un entier. De plus, un processus peut utiliser la fonction getpid () pour extraire l'ID de processus affecté à ce processus . Par conséquent, après l'appel système à fork (), un simple test peut indiquer quel processus est l'enfant. Veuillez noter qu'Unix fera une copie exacte de l'espace d'adressage du parent et le remettra à l'enfant. Par conséquent, les processus parent et enfant ont des espaces d'adressage distincts.

Laissez-nous comprendre avec un exemple pour clarifier les points ci-dessus. Cet exemple ne distingue pas les processus parent et enfant. 

#include  <stdio.h>
#include  <string.h>
#include  <sys/types.h>

#define   MAX_COUNT  200
#define   BUF_SIZE   100

void  main(void)
{
     pid_t  pid;
     int    i;
     char   buf[BUF_SIZE];

     fork();
     pid = getpid();
     for (i = 1; i <= MAX_COUNT; i++) {
          sprintf(buf, "This line is from pid %d, value = %d\n", pid, i);
          write(1, buf, strlen(buf));
     } 
}

Supposons que le programme ci-dessus s'exécute jusqu'au moment de l'appel de fork ().

Si l'appel à fork () est exécuté avec succès, Unix fera deux copies identiques d'espaces d'adresses, une pour le parent et l'autre pour l'enfant . Les deux processus commenceront leur exécution à la prochaine instruction suivant le fork (). appel. Dans ce cas, les deux processus commenceront leur exécution à l'affectation 

pid = .....;

Les deux processus démarrent leur exécution juste après l'appel système fork (). Comme les deux processus ont des espaces adresse identiques mais séparés, les variables initialisées avant l'appel fork () ont les mêmes valeurs dans les deux espaces adresse. Puisque chaque processus a son propre espace d'adressage, toutes les modifications seront indépendantes des autres. En d'autres termes, si le parent modifie la valeur de sa variable, la modification affectera uniquement la variable dans l'espace d'adressage du processus parent. Les autres espaces adresse créés par les appels fork () ne seront pas affectés même s'ils portent des noms de variables identiques.

Quelle est la raison d'utiliser write plutôt que printf? C'est parce que printf () est "tamponné", ce qui signifie que printf () regroupera la sortie d'un processus. Lors de la mise en mémoire tampon de la sortie pour le processus parent, l'enfant peut également utiliser printf pour imprimer certaines informations, qui seront également mises en mémoire tampon. En conséquence, étant donné que la sortie ne sera pas envoyée à l’écran immédiatement, vous risquez de ne pas obtenir le bon ordre du résultat attendu. Pire encore, les résultats des deux processus peuvent être mélangés de manière étrange. Pour résoudre ce problème, vous pouvez envisager d'utiliser l'écriture "sans tampon".

Si vous exécutez ce programme, les éléments suivants peuvent s'afficher à l'écran:

................
This line is from pid 3456, value 13
This line is from pid 3456, value 14
     ................
This line is from pid 3456, value 20
This line is from pid 4617, value 100
This line is from pid 4617, value 101
     ................
This line is from pid 3456, value 21
This line is from pid 3456, value 22
     ................

L'ID de processus 3456 peut être celui attribué au parent ou à l'enfant. Du fait que ces processus sont exécutés simultanément, leurs lignes de sortie sont mélangées de manière plutôt imprévisible. De plus, l'ordre de ces lignes est déterminé par le planificateur de la CPU. Par conséquent, si vous exécutez à nouveau ce programme, vous obtiendrez un résultat totalement différent.

4
cpp-coder

Vous n'avez probablement pas besoin d'utiliser fork dans la programmation quotidienne si vous écrivez des applications.

Même si vous souhaitez que votre programme en commence un autre pour effectuer une tâche, il existe d'autres interfaces plus simples utilisant un fork en arrière-plan, telles que "système" en C et Perl.

Par exemple, si vous souhaitez que votre application lance un autre programme tel que bc pour effectuer certains calculs, vous pouvez utiliser "système" pour l'exécuter. Le système fait un "fork" pour créer un nouveau processus, puis un "exec" pour transformer ce processus en bc. Une fois que bc est terminé, le système retourne le contrôle à votre programme.

Vous pouvez également exécuter d'autres programmes de manière asynchrone, mais je ne me souviens plus comment.

Si vous écrivez des serveurs, des shells, des virus ou des systèmes d’exploitation, vous voudrez probablement utiliser fork.

4
Alex Brown

Fork crée de nouveaux processus. Sans fork, vous auriez un système unix ne pouvant exécuter que init.

4
Stephen

Fork () est utilisé pour créer de nouveaux processus comme tout le monde l'a écrit.

Voici mon code qui crée des processus sous la forme d'arborescence binaire ....... Il vous demandera d'analyser le nombre de niveaux jusqu'à lequel vous souhaitez créer des processus dans l'arborescence binaire.

#include<unistd.h> 
#include<fcntl.h> 
#include<stdlib.h>   
int main() 
{
int t1,t2,p,i,n,ab;
p=getpid();                
printf("enter the number of levels\n");fflush(stdout);
scanf("%d",&n);                
printf("root %d\n",p);fflush(stdout);
for(i=1;i<n;i++)    
{        
    t1=fork();

    if(t1!=0)
        t2=fork();        
    if(t1!=0 && t2!=0)        
        break;            
    printf("child pid %d   parent pid %d\n",getpid(),getppid());fflush(stdout);
}   
    waitpid(t1,&ab,0);
    waitpid(t2,&ab,0);
return 0;
}

SORTIE

  enter the number of levels
  3
  root 20665
  child pid 20670   parent pid 20665
  child pid 20669   parent pid 20665
  child pid 20672   parent pid 20670
  child pid 20671   parent pid 20670
  child pid 20674   parent pid 20669
  child pid 20673   parent pid 20669
3
Anil Kumar Arya

Le multitraitement est au cœur de l'informatique. Par exemple, votre IE ou Firefox peuvent créer un processus pour télécharger un fichier pour vous pendant que vous naviguez encore sur Internet. Ou bien, pendant que vous imprimez un document dans un traitement de texte, vous pouvez toujours consulter différentes pages et continuer à le modifier.

3

fork() est utilisé pour générer un processus enfant. Il est généralement utilisé dans des situations similaires à celles du filetage, mais il existe des différences. Contrairement aux threads, fork() crée des processus séparés entiers, ce qui signifie que l’enfant et le parent, s’ils sont des copies directes l’un de l’autre au moment où fork() est appelé, sont complètement séparés, aucun d’entre eux n’a accès à la mémoire de l’autre (sans passer par la problèmes normaux, vous allez accéder à la mémoire d'un autre programme).

fork() est toujours utilisé par certaines applications serveur, principalement celles qui s'exécutent en tant que root sur un ordinateur * NIX qui supprime les autorisations avant de traiter les demandes des utilisateurs. Il y a encore d'autres cas d'utilisation, mais la plupart des gens sont maintenant passés au multithreading.

1
Matthew Scharley

Il faut d’abord comprendre l’appel système fork (). Laisse-moi expliquer

  1. l'appel système fork () crée la copie exacte du processus parent. Il duplique la pile, le tas, les données initialisées et les données non initialisées parent et partage le code en mode lecture seule avec le processus parent.

  2. Un appel système Fork copie la mémoire sur la base de la copie sur écriture, ce qui signifie que l'enfant crée une page de mémoire virtuelle lorsque la copie est requise.

Maintenant, but de fork ():

  1. Fork () peut être utilisé à l'endroit où il y a une division du travail, comme un serveur doit gérer plusieurs clients. Par conséquent, le parent doit accepter la connexion sur une base régulière. Ainsi, le serveur spécifie que chaque client effectue une opération de lecture-écriture.
1
Sandeep_black

La raison d'être de fork () par rapport à une fonction exec () pour lancer un nouveau processus est expliquée dans une réponse à une question similaire sur l'échange de pile unix .

Essentiellement, puisque fork copie le processus en cours, toutes les options possibles pour un processus sont définies par défaut, de sorte que le programmeur ne les a pas fournies.

Dans le système d'exploitation Windows, en revanche, les programmeurs doivent utiliser la fonction CreateProcess qui est BEAUCOUP plus compliquée et qui nécessite de renseigner une structure multiple pour définir les paramètres du nouveau processus.

Donc, pour résumer, la raison pour forger (versus exécuter) est la simplicité dans la création de nouveaux processus.

0
Tyler Durden

La fonction fork () est utilisée pour créer un nouveau processus en dupliquant le processus existant à partir duquel il est appelé. Le processus existant à partir duquel cette fonction est appelée devient le processus parent et le processus nouvellement créé devient le processus enfant. Comme déjà indiqué, "enfant" est une copie du parent mais il existe quelques exceptions.

  • L'enfant a un PID unique comme tout autre processus exécuté dans le système d'exploitation

  • L’enfant a un ID de processus parent identique au PID du
    processus qui l'a créé.

  • L'utilisation des ressources et les compteurs de temps CPU sont remis à zéro dans le processus fils

  • L'ensemble des signaux en attente dans l'enfant est vide.

  • L'enfant n'hérite d'aucun minuteur de son parent

Exemple :

    #include <unistd.h>
    #include <sys/types.h>
    #include <errno.h>
    #include <stdio.h>
    #include <sys/wait.h>
    #include <stdlib.h>

    int var_glb; /* A global variable*/

int main(void)
{
    pid_t childPID;
    int var_lcl = 0;

    childPID = fork();

    if(childPID >= 0) // fork was successful
    {
        if(childPID == 0) // child process
        {
            var_lcl++;
            var_glb++;
            printf("\n Child Process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb);
        }
        else //Parent process
        {
            var_lcl = 10;
            var_glb = 20;
            printf("\n Parent process :: var_lcl = [%d], var_glb[%d]\n", var_lcl, var_glb);
        }
    }
    else // fork failed
    {
        printf("\n Fork failed, quitting!!!!!!\n");
        return 1;
    }

    return 0;
}

Maintenant, quand le code ci-dessus est compilé et exécuté:

$ ./fork

Parent process :: var_lcl = [10], var_glb[20]

Child Process :: var_lcl = [1], var_glb[1]
0
Usman

L'utilisation de l'appel système Fork pour crée un nouveau processus, appelé processus enfant, qui s'exécute simultanément avec le processus (processus appelé appel fourchette système) et ce processus est appelé processus parent.

Après la création d'un nouveau processus enfant, les deux processus exécuteront l'instruction suivante à la suite de l'appel système fork (). Un processus enfant utilise le même ordinateur (compteur de programme), les mêmes registres de CPU, les mêmes fichiers ouverts que ceux utilisés dans le processus parent.

Dans certains systèmes, différentes versions de fork () existent en fonction du comportement souhaité

Certains systèmes UNIX ont fork1 () et forkall ()

  • fork1 () ne fait que dupliquer le thread appelant
  • forkall () duplique tous les threads d'un processus
0
Malith Ileperuma

Appel système Fork () utilisé pour créer un processus enfant. C'est la copie exacte du processus parent. Fork copie la section pile, la section tas, la section données, la variable d'environnement, les arguments de ligne de commande du parent.

se référer: http://man7.org/linux/man-pages/man2/fork.2.html

0
user9344710