IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

comment implémenter avec fork un appel de fonction engendrant un processus?


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2013
    Messages : 287
    Points : 0
    Points
    0
    Par défaut comment implémenter avec fork un appel de fonction engendrant un processus?
    bonjour,

    J'ai lu un peu la doc de fork.
    Je n'arrive pas à implémenter un programme program.c faisant ceci en pseudo-code:
    creation d'une fonction simple f1
    création d'ue fonction simple f2
    si f1 est appelée,ça engendre un processus p1
    si f2 est appelée,ça engendre un processus p2



    merci de votre aide

  2. #2
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    septembre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : septembre 2012
    Messages : 264
    Points : 310
    Points
    310
    Par défaut
    Oui...

    fork() est un mécanisme particulier...

    J'ai pour habitude lorsque j'utilise fork() de récupérer sa valeur de retour.

    [EDIT après avoir relu le man :} ]

    Grâce à celle-ci je peux déterminer
    + le processus père
    + le processus fils (child) enfant


    Le processus père enfant sera le bloc d'instructions exécuté si la valeur de retour du fork() est égale à 0.
    Le processus enfant père sera le bloc d'instructions exécuté si la valeur de retour du fork() est différente de 0 (correspondant à l'identifiant de processus enfant).

    Dans ton cas, il faudrait appeler la fonction f1 dans le bloc correspondant au "père", et du coup la fonction f2 sera appelée dans le bloc correspondant au "fils" à l'enfant.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    #include  <stdio.h>
    #include  <sys/types.h>
     
    #define   MAX_COUNT  200
     
    void  ChildProcess(void);                /* child process prototype  */
    void  ParentProcess(void);               /* parent process prototype */
     
    void  main(void)
    {
         pid_t  pid;
     
         pid = fork();
         if (pid == 0) 
              ChildProcess();
         else 
              ParentProcess();
    }
     
    void  ChildProcess(void)
    {
         int   i;
     
         for (i = 1; i <= MAX_COUNT; i++)
              printf("   This line is from child, value = %d\n", i);
         printf("   *** Child process is done ***\n");
    }
     
    void  ParentProcess(void)
    {
         int   i;
     
         for (i = 1; i <= MAX_COUNT; i++)
              printf("This line is from parent, value = %d\n", i);
         printf("*** Parent is done ***\n");
    }
    -- from https://www.csl.mtu.edu/cs4411.ck/ww...rk/create.html --

  3. #3
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    532
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : mai 2010
    Messages : 532
    Points : 1 674
    Points
    1 674
    Par défaut
    Bonjour,
    Citation Envoyé par hurukan Voir le message
    Oui...

    fork() est un mécanisme particulier...

    J'ai pour habitude lorsque j'utilise fork() de récupérer sa valeur de retour.

    Grâce à celle-ci je peux déterminer
    + le processus père
    + le processus fils

    Le processus père sera le bloc d'instructions exécuté si la valeur de retour du fork() est égale à 0.
    Le processus fils sera le bloc d'instructions exécuté si la valeur de retour du fork() est différente de 0.

    .......
    Attention, après le retour d'un fork les deux contextes d'exécution (processus père et fils) reçoivent tous les deux une valeur de retour qui sont différentes. L'enfant reçoit du fork la valeur de retour zéro (0) tandis que le père reçoit comme valeur de retour l'identifiant du processus enfant et donc différent de zéro. En termes plus clairs, le père reçoit le PID du nouveau processus fils, ce qui permettra à la fois au père et au fils de savoir qui est qui. Le cas contraire où la primitive fork renvoie la valeur -1 en cas d'échec cela peut être dû (très souvent) au fait que nous avons atteint la limite des processus fils auxquels un père peut posséder ou à un manque d'espace qui empêche la création d'une entrée dans la table des processus ou à une mémoire virtuelle insuffisante.

    Aussi la création de processus est très utile mais il faut faire attention car si l'entrée d'un enfant dans la table des processus se fait facilement, ce n'est pas le cas des suppressions immédiates de celle-ci. En effet bien que l'enfant ne soit pas/plus actif, son contexte d'exécution aux yeux du système reste dans la mesure où son code de retour doit être stocké en cas d'appel à wait et donc on parle de processus zombie, surtout si l'enfant se termine avant le père.


    Pour le débutant je dirais juste que lors de la création d'un processus avec la primitive fork vous obtiendrez pour le père une valeur de retour qui est égale au processus Identifer qui est surnommé PID du fils et pour le fils le PID = zéro. En cas d'erreur vous obtenez une valeur négative. Aussi, Il faut toujours éviter qu'un processus soit dans un état zombie en utilisant des primitives comme Wait mais je vous laisse le soin de vous documenter après avoir compris comment fonctionne fork et comment les utiliser.

    à bientôt.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2013
    Messages : 287
    Points : 0
    Points
    0
    Par défaut
    quel est le rapport avec la fonction appelée qui déclenche un processus?

    Ma fonction f1 appelée serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int somme (int a,int b)
    { int c;
       c=a+b;
      return c;
    }
    Ma fonction f2 appelée serait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int difference (int a,int b)
    { int c;
       c=a-b;
      return c;
    }
    Ce code là serait-il alors correct?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
     
    #include  <stdio.h>
    #include  <sys/types.h>
     
    #define   MAX_COUNT  200
     
    void  ChildProcess(void);                /* child process prototype  */
    void  ParentProcess(void);               /* parent process prototype */
     
    void  main(void)
    {
         pid_t  pid;
     
         pid = fork();
         if (pid == 0) 
              ChildProcess();
         else 
              ParentProcess();
     
      if(somme(0,1)==1)
    {
    ParentProcess();   
    }
     
    if(difference(1,0)==1)
    {
    ChildProcess();  
    }
     
    }
     
    void  ChildProcess(void)
    {
         int   i;
     
         for (i = 1; i <= MAX_COUNT; i++)
              printf("   This line is from child, value = %d\n", i);
         printf("   *** Child process is done ***\n");
    }
     
    void  ParentProcess(void)
    {
         int   i;
     
         for (i = 1; i <= MAX_COUNT; i++)
              printf("This line is from parent, value = %d\n", i);
         printf("*** Parent is done ***\n");
    }
     
    int somme (int a,int b)
    { int c;
       c=a+b;
      return c;
    }
     
    int difference (int a,int b)
    { int c;
       c=a-b;
      return c;
    }

  5. #5
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    septembre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : septembre 2012
    Messages : 264
    Points : 310
    Points
    310
    Par défaut
    Je dirais: si tu veux tenter d'appréhender les mécanismes liés au fork() -- je m'étais planté avec les notions de parent/enfant père/enfant, j'utilise principalement les threads (corrigé suite aux précisions de sambia) --
    tu pourrais, par exemple, tester les instructions de la fonction somme() dans le processus enfant d'un fork()... de même pour soustraction().

    Maintenant la nature de ces fonctions ne te permettra pas d'appréhender réellement les mécanismes liés à l'appel système fork()...
    Moi j'ai utilisé fork() pour créer des drivers, des "daemons" (serveurs dans le monde Unix)... ils sont censés être en attente que "quelque chose se passe" et réagissent
    quand les conditions sont remplies (un périphérique USB se connecte par exemple, une demande de connexion TCP est reçue, ...).

    En général ces "serveurs" tournent en arrière plan dans une "boucle infinie" (pour ne pas monopoliser toutes les ressources du système) qui ne s'arrête que lorsque un message (signal) précis est envoyé au processus (SIGHUP, ...).

    [EDIT]
    Je ne suis pas certain que le compilateur va aimer ces instructions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    if(somme(0,1)==1)
    {
    ParentProcess();   
    }
     
    if(diiference(1,0)==1)
    {
    ChildProcess();  
    }
    ...en fin de listing.

  6. #6
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    septembre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : septembre 2012
    Messages : 264
    Points : 310
    Points
    310
    Par défaut
    Il vaut mieux afficher quelque chose...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #include  <stdio.h>
    #include  <sys/types.h>
     
    void  ChildProcess(void);                /* child process prototype  */
    void  ParentProcess(void);               /* parent process prototype */
     
    void  main(void)
    {
         pid_t  pid;
     
         pid = fork();
         if (pid == 0) 
              ChildProcess();
         else 
              ParentProcess();
    }
     
    void  ChildProcess(void)
    {
      int c;
      c=a+b;
      //return c;
      printf("Somme de %d et %d = %d\n",a,b,c);
    }
     
    void  ParentProcess(void)
    {
      int c;
      c=a-b;
      //return c;
      printf("Différence de %d par %d = %d\n",a,b,c);
    }
    Tu pourrais "voir" le côté "exécution en parallèle" si tu faisais une boucle infinie autour des deux opérations...
    Comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    while(1)
    {
      c=a+b;
      printf("Somme de %d et %d = %d\n",a,b,c);
      a++;
      b++;
    }
    ...tu devras probablement effectuer un CTRL-C pour arrêter le programme ^^

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    février 2013
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : février 2013
    Messages : 287
    Points : 0
    Points
    0
    Par défaut
    ...et pour obtenir le processus dès que le programme c est lancé?
    (je veux dire,le programme est lancé donc automatiquement,indépendemment du contenu du code implémenté,un processus est exécuté.Mais je souhaite que se crée en fait un autre processus:comment implémenter ceci?)

  8. #8
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    septembre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : septembre 2012
    Messages : 264
    Points : 310
    Points
    310
    Par défaut
    Le fork() le fait justement ^^

    [EDIT]
    La fonction main() cache un fork()... si mes souvenirs sont bons.
    Donc quand tu lances ton programme, que ce soit sous Linux, Mac OS X ou autre OS, il y a un petit programme (loader) qui va se charger de "créer un processus" un peu comme le fork() le fait
    puis de brancher le "pointeur d'instruction" sur la première instruction de la fonction main().


    Je me suis emmêlé les pinceaux et/ou j'ai fait un raccourci foireux -> https://courses.cs.washington.edu/co...on/notes/fork/

    Si tu observes les processus qui tournent sur ton système, imaginons que tu es sous Linux, avec htop c'est un peu plus facile.

    Tu lances htop, tu appuies sur F4 puis tu tapes le nom de ton programme... au début il n'y aura rien.
    Tu lances dans un autre terminal ton programme...
    Tu vas voir que ton programme est listé avec un numéro de processus (pid).
    Si ton programme utilisais la fonction fork() tu devrais voir une autre "entrée" dans la liste avec un pid différent -> c'est un nouveau processus créé.

    Nom : Screenshot_20220417_012438.png
