Contenu | Rechercher | Menus

Annonce

L'équipe des administrateurs et modérateurs du forum vous souhaite d'excellentes fêtes de fin d'année !

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 24/12/2018, à 21:52

sabayke

programmation réseau avec la fonction fork

Salut la famille je suis en licence 3 réseau et télécommunication.
j'ai un petit problème avec mon code

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

  int main(void)
  {
     int i, status;
     pid_t fils, fin;

     if ((fils = fork()) == -1) {     /* au cas ou y a une erreur */
        perror("erreur fork");
        exit(EXIT_FAILURE);
     }
     else if (fils == 0) {            /* les 5 fils.          */
      for(i=0; i<=4;i++)
	{
        printf("Le fils, processus[%d], mon pid[%d], mon ppid[%d]\n",i, getpid(), getppid());
        sleep(10);                       /* fais dodo pour 10 secondes.       */
        exit(EXIT_SUCCESS);
	}  
  			 }
     else {                              /* Papa.         */

        printf("Le père , mon pid[%d], mon ppid[%d]\n", getpid(), getppid());

           /* Le père doit attendre 20 secondes pour que les fils terminent            */
        for(i = 0; i < 25; i++) {
           fin = waitpid(fils, &status, WNOHANG|WUNTRACED);
           if (fin == -1) {            /* erreur de waitpid       */
              perror("erreur dans la fonction waitpid\n");
              exit(EXIT_FAILURE);
           }
           else if (fin == 0) {        /* les processus fils sont en cours d'éxecutions        */

              printf("Les processus fils sont en cours d'éxecutions\n");
              sleep(1);
           }
           else if (fils == fin) {  /* les 5 processus ont termine           */
              if (WIFEXITED(status))
                 printf("je suis mort :( ");
              else if (WIFSIGNALED(status))
                 printf("y a un signal qui m'a tué:(((((.n");
              else if (WIFSTOPPED(status))
                 printf("le processus fils est arréte.n");
              exit(EXIT_SUCCESS);
           }
        }
     }
  }

le problème c'est qu'il affiche juste un seul processus je sais pas pourquoi ???

Hors ligne

#2 Le 24/12/2018, à 22:10

Naziel

Re : programmation réseau avec la fonction fork

Je vois deux processus (un père un fils) avec pstree mais c'est normal puisque fork() n'apparaît qu'une fois et en dehors de la boucle for

Dernière modification par Naziel (Le 24/12/2018, à 22:11)

Hors ligne

#3 Le 24/12/2018, à 23:43

sabayke

Re : programmation réseau avec la fonction fork

D'abord merci pour votre réponse Monsieur Naziel.
Donc si je veux créer 5 processus fils je dois appeler la fonction fork() dans la boucle for ?
exemple

for(int i=0; i<=4; i++)
{
fork();
printf("[processus [%d], mon pid[%d],  mon ppid[%d]\n", i, getpid(), getppid());
}

Mais dans ce cas comment peut on différencier le processus père et le processus fils.

Hors ligne

#4 Le 25/12/2018, à 05:57

NicoApi73

Re : programmation réseau avec la fonction fork

Bonjour,
Une bonne explication du fonctionnement de fork() : https://www.commentcamarche.net/faq/106 … it-un-fork.

Hors ligne

#5 Le 25/12/2018, à 10:21

Naziel

Re : programmation réseau avec la fonction fork

sabayke a écrit :

Monsieur Naziel

Je préfère Monseigneur big_smile

J'imagine que getpid revoie le pid du processus lancé, mais le fils ressort il lui aussi ses messages sur le même terminal que le père?
Dans le lien que tu donnes Nico, pid c'est vraiment le pid? Pour moi ce serait plus un code d'erreur ou d'exécution correcte (ce qui est assez trompeur)

Et aussi appeler 2 fois fork() va t'il vraiment créer deux processus de plus ou va t'il en faire 3 (le père, puis le père 1 fils, puis le père 3 fils (un venant du père et 1 du fils))

Edit: mon impression se confirme: https://www.geeksforgeeks.org/fork-system-call/ indique qu'il y a 2^n processus avec n forks, avec n entier naturel. Donc pour avoir 5 fils, faut ruser.


