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

Programmation et administration système Perl Discussion :

[Perl] mécanismes du fork


Sujet :

Programmation et administration système Perl

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Points : 314
    Points
    314
    Par défaut [Perl] mécanismes du fork
    Bonjour à tous,
    Voilà, je poste depuis un ou deux jours pour apprendre à utiliser fork() et pipe() mais je galère.
    Alors je voudrais d'abord avoir quelques point d'éclaircissement théorique sur ces deux mécanismes:

    J'ai donc plusieurs questions :

    #################Question sur fork##################
    fork permet de générer un processus fils. On peut l'utiliser de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $pid=fork();
    if $pid==0
    {
          #Le fils (processus A') est né et éxécute le code entre les accolades
    }
    else
    {
          #C'est le père (processus A) qui éxécute le code entre les accolades
    }
    Mes questions la-dessus:
    1) Est-ce que le processus fils A' a accès aux variables définies dans A et inversement ???
    2) Est-ce que les processus A et A' s'éxécute simultanément si l'on décide de ne pas mettre le code suivant dans A:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    waitpid($pid,0) #ou wait()
    3) Si j'écris le code suivant:
    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
     
    $pid=fork();
    if $pid==0
    {
          #Le fils (processus A') est né et éxécute le code entre les accolades
          $pid2=fork();
          if($pid2==0)
          {
                #petit-fils ??? (processus A'')
          }
          waitpid($pid2,0);
    }
    else
    {
          #C'est le père (processus A) qui éxécute le code entre les accolades
    }
    Est-ce que A'' ($pid2) est le petit-fils de A. Si oui, A'' a t'il accès aux variables de A ?

    4) Est-ce que finalement, le code de dessus revient pas à faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    $pid=fork();
    $pid2=fork();
    if $pid==0
    {
    #Le fils 1 (processus A') est né et éxécute le code entre les accolades
    }
     
    if($pid2==0)
    {
    #Le fils 2 (processus A'') est né et éxécute le code entre les accolades
    }
     
    #C'est le père (processus A) qui éxécute le code entre les accolades
    c'est à dire lancer 2 fils ??

    ##############Questions sur Pipe###############

    Pipe(entree, sortie) permet de communiquer entre deux processus
    1) Comment faire pour écraser l'entrée (là ou le père écrit à son fils par exemple) à chaque fois que le père écrit.

    Ex: Je fais un script dans lequel le père fait des calculs et envoie le résultat au processus fils.
    Le fils, toutes les secondes doit récupérer le dernier résultat en lisant le pipe.
    Mais en 1 seconde, le père a eu le temps d'écrire des centaines de résultats sur le pipe. Donc le fils récupère tout ça et ça va pas !!!

    2) Est-ce que ce raisonnement est, justement, la bonne manière de raisonner ???

    ##################Questions générales################
    1) Quels avantages apportent fork.Est-ce que fork permet d'augmenter la mémoire alloué au programme ?Est ce qu'utiliser fork rend le script plus stable, plus rapide ?

    2) Ecrire dans un fichier pour passer l'info d'un processus à un autre est il beucoup plus lent qu'utiliser un pipe ? (2eurocents avait répondu à cette question mais je ne le retrouve plu (désolé))


    Enfin voilà, désolé pour le post un peu long mais j'me pose plein de questions. Si vous pouvez répondre à quelques unes d'entre elles (car je comprend bien que répondre à toutes doit être saoulant), ça serait super.

    Merci encore, bonne journée et longue vie à ce forum.
    tout le monde est d'accord pour critiquer la pensée unique

  2. #2
    Yux
    Yux est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 105
    Points : 74
    Points
    74
    Par défaut
    Salut,

    Je ne vais pas répondre en détail à toutes tes questions mais je peux peut-être t'éclairer sur le fonctionnement du fork(). Première chose, le but de cet appel système est de créer un second processus à partir d'un processus existant. Ce qu'il faut comprendre, c'est qu'un processus B ne pourra jamais accéder aux variables d'un processus A si tu ne mets pas en place les mécanismes requis (IPC, mémoire partagée...) et ce même si B est le fils de A. Le mécanisme de fork() veut que lorsqu'il est créé, le processus fils dispose d'un environnement identique en tout point à celui du père. Les variables de B ont donc les mêmes valeurs que celles de A. Juste après le fork(), les pages mémoires contenant les données du processus père sont marquées en lecture seule, et si l'un ou l'autre des processus tente de modifier une donée en écriture, une ou des nouvelle(s) page(s) mémoire est allouée(s) pour le processus fils, contenant une copie de la variable initiale ou la nouvelle variable modifiée. Ce mécanisme est appelé COW (copy on write). Il permet d'alléger le mécanisme du fork(), dans la mesure ou la création d'un nouveau processus requiert peu d'allocation mémoire immédiate.

    Troisième chose, une fois créé, le nouveau processus vit sa vie indépendamment de celle de son père, à moins que tu n'utilise dans ton code des mécanismes de synchronisation (sémaphores, etc...). Sinon, les processus s'exécutent tour à tour en fonction des décisions de l'ordonnanceur et tu n'auras aucun moyen de contrôler ces exécutions.

    fork() n'apporte aucun avantage, il répond à un besoin : peux-tu te contenter pour arriver à tes fins d'un code dont l'exécution sera séquentielle ou dois-tu mettre en place des mécanismes parallèles ? Dans le deuxième cas, il te faudra créer un ou plusieurs nouveau(x) processus.

    fork() n'a rien à voir avec la gestion de la mémoire. Si ton programme a besoin de davantage de mémoire, elle lui sera allouée par l'interpréteur perl. En sortie d'un fork(), la mémoire centrale utilisée aura augmenté (allocation de pages pour le nouveau processus).

    fork() n'impacte pas la stabilité, et aurait plutôt tendance à ralentir l'exécution (la création d'un nouveau processus est coûteuse en terme de ressources systèmes, on ne le fait que si cela s'impose). Ton script ne sera pas plus rapide.

    Pour répondre à tes questions sur le pipe, il serait beaucoup plus lent de passer par un fichier plutôt que par un pipe (données écrites et lues sur le disque contre données écrites et lues en mémoire). Il faut que tu t'arranges pour que ton processus père écrive sur l'entrée standard du fils. Pas besoin d'écraser l'entrée, le fils lira les données au fur et à mesure de leur arrivée. Tu peux utiliser une boucle de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while (my $data = <STDIN>)
    {
         Le traitement des données
    }

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Points : 314
    Points
    314
    Par défaut
    Bonjour Yux et 'abord, merci beaucoup pour tes réponses et explications,
    j'y vois un peu plus clair.

    D'après ce que tu m'as expliqué, j'ai encore deux dernières questions à te poser:
    Citation Envoyé par Yux
    Salut,
    Troisième chose, une fois créé, le nouveau processus vit sa vie indépendamment de celle de son père, à moins que tu n'utilise dans ton code des mécanismes de synchronisation (sémaphores, etc...). Sinon, les processus s'exécutent tour à tour en fonction des décisions de l'ordonnanceur et tu n'auras aucun moyen de contrôler ces exécutions.
    Ou puis-je trouver de la doc sur les mécanismes de synchronisation entre processus ?Est-ce compliqué à mettre en place ?

    fork() n'apporte aucun avantage, il répond à un besoin : peux-tu te contenter pour arriver à tes fins d'un code dont l'exécution sera séquentielle ou dois-tu mettre en place des mécanismes parallèles ? Dans le deuxième cas, il te faudra créer un ou plusieurs nouveau(x) processus.
    J'ai fait un script très récemment et je me demande si il requiert des fork() finalement. Peux tu y jeter un coups d'oeil et me dire ce que tu en penses:

    Script:
    partie client: envoie d'un message par socket
    partie serveur: joue un son et affiche une boite d'alerte. Le son est arrêté lorsque acquitte la boite de dialogue:
    script client.pl
    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
     
     my $Code_Erreur=$_[0];
          my @Nom_PC=('PC1','PC2','PC3');
     
          foreach(@Nom_PC)
          {
                #print "Message envoye  &Domain2IP($_)\n";
                $socket = new IO::Socket::INET (
                        PeerHost => &Domain2IP($_) ,
                        PeerPort => 5004 ,
                        Proto => 'tcp' ,
                        );
     
                if($socket)
                {
                      print $socket "$Code_Erreur" ;
                      $socket -> flush ( ) ;
                      close ( $socket ) ;
                }
          }
    script serveur.pl
    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
     
    #!c:\perl\bin\perl.exe
     
    use IO::Socket::INET ;
    use IO::Handle;
    use TX2::IntSocks;
    use Tk;
    use win32::sound;
     
    #%Texte: Cle: Nom du code erreur
    #        Tableau 1er elt: Texte de description d'erreur  
    #                2nd elt: fichier d'erreur
     
    %Texte=(Code1=>["L\'automate semble être arrêté\,impossible de trouver HBSTATO\.RUN","station1.wav"],
            Code2=>["L\'automate semble être arrêté\,la derniere vérification de l'automate est trop ancienne","station2.wav"],
            Code3=>["Il y a eu une erreur de traduction","station3.wav"],
            Code4=>["Il y a eu une erreur de communication","station4.wav"]
           );
     
    $socket = new IO::Socket::INET (
                        LocalPort => 5004 ,
                        Proto => 'tcp' ,
                        Listen => 5 ,
                        Reuse => 1
                  ) ;
     
    $socket -> autoflush ( 1 ) ;
     
    while ( $nouvelle_socket = $socket -> accept ( ) ) 
    {
    $Code_message=<$nouvelle_socket>;
      $pid_fils = fork ( ) ;
      if ( $pid_fils == 0 )
      {
          while(1)
          { 
              print $Code_message;
              &TX2::IntSocks::PlaySound(@{$Texte{$Code_message}}[1]);
              sleep(1);
          }
     
      }
     
          $status=&TX2::IntSocks::Alert(@{$Texte{$Code_message}}[0]);
          if($status eq 'ok')
          {
                kill(9,$pid_fils);
          }
    }
    package TX2::IntSocks
    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
     
    #!c:\perl\bin\perl.exe
    package TX2::IntSocks;
    use Tk;
    use win32::sound;
    $wav_folder="\\\\161.xxx.xxx.xxx\\d\\#Divers\\Outils\\WavSound\\";
     
    sub Alert()
    {
          my $message=$_[0];
          $fenetre = new MainWindow ( ) ;
          $fenetre -> title ( "Message d\'alerte de TX2" ) ;
     
          $label = $fenetre -> Label( -textvariable => \$message ) ;
          $label->pack();
          $bouton = $fenetre -> Button ( -text => 'Acquitter',-command=>sub{$fenetre->destroy();StopSound();return 'ok';} ) ;
          $bouton -> pack ( ) ;
          MainLoop();
    return 'ok';
    }
    sub StopSound()
    {
          Win32::Sound::Stop();
    }
    sub PlaySound()
    {
            my $file=$_[0];
            $file=$wav_folder.$file;
            Win32::Sound::Volume('200%');
            Win32::Sound::Play($file);
            Win32::Sound::Stop();
            return;
    }
     
    -1;
    Ce script fonctionne (à peu près) mais j'ai des problème de ressource mémoire au niveau de celui qui éxécute le script serveur, à chaque alerte reçue, ma mémoire augmente de 6 Mo environ

    Voilà, merci en tout cas pour tes réponses.
    tout le monde est d'accord pour critiquer la pensée unique

  4. #4
    Yux
    Yux est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2004
    Messages : 105
    Points : 74
    Points
    74
    Par défaut
    Je ne vais pas vraiment pouvoir t'aider pour le perl ; je connais mieux les IPC et autres tubes en C. Mais une simple recherche cpan sur le terme IPC te donne une belle floppée de réponses Pour ce qui est de ton script, je n'ai pas très bien compris le détail du fonctionnement mais la seule chose qui pourrait expliquer l'augmentation de mémoire (à mes yeux), c'est le passage de variables volumineuses en arguments des fonctions. En effet, à chaque appel de procédure, une copie de la variable passée en argument est effectuée sur la pile, et la fonction travaille sur cette copie. Corollaire : si tu passes en argument à l'une des tes fonctions un fichier de 6Mo, l'interpréteur allouera 6Mo de mémoire (ou moins si ta pile est déjà dimensionnée pour les absorber, ne serait-ce que partiellement). Pour éviter cela, tu peux passer à la fonction une référence sur la variable (l'adresse de ta variable en mémoire).

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Tu n'as vraiment pas besoin de fork() ici (forker un processus perl est souvent couteux, même si 6Mo me semble gros). Il te suffit d'utiliser à la place les fonctions du module Tk::after pour programmer ton son, à la fermeture de ta fenètre principale, la boucle d'évènement s'arrètera toute seule.

    (quand aux IPC, Perl dispose d'à peu près tous les mécanismes d'IPC disponible sur plateforme Unix, pipe, sémaphore, mémoire partagée....)

    --
    Jedaï

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    801
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 801
    Points : 314
    Points
    314
    Par défaut
    Ok, merci beaucoup pour vos réponses Yux et Jedaï. Je vais donc refaire le script sans fork, regarder du côté de Tk::after et qd je ferais un ptit tour du côté du cpan pour me documenter sur les IPC.

    Bonne matinée !!!
    tout le monde est d'accord pour critiquer la pensée unique

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

Discussions similaires

  1. Perl OO: Class et fork()
    Par Joccy dans le forum Langage
    Réponses: 1
    Dernier message: 05/10/2007, 13h34
  2. équivalent du fork() de perl ?
    Par minusette dans le forum Langage
    Réponses: 2
    Dernier message: 04/07/2007, 16h20
  3. Probleme processus Fork PERL
    Par djezair31 dans le forum Langage
    Réponses: 3
    Dernier message: 02/10/2006, 16h00
  4. [PERL] Problème en essayant de comprendre fork et pipe
    Par LE NEINDRE dans le forum Langage
    Réponses: 6
    Dernier message: 04/10/2005, 15h23
  5. [Perl]problème avec fork
    Par LE NEINDRE dans le forum Programmation et administration système
    Réponses: 1
    Dernier message: 23/09/2005, 15h31

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