Affichages : 87
Taille : 11,4 Ko

    Il faut évidemment que le processus créé par le fork() vive suffisamment longtemps pour que tu puisses "voir" que le processus a été créé.
    Si tu faisais un sleep(10) dans le processus créé ce serait suffisant.

  9. #9
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    septembre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : septembre 2012
    Messages : 264
    Points : 310
    Points
    310
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc,char** argv)
    Ici un processus est créé par le "loader" propre à l'OS...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    {
    	printf("Main: %05d\n",getpid());
    	int coderetour=fork();
    	if(!coderetour)
    	{
    Ici un nouveau processus est créé... (avec un pid différent de celui de la fonction main())
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    		printf("CHILD\n");
    		while(1)
    		{
    			printf("(%05d) Child en action...\n",getpid());
    			sleep(1);
    		}
    	}
    Ici le processus parent n'est pas vraiment un nouveau processus, il s'agit de la fonction main() en fait... (le pid est le même)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	printf("PARENT\n");
    	while(1)
    	{
    		printf("(%05d) Parent en action...\n",getpid());
    		sleep(1);
    	}
    	return(EXIT_SUCCESS);
    }
    Nom : forks.png
Affichages : 92
Taille : 31,8 Ko
    Pour quitter le programme il faut faire un CTRL-C ou kill -2 $(pgrep nomdetonprogramme)
    Entre nous CTRL-C c'est plus facile à faire lol ^^

  10. #10
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    septembre 2012
    Messages
    264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : septembre 2012
    Messages : 264
    Points : 310
    Points
    310
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int main(int argc,char** argv)
    {
    	printf("Main: %05d\n",getpid());
    	int coderetour=fork();
    	if(!coderetour)
    	{
    		printf("CHILD\n");
    		while(1)
    		{
    			printf("(%05d) Child en action...\n",getpid());
    			sleep(1);
    		}
    	}
    }
    si tu faisais ceci là tu seras obligé de passer par une commande capable de "tuer" le processus, le CTRL-C ne va pas fonctionner (le parent est mort)...
    kill -2 $(pgrep nomdetonprogramme) devrait suffire, sinon il faut passer par un GUI qui affiche les processus du système, retrouver le tiens et arrêter la tâche.
    Nom : kill.png
