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

Linux Discussion :

fork(), le père doit attendre le fils et vice versa [Débutant(e)]


Sujet :

Linux

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 49
    Par défaut fork(), le père doit attendre le fils et vice versa
    Bonjour,
    voila mon problème , je dois faire un code qui après un fork() utilise un pipe afin de transmettre les entrées standard du père au fils qui doit les afficher.

    Voici mon code:
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
     
     
     
    int main(int argc,char* argv[])
    {
    int tube[2],i;
    pid_t pid;
    char chaine[20];
    pipe(tube);
    pid=fork();
     
    if(pid!=0)
    	{//PERE
    		for(i=0;i<10;i++)
    		{
    		printf("Donnez moi une chaine de caractere<20 \n");
    		scanf("%s \n",chaine);
    		write(tube[1],chaine,sizeof(chaine));
    		kill(pid,SIGUSR1);//On va en 1
    		pause();
    		//2
    		}
    		//wait(NULL);
    	}
    	else
    	{//FILS
    	for(i=0;i<10;i++)
    		{
    		pause();
    		//1
    		read(tube[0],chaine,sizeof(chaine));
    		printf("%s \n",chaine);
    		kill(getppid(),SIGUSR2);//On va en 2
    		}
    	}
    return 0;
    }
    }

    Mais le problème , c'est que la communication entre les processus ne se fait pas et je rentre dans une boucle infinie dans le père.Je ne comprends pas pourquoi.Car pause() doit s'interrompre lors de l'envoie d'un signal.

    J'ai essaye de faire une autre version de ce code sans utiliser pause() , mais en interceptant avec signal() , mais cela n'a pas été concluant non plus.

    Merci de m'aiguiller.

    N.B.: Je ne dois pas me servir de sémaphore.

  2. #2
    Membre éclairé
    Homme Profil pro
    Sécurité
    Inscrit en
    Février 2011
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2011
    Messages : 53
    Par défaut Fermer les bouts
    Bonsoir,


    Pour commencer, je te conseillerai de fermer le côté du tube qui ne t'intéresse pas.
    C'est à dire, dans le père fermer le tube[0] et dans le fils fermer le tube[1].

    Egalement, il faut qu'à la fin du code du père comme du fils, tu fermes le tube sur lequel tu travaillais.

    Finalement, pourquoi te sers tu de pause() et de kill(...) ? Es tu obligé de t'en servir?
    Je te demande ça car j'ai un producteur-consommateur comme toi et je ne m'en suis pas servi et il marche très bien...

    Bonnes modifications


    Graimbault

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 36
    Par défaut
    Salut ^^

    J'ajouterais quelques petites choses:

    Si tu utilises les signaux, il faut les dérouter.

    Je pense que tu ne fais pas une boucle infinie, mais ton père est bien en attente:

    - Tu crée deux processus,
    - Un des deux processus prends la main:

    Deux possibilités:

    1. Le père prend la main en premier:
    Il écrit sur le tube, envoie un signal au fils. Mais tu n'as pas dérouté le signal dans le code du fils, donc l'action par défaut c'est une terminaison anormale => le fils est tué.
    le père exécute pause(), du coup il passe en attente d'un signal qu'il ne recevra jamais.

    2. Le fils prends la main en premier
    Il lit sur le tube, rien n'est écrit donc il attend.
    Le père prend la main à un moment ou un autre, il écrit sur le tube.
    Deux possibilités:
    - Il garde la main et il envoie le signal, cf 1.
    - Le fils reprends la main: il envoie un signal au père, et de la même manière vu que le père ne déroute pas ce signal, il se termine.Le fils est soit rattrapé par le processus init, soit tué (de mémoire, je crois qu'il est tué). S'il est rattrapé par init, il poursuit son exécution et se met en pause.

    Pour conclure sur ce point, il faut bien comprendre qu'il est impossible de prévoir à l'avance quel processus va exécuter son code en premier.

    Autrement, l'utilisation seule d'un pipe te permet de communiquer entre le père et le fils.
    Pourquoi ? Car les primitives système read et write sont dites bloquantes (sous certaines conditions, je vais y revenir).

    Il faut matérialiser un pipe par quelque chose qui contient une suite de caractères. Tu peux ajouter ou retirer un certain nombre de caractères.

    Dans ton cas, il faut utiliser deux tubes: un pour communiquer du père vers le fils et un dans le sens contraire.

    Le principe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    PERE:
    Boucle:
       récupération entrée standard;
       écriture sur le premier pipe;
       lecture sur le second pipe;
    Fin boucle
     
    FILS:
    Boucle
       lecture sur le premier pipe;
       affichage;
       écriture sur le second pipe;
    Fin boucle
    Le second pipe permet au fils de dire "père, j'ai lu ce que tu m'as envoyé". Tu peux envoyer une variable de type "drapeau", à savoir une chaine de caractère que tu définis en variable globale.

    Un dernier point: lorsque tu crée un pipe, le père et le fils ont un accès en lecture et écriture sur celui-ci. Il faut garder uniquement celui qui nous intéresse, et fermer l'autre accès avec un close(). Pourquoi? Car on ne récupère pas soi-même ce que l'on écrit !

    Je t'ai dit tout à l'heure que les primitives read, write étaient bloquantes. En fait il y a des règles:

    Si tu lis dans un pipe qui n'a plus d'écrivains, il y a deux cas:
    - Si le tube n'est pas vide, on lit tout ce qui est possible.
    - Si le tube est vide, une fin de fichier est simulée et le read n'est pas bloquant, tu poursuis l'exécution de ton programme.

    Si tu écris dans un pipe qui n'a plus de lecteurs, c'est plus génant, de mémoire tu écris tout ce qui est possible si le tube n'est pas vide et sinon, tu fais un dépassement mémoire (qui doit se caractériser par un buffer overflow, corrigez-moi si je me trompe).

  4. #4
    Membre averti
    Inscrit en
    Octobre 2010
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 49
    Par défaut
    Tout d'abord , merci pour vos réponses.

    Voila mon code modifié:

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <signal.h>
    #include <sys/wait.h>
     
    char drapeau[]="drapeau";
     
    int main(int argc,char* argv[])
    {
    int tube[2],tubeValid[2],i;
    pid_t pid;
    char chaine[20];
    pipe(tube);
    pipe(tubeValid);
     
    pid=fork();
    if(pid!=0)
    	{//PERE
    		close(tube[0]);//Le pere ne fait que ecrire dans ce tube
    		close(tubeValid[1]);//Le pere ne fait que lire dans ce tube
    		for(i=0;i<10;i++)
    		{
    		printf("Donnez moi une chaine de caractere<20 \n");
    		scanf("%s \n",chaine);
    		write(tube[1],chaine,sizeof(chaine));
    		read(tubeValid[0],drapeau,sizeof(drapeau));//Mon fils a bien recu le message
    		}
    		//Je ferme les tubes quand je ne m en sers plus
    		close(tube[1]);
    		close(tubeValid[0]);
    	}
    	else
    	{//FILS
    	close(tube[1]);//Le fils ne fait que lire dans ce tube
    	close(tubeValid[0]);//Le fils ne fait que ecrire dans ce tube
    	for(i=0;i<10;i++)
    		{
    		read(tube[0],chaine,sizeof(chaine));
    		printf("%s \n",chaine);
    		write(tubeValid[1],drapeau,sizeof(drapeau));//Pere , j ai bien reçu ton message
    		}
    		//Je ferme les tubes quand je ne m en sers plus
    		close(tube[0]);
    		close(tubeValid[1]);
    	}
    return 0;
    }
    Cependant , j'ai un petit problème à l’exécution:

    Donnez moi une chaine de caractere<20
    azerty
    pointDAttente
    azerty
    Donnez moi une chaine de caractere<20
    qwerty
    pointDAttente
    Donnez moi une chaine de caractere<20
    leProchainSeraQwerty
    qwerty
    Donnez moi une chaine de caractere<20
    ^C
    Au tout premier pointDAttente , je suis en attente.Mais je ne sais pas d’où:
    _pas du read(tube[0],....) du fils (ce qui m'aurait parut logique) car j'ai essayer en mettant un sleep(10) juste avant le read (ce qui me laissait le temp rentrer ma chaîne dans le père) mais ce la n'a rien changé.
    _pas du père , car les seules situations d'attente sont scanf et read et l'affichage serait alors différents

    Si vous avez une petite idée?

    Merci encore.

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 36
    Par défaut
    A vue d'oeil je n'ai pas trouvé, mais je n'ai pas cherché longtemps non plus

    Du coup j'ai codé rapidement une version de ce que tu recherches, comme ça tu peux comparer et voir ce qui ne fonctionne pas

    Je repasserais un peu plus tard et si tu n'as pas trouvé, je t'aiguillerais.

    Le plus important c'est de réussir à le refaire par soi-même

    Nb: char * est équivalent à char[];

    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
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
     
    #define MAX 50
    #define NB_LECTURES 5
     
    int main(int argc,char** argv) {
      int tubeVersFils[2],tubeVersPere[2], ind;
      pid_t idproc;
     
      char message[MAX], *drapeau;
     
      drapeau = "msg_recu";
     
      pipe(tubeVersFils);
      pipe(tubeVersPere);
     
      idproc = fork();
     
      /* Si le fork échoue */
      if (idproc == -1) {
        fprintf(stderr, "Erreur fork \n");
      }
      /* Code du père */
      else if (idproc != 0) {
        /* Fermeture des accès inutiles */
        close(tubeVersFils[0]);
        close(tubeVersPere[1]);
     
        for (ind = 0; ind < NB_LECTURES; ind++) {
          /* Lecture d\'un message sur l\'entrée standard*/
          scanf("%s",message);
     
          /* Envoi au fils */
          write(tubeVersFils[1], message, sizeof(message));
     
          /* On attends l\'accusé de réception */
          read(tubeVersPere[0], drapeau, sizeof(drapeau));
        }
     
        wait(NULL);
      }
      /* Code du fils */
      else {
        close(tubeVersFils[1]);
        close(tubeVersPere[0]);
     
        for (ind = 0; ind < NB_LECTURES; ind++) {
          read(tubeVersFils[0], message, sizeof(message));
          printf("Fils: message recu: %s \n", message);
          write(tubeVersPere[1], drapeau, sizeof(drapeau));
        }
      }
     
      return 0;
    }

  6. #6
    Membre éclairé
    Homme Profil pro
    Sécurité
    Inscrit en
    Février 2011
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2011
    Messages : 53
    Par défaut Synchro dérangeante
    Bonjour,


    Quelques petites choses...

    D'où viennent tes "pointDAttente"? C'est bien toi qui les a rajouté à la main pour nous décrire ton problème? Etant donné que ne les vois nullepart dans le code je trouve ca bizarre!

    Bref, passons!

    J'aimerai savoir si le fait de faire une boucle (ici de 0 à 10) ne te dérange pas?
    Si j'ai que 2 chaines à rentrer, je suis obligé de faire marcher 10fois la boucle.
    A contrario si j'ai plus de 10 chaines à faire passer, je fais comment?
    Je te proposerais donc de ne pas marcher avec une boucle mais en comparant ce que tu lis avec un éventuel marqueur de fin. Par exemple, si je n'ai plus rien à écrire, je presse la touche "Entrer" une dernière fois et mon programme doit s'arreter.

    Également, je ne vois pas trop l'intéret de ton nouveau tube avec ce drapeau "drapeau".

    Je pense que tu cherche à faire trop compliqué pour un simple producteur-consommateur dans un même fichier, je te propose un algo...

    D'un côté, je stocke la saisie utilisateur dans tabEcr et c'est ca que recopie dans le tube. De l'autre côté, je stocke le contenu du tube dans tabLir et c'est ca que j'affiche.

    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
    DEBUT
         tube();
         SI pere() ALORS
            FERMER(tube[0])
            AFFICHER
            LIRE(tabEcr)
            TQUE !fin FAIRE
                 ECRIRE(tube[1])
                 AFFICHER
                 LIRE(tabEcr)
            FTQUE
            ECRIRE(tube[1])
            FERMER(tube[1])
         SINON
            FERMER(tube[1])
            LIRE(tube[0])
            TQUE !fin FAIRE
                 AFFICHER(tabLir)
                 LIRE([tube[0])
            FTQUE
            FERMER(tube[0])
         FSI
    FIN
    Bonne chance


    Graimbault

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 36
    Par défaut
    Également, je ne vois pas trop l'intéret de ton nouveau tube avec ce drapeau "drapeau".
    Désolé, c'était juste une suggestion que je lui faisais
    De cette manière, ça l'exerce à utiliser les tubes dans les deux sens

    Sinon ouaip, la boucle for, c'est pas top !

  8. #8
    Membre Expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Par défaut
    Salut,

    pour synchroniser deux processus tu peux utiliser des sémaphores.
    http://fr.wikipedia.org/wiki/S%C3%A9...nformatique%29

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

Discussions similaires

  1. Re exécuter un job père à partir du job fils en erreur
    Par taltal dans le forum Développement de jobs
    Réponses: 4
    Dernier message: 08/11/2012, 16h24
  2. auto dimensionnement d'un calque père selon deux calque fils.
    Par death_style dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 04/03/2010, 19h35
  3. [Thread] Un père qui doit attendre la fin des fils
    Par Chatbour dans le forum Concurrence et multi-thread
    Réponses: 9
    Dernier message: 09/09/2008, 14h29
  4. Réponses: 8
    Dernier message: 09/11/2006, 14h01

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