Et joyeux Noël à vous deux!

Dernière modification par Naziel (Le 25/12/2018, à 10:34)

Hors ligne

#6 Le 25/12/2018, à 11:07

NicoApi73

Re : programmation réseau avec la fonction fork

Naziel a écrit :

Je préfère Monseigneur big_smile

Tu as oublié la petite icone de celui qui se prosterne big_smile

Je ne suis pas chez moi pour regarder en détail dans les bibliothèques : https://fr.wikipedia.org/wiki/Fork_(programmation) Dans le lien que tu as mis, c'est également précisé :

It takes no parameters and returns an integer value. Below are different values returned by fork().

Negative Value: creation of a child process was unsuccessful.
Zero: Returned to the newly created child process.
Positive value: Returned to parent or caller. The value contains process ID of newly created child process.

Joyeux Noël à vous 2 également (@Naziel : pas trop de copies sous le sapin? wink )

Hors ligne

#7 Le 25/12/2018, à 11:08

Naziel

Re : programmation réseau avec la fonction fork

Nico a écrit :

@Naziel : pas trop de copies sous le sapin?

@Nico: Aucune smile Faut être stratège, on verra ça à la rentrée big_smile

Dernière modification par Naziel (Le 25/12/2018, à 11:09)

Hors ligne

#8 Le 26/12/2018, à 13:59

NicoApi73

Re : programmation réseau avec la fonction fork

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

int main(void)
{
	int i;
	pid_t pid_current;
	
	pid_current = getpid();
	printf("Avant la boucle : Le père , mon pid[%d]\n\n", pid_current);
	     
	for (i=0; i<5; i++)
	{
		printf("boucle %d\n", i);		
		if (pid_current != 0)
		{
			if ((pid_current = fork ()) == -1)
			{     /* au cas ou y a une erreur */
				perror("erreur fork");
				exit(EXIT_FAILURE);
			}
			if (pid_current != 0)
				printf("Le père , mon pid[%d], mon ppid[%d]\n\n", getpid(), getppid());
			else
			{
				printf("Le fils, processus[%d], mon pid[%d], mon ppid[%d]\n",i, getpid(), getppid());
				sleep(10);                       /* fais dodo pour 10 secondes.       */
				printf("Le fils, FIN processus[%d], mon pid[%d], mon ppid[%d]\n",i, getpid(), getppid());
				exit(EXIT_SUCCESS);
			}
		}		
	}
	wait (NULL);
	printf ("\nFin processus père\n");
}

Hors ligne

#9 Le 26/12/2018, à 14:32

Naziel

Re : programmation réseau avec la fonction fork

Ça fonctionne mais je ne comprends pas pourquoi il n'y a que 5 fils et non 2^5 fils ou 2^5-1 . Les fils sont ils connectés à la même sortie standard ou sont ils déconnectés?

Hors ligne

#10 Le 26/12/2018, à 16:05

NicoApi73

Re : programmation réseau avec la fonction fork

Les fils sont connectés à la même sortie standard. Par contre le contexte est dupliqué entre les fils et le père.

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

int main(void)
{
	int i;
	pid_t pid_current;
	
	pid_current = getpid();
	printf("Avant la boucle : Le père , mon pid[%d]\n\n", pid_current);
	     
	for (i=0; i<5; i++)
	{
		printf("boucle %d\n", i);		
		if (pid_current != 0)
		{
			if ((pid_current = fork ()) == -1)
			{     /* au cas ou y a une erreur */
				perror("erreur fork");
				exit(EXIT_FAILURE);
			}
			if (pid_current != 0)
				printf("Le père , mon pid[%d], mon ppid[%d], le pid du nouveau fils [%d]\n\n", getpid(), getppid(), pid_current);
			else
			{
				printf("Le fils, processus[%d], mon pid[%d], mon ppid[%d],le retour de fork [%d]\n",i, getpid(), getppid(), pid_current);
				sleep(10);                       /* fais dodo pour 10 secondes.       */
				printf("Le fils, FIN processus[%d], mon pid[%d], mon ppid[%d]\n",i, getpid(), getppid());
				exit(EXIT_SUCCESS);
			}
		}		
	}
	wait (NULL);
	printf ("\nFin processus père\n");
}