Affichages : 91
Taille : 61,1 Ko

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    10 410
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 10 410
    Points : 28 299
    Points
    28 299
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par tabkelm Voir le message
    Je n'arrive pas à implémenter un programme program.c faisant ceci en pseudo-code:
    creation d'une fonction simple f1
    création d'ue fonction simple f2
    si f1 est appelée,ça engendre un processus p1
    si f2 est appelée,ça engendre un processus p2
    Déjà ce serait bien que tu réalises que f1 et f2 c'est la même chose.

    Citation Envoyé par tabkelm Voir le message
    Mais je souhaite que se crée en fait un autre processus:comment implémenter ceci?)
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/wait.h>
     
    void f() {
    	int pid;
    	int status;
    	switch(pid=fork()) {
    		case -1: // Erreur
    			fprintf(stderr, "Erreur fork() - %s\n", strerror(errno));
    			break;
    		case 0: // Fils
    			printf("\tJe suis le fils %d de %d\n", getpid(), getppid());
    			sleep(10);
    			exit(123);
    			break;
    		default: // Pere
    			sleep(1);		// Pour être sûr que le fils sera lancé avant le père
    			printf("Je suis le pere %d de %d\n", getpid(), pid);
     
    			// Attente fin fils
    			int p=wait(&status);
    			printf("Fils %d(=%d) terminé (%d)\n", p, pid, WEXITSTATUS(status));
    	}
    }
     
    int main() {
    	f();
    }

    Citation Envoyé par hurukan Voir le message
    La fonction main() cache un fork()... si mes souvenirs sont bons.
    Absolument pas. C'est le shell qui cache un fork. Quand tu lances une commande shell (ou un programme) le shell lance un fork et c'est le shell fils qui se charge d'exécuter le programme pendant que le père attend la fin (un peu comme mon code où le père attend la fin du fils).
    Et c'est grâce à ce système que tu peux lancer un programme en arrière plan via le "&". Dans ce cas rien ne change sauf que le père n'attend pas la fin du shell fils.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

Discussions similaires

  1. [AC-2003] Comment appeler une fonction avec deux paramètres. Erreur '=' attendu
    Par nirG95 dans le forum VBA Access
    Réponses: 1
    Dernier message: 02/09/2009, 10h53
  2. Comment appeler une fonction externe avec XPath
    Par ttttnht dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 19/06/2009, 13h54
  3. Réponses: 2
    Dernier message: 30/10/2008, 18h30
  4. Réponses: 3
    Dernier message: 19/03/2008, 22h11
  5. [JQUERY] Comment appeler une fonction php avec jquery
    Par popogendarme dans le forum jQuery
    Réponses: 1
    Dernier message: 20/03/2007, 16h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo