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 :

Création d'un anneau de n processus


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 8
    Par défaut Création d'un anneau de n processus
    Bonjour, je bloque depuis plus d'une semaine sur un TP, le prof ne donne pas de correction et j'aurai grandement besoin de le réussir pour réviser en vue du test. La consigne est simple : réaliser un anneau de n processus (passé par argv[1]) qui donnent leur pid au processus suivant.
    J'en suis rendu à avoir une file de processus qui transmettent leur pid au suivant mais le processus n ne peut pas transmettre au processus 1.
    Je vois bien que mon code ne permet pas aux processus de former une boucle mais je n'arrive pas à comprendre comment le transformer pour y parvenir.

    Voici le code en question :

    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
    //écrire la mise en place de l'anneau de n proc
     
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/wait.h>
     
    int main (int argc, char* argv[])
    {
    	if(argc != 2)
    	{
    		printf("Nombre d'arguments incorrect\n");
    		exit(1);
    	}
    	int out, in, i, k;
    	int n = atoi(argv[1]);
    	int* t = (int*)malloc(2*n*sizeof(int));
    	//0 : out; 1 : in
    	for(i = 0; i<n; i++)
    	{
    		pipe(&t[2*i]); 	 	 
    		if(fork()==0)
    		{
     
    			printf("processus : %d\n", i+1);
     
    			//fermeture
    			for(k = 0; k<2*n; k++)
    			{
    				if(k != 2*i+1 && k != 2*i-2) // si k : out ET pas out du precedent
    				{
    					if((i == 0 && k != 2*n-1) || i != 0) // proc 0 : ne ferme pas le in du dernier proc
    					{	
    						//printf("fermeture processus : %d\n", k);									
    						close(t[k]);
    					}	
    				}
    			}
     
    			//transfert des ids
    			in = getpid();	
    			write(t[2*i+1], &in, 4);
    			read(t[2*i-2], &out, 4);
     
    			printf("In : %d\n", in);
    			printf("Out : %d\n", out);
     
    			exit(0);
    		}
    		wait(NULL);
    	}
    	free(t);
    	exit(0);
    }
    Merci de votre aide

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Reprend ton post et mets le code sous balise (le bouton #) sinon c'est illisible.

    Quand on fait un fork(), il est facile de connaître le pid du fils c'est la valeur retournée au fork() du père.
    Pour que le fils trouve celui du père, c'est plus compliqué on peut utiliser un pipe.
    Le père connait le pid de son père, il peut donc le transmettre et on peut utiliser un autre pipe par lequel on recevra le pid du grand-père pour le transmettre à son fils. Le dernier des fils n'aura qu'à le lire.

  3. #3
    Membre régulier
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 8
    Par défaut
    En fait le problème ça serait de faire en sorte que le processus n attende que le processus n-1 ai écrit son pid dans le pipe pour le lire. Je pensais à utiliser un wait sauf dans le processus 0 mais ça ne fonctionne pas.

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Bonjour,

    En fait, il y a plusieurs petits problèmes de conception dans ton programme, et la plupart d'entre eux sont structurels, notamment au fait que ce type de communication peut engendrer des deadlocks, et que la fin de tes processus est mal contrôlée : un processus fils qui meurt trop tôt envoie un signal qui reste en attente, certes, mais si un processus père veut lui écrire, cela provoquera un SIGPIPE. Un processus père qui meurt trop tôt, lui, peut provoquer la fin de sa descendance, même si en principe celle-ci se retrouve attachée à init. À part cela :

    • Lignes 32 à 35, ta clause i != 0 empêche le processus de fermer tout descripteur, quel qu'il soit. Et cela concerne non pas le père original, mais le premier des fils ;
    • Lignes 42 et 43, tu as écrit write(&in) et read(&out) ;
    • Ligne 18, c'est « 0: in ; 1: out » et pas l'inverse. Passe ton programme en revue pour voir si les index de ton tableau sont toujours les bons ;
    • C'eût été beaucoup plus simple de créer récursivement des fils en cascade qui créent à chaque fois leur propre tube, mais du côté de l'arborescence des processus, il est vrai qu'il est préférable de tous les avoir au même niveau ;


    Ce qu'il faut faire, donc, c'est créer un tube si l'on n'est pas le dernier processus OU utiliser t[1] et t[2*i-1] si on l'est.

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 8
    Par défaut
    Je ne comprend pas grand chose à ce que je doit faire algorithmiquement parlant. (notre prof nous a rapidement balancé les fonctions pipe(), close() et fork() et on devait en faire un anneau c'est un peu léger ^^') Le processus 0 se fermera toujours avant que le processus n écrive son pid et donc il ne pourra jamais le récupérer. J'avais essayé avec un tableau 2D, chaque fils créant un tube dans t[i] mais j'arrivais au même résultat.

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par ludocorpe Voir le message
    Le processus 0 se fermera toujours avant que le processus n écrive son pid et donc il ne pourra jamais le récupérer.
    Tout le problème est là. :-) C'est donc une question de conception initiale. Il ne faut donc PAS que les processus se terminent.

    Pour cela, tu fais une boucle infinie donc tu ne sors que lorsqu'un critère donné est rempli : réception d'un signal, frappe au clavier, délai de grâce déterminé en entrant dans ton programme, ou n'importe quoi d'autre. Tu peux aussi utiliser tes tubes pour faire circuler autre chose qu'un PID. Tu peux décider par exemple que l'envoi de la valeur « -1 » doit être interprété comme l'ordre de faire suivre cette valeur dans le tube puis de sortir immédiatement, de façon à provoquer la fin en cascade de tous les processus de l'anneau.

    Mais si tu n'as pas envie de t'ennuyer avec tout cela maintenant, tu peux te contenter d'ajouter alarm(30); juste après fork() dans ton programme. Cela initialisera un timer à 30 secondes, timer qui enverra le signal SIGALRM à l'échéance. Et comme ton programme n'est pas prévu pour les récupérer, ledit signal provoquera par défaut la fin du processus.

    Je ne comprend pas grand chose à ce que je doit faire algorithmiquement parlant. (notre prof nous a rapidement balancé les fonctions pipe(), close() et fork() et on devait en faire un anneau c'est un peu léger ^^')
    Un pipe est une ressource système indépendante du processus qui l'a engendré et/ou de ceux qui l'utilisent. Le tube lui-même est géré par le noyau et est « en dehors » du périmètre de tout processus puisqu'il sert justement à établir une relation entre plusieurs d'entre eux. C'est également un canal de communication unidirectionnel. Quand tu appelles pipe, tu obtiens une paire de descripteurs de fichiers qui correspondent respectivement à l'entrée et à la sortie du tube. Et comme tous les descripteurs de fichiers (qu'ils servent à ouvrir des fichiers ordinaires, des tubes nommés ou des sockets), ils sont hérités par les processus fils lors d'un fork s'ils ne sont pas refermés auparavant.

    Ça veut dire que, dans l'absolu, rien n'empêche un processus de s'écrire à lui-même en écrivant par un bout et en lisant par l'autre puisqu'il dispose des deux descripteurs. Ça signifie également que tu pourrais avoir une dizaine de processus écrivant dans le même tube et une dizaine d'autres lisant le même également. Du côté des rédacteurs, tout ce qui est écrit avec write() est envoyé à la queue-leu-leu dans le tube et, du côté des lecteurs, c'est le premier processus réveillé par l'ordonnanceur et qui est bloqué sur read() qui récupère ce qui s'y trouve, dans la limite de la quantité précisée par le paramètre count. S'il n'y a pas autant de données dans le tube, l'appel système se termine quand même et read() renvoie le nombre de caractère qu'il a pu lire. Évidemment, ce n'est pas ce qu'on a l'intention de faire ici.

    Ce n'était pas une mauvaise idée de créer en une fois autant de tubes que de processus. Et utiliser un tableau à deux dimensions était même une très bonne idée. Les seules choses qu'il faut retenir est qu'un tube doit se trouver « entre » deux processus, et qu'il doit y avoir un relation de congruence, comme un modulo, quand tu arrives au bout de la liste. Par exemple, pour dix processus et dix tubes, chacun numérotés de 0 à 9 :

    • le tube numéro 0 doit être partagé entre le processus 0 et le processus 1 ;
    • le tube numéro 1 doit être partagé entre le processus 1 et le processus 2 ;
    • le tube numéro 2 doit être partagé entre le processus 2 et le processus 3 ;
    • le tube numéro 9 doit être partagé entre le processus 9 et le processus 0.


    Ça veut dire que juste après ton fork, là où tu as écrit "processus : %d", tu simplement dois contrôler si le processus en question est ou non le dernier de la liste. En fonction de cela, soit tu récupères normalement ton descripteur, soit tu utilises celui du début de liste, tout simplement. Et tu fermes les autres ensuite. Tu peux même faire cela en une seule clause en utilisant judicieusement l'opérateur modulo « % ».

    Tu peux rendre ton programme plus clair en déclarant d'emblée deux variables p_in et p_out auxquelles tu assigneras dès le départ les bons descripteurs, puisés aux bons endroits dans ton tableau et ne plus avoir à faire le calcul par la suite dans ton code.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. création d'une liste chainé de processus
    Par katiii dans le forum Général Java
    Réponses: 5
    Dernier message: 07/12/2007, 10h45
  2. création de plusieurs processus
    Par Paul75 dans le forum Linux
    Réponses: 5
    Dernier message: 29/01/2007, 11h22
  3. Réponses: 6
    Dernier message: 20/12/2006, 08h55
  4. fork & création de processus
    Par seb__ dans le forum POSIX
    Réponses: 3
    Dernier message: 08/10/2006, 23h42
  5. Problème création et destruction de processus.
    Par loupdeau dans le forum MFC
    Réponses: 5
    Dernier message: 08/04/2005, 13h33

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