Hors ligne

#11 Le 27/12/2018, à 21:17

NicoApi73

Re : programmation réseau avec la fonction fork

Naziel a écrit :

Ça fonctionne mais je ne comprends pas pourquoi il n'y a que 5 fils et non 2^5 fils ou 2^5-1 . Les fils sont ils connectés à la même sortie standard ou sont ils déconnectés?

As tu compris?

Hors ligne

#12 Le 27/12/2018, à 21:57

Naziel

Re : programmation réseau avec la fonction fork

Hum, non, je suis resté bloqué sur l'idée du 2^n

Vu qu'on duplique le contexte, je vois pas pourquoi il y aurait pas 2^n processus, vu que le père et les fils exécutent tous la commande fork()

Dernière modification par Naziel (Le 27/12/2018, à 22:10)

Hors ligne

#13 Le 27/12/2018, à 23:33

NicoApi73

Re : programmation réseau avec la fonction fork

Naziel a écrit :

Vu qu'on duplique le contexte, je vois pas pourquoi il y aurait pas 2^n processus, vu que le père et les fils exécutent tous la commande fork()

Non, ils n'exécutent pas tous la commande fork. Seul le père l'exécute, grâce au premier :

		if (pid_current != 0)

Le contexte étant dupliqué, pid_current vaut 0 dans le contexte des fils et il vaut le pid du père au premier passage dans la boucle, puis celui du fils créé dans le passage précédent par la suite.

Il y a également le exit(EXIT_SUCCESS); qui permet d'arrêter la boucle des fils. J'ai remodifié le code et je l'ai commenté pour une meilleur compréhension. J'ai viré également le exit, qui permet de voir les fils passer dans la boucle plusieurs fois, le nombre de fois dépendant du nombre de fois que le père est déjà passé dans la boucle :

int main(void)
{
	int i,j=-1;
	pid_t pid_current;
	
	pid_current = getpid();
	printf("Avant la boucle : mon pid[%d]\n\n", pid_current); // Affiche le PID du père
	     
	for (i=0; i<5; i++)
	{
		printf("boucle %d, pid[%d],fils (si positif ou nul) : %d\n", i,pid_current,j); // Donne le n° de la boucle, la valeur du PID dans ce contexte et le n° du fils (-1 pour le père). Prouve que le contexte est dupliqué, j est unique pour chaque fils		
		if (pid_current != 0) // on ne rentre ici que dans le cas du père, interdit pour les fils
		{
			if ((pid_current = fork ()) == -1) // création d'un fils
			{     /* au cas ou y a une erreur */
				perror("erreur fork");
				return -1;
			}
			if (pid_current != 0) // on passe ici pour le père (si le PID est != de 0
				printf("Le père , mon pid[%d], mon ppid[%d], le pid du fils %d [%d]\n\n", getpid(), getppid(), i, pid_current);
			else // sinon, pour les PID nuls, c'est un fils et on passe ici
			{
				printf("Le fils, processus[%d], mon pid[%d], mon ppid[%d],le retour de fork [%d]\n",i, getpid(), getppid(), pid_current);
				j=i; // pour prouver que le contexte est dupliqué.
				sleep(10);                       /* fais dodo pour 10 secondes.       */
			}
		}		
	}
	
	if (pid_current != 0)
	{
		sleep (1); // pour aider à la compréhension
		printf ("=========================================================\n");
		printf ("                FIN CREATION PROCESSUS FILS              \n");
		printf ("=========================================================\n");
		wait (NULL); // Attend la fin des processus fils
		sleep (1); // pour aider à la compréhension
		printf ("\nFin processus père\n");
	}
	else
	{
		sleep (0.5); // pour aider à la compréhension
		printf ("\nFin processus fils %d \n",j);
	}
	return 0;
}

Les commandes sleep à la fin, c'est pour assurer un minimum de synchronisation dans l'affichage. Elles peuvent être supprimées.

Hors ligne

#14 Le 28/12/2018, à 10:02

Naziel

Re : programmation réseau avec la fonction fork

Ah ok! Merci pour l'explication Nico, j'avais zappé le exit!

Hors ligne