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

Langage Perl Discussion :

[langage] threads en Perl


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut [langage] threads en Perl
    Bonjour,

    J'aimerais un peu d'aide sur les threads. Mon script se connecte sur des routeurs et lance des actions. La liste de routeurs est dans un fichier.

    liste_routeurs.txt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    routeur1
    routeur2
    routeur3
    ...
    mon_script.pl
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    open (FILE, "liste_routeurs.txt") or die "blabla";
    while (<FILE>)
    {
        $routeur = $_;    faire_les_choses_sur_routeur($routeur);
    }
    close FILE;
    Ca c'est ce qui marche, et ca fonctionne sequenciellement (et ca prend du temps)

    En utilisant plusieurs threads je pourrais reduire le temps d'execution du script de maniere drastique, par contre je ne vois pas du tout comment faire.

    Par exemple avec 3 threads:
    routeur1 ----> le thread1 s'en charge
    routeur2 ----> le thread2 s'en charge
    routeur3 ----> le thread3 s'en charge
    ...

    Chaque thread doit lire dans liste_routeurs.txt la ligne suivante qu'un autre thread a lu.

    Une maniere peu elegante a mon gout serait d'utiliser Xmod3 avec X le numero de la ligne pour que :
    - le thread1 s'occupe des routeurs 1,4,7,10,...
    - le thread2 s'occupe des routeurs 2,5,8,11,...
    - le thread3 s'occupe des routeurs 3,6,9,12,...

    Donc je voudrais savoir comment puis-je faire pour que chaque thread lance la fonction faire_les_choses_sur_routeur($routeur) puis passe au routeur qui suit dans la liste mais qui n'a pas encore été géré par un autre thread.
    Ce que je veux dire est dur a expliquer mais simple a comprendre, si je n'ai pas ete assez precis dites le moi.

    Merci

  2. #2
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Salut !

    Personnelement, je n'ai jamais utilisé de threads étant sous windows. Par contre, ave de simples processus, ton cas est facile à traiter :
    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
    sub faire_les_choses_sur_routeur
    {
        my $pid = fork;
        if ($pid <  0)
        {
            die ("Erreur de fork : $!");
        }
        elseif ($pid == 0)
        {
            #le fils fait quelque chose avec $_[0]
            exit 0;
        } 
        else
        {
           #Le père retourne au programme principal
            return 0;
        }
    }
    Peut être peux-tu t'insiper de ce code pour t'aider...
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Oui ca m'a l'air d'etre une autre piste.

    J'ai 1000 routeurs dans mon fichier alors il va falloir que je trouve un moyen pour ne pas créer 1000 processus fils.
    Peut etre mettre un sleep 2 avant que le pere ne retourne au programme principal.

    En sequenciel, mon script met 80 minutes pour executer les opérations sur les 1000 routeurs, ce qui fait a peu pres 4 à 5 secondes par routeur en moyenne.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    427
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 427
    Points : 459
    Points
    459
    Par défaut
    tu fais koi sur tes routeurs?
    Tu a regardé si tu pouvais faire ce que tu veux avec POE?
    Recherche staigiaire(s) motivé(s) sur projet perl/reseau a grande echelle. Me contacter par mp.

  5. #5
    Membre actif Avatar de scaleo
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 327
    Points : 219
    Points
    219
    Par défaut
    Citation Envoyé par Woufeil
    Salut !

    Personnelement, je n'ai jamais utilisé de threads étant sous windows. Par contre, ave de simples processus, ton cas est facile à traiter :
    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
    sub faire_les_choses_sur_routeur
    {
        my $pid = fork;
        if ($pid <  0)
        {
            die ("Erreur de fork : $!");
        }
        elseif ($pid == 0)
        {
            #le fils fait quelque chose avec $_[0]
            exit 0;
        } 
        else
        {
           #Le père retourne au programme principal
            return 0;
        }
    }
    Peut être peux-tu t'insiper de ce code pour t'aider...

    La gestion des threads est meilleur sous unix ou linux ????
    Vista powaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ::

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Sur mes routeurs/switches je fais un show run ou show conf. Ainsi, je recupere la sortie standard de la commande et la mets dans un fichier.
    L'operation prend entre 2 et 40 secondes suivant la puissance de l'equipement.

    POE je ne connais pas...c'est quoi ?

    Je ne sais pas si les threads sont meilleurs sous linux ou unix. Personellement je code ce script sous un HPUX, et d'ailleurs je deteste cet OS. Mais je veux tirer l'avantage de perl en portabilité, donc aujourd'hui c'est HPUX demain ca sera peut etre Linux.

    Je vais commencer a reflechir comment je peux intergrer le fork dans mon script mais je vois deja un petit probleme. Pour qu'il s'execute proprement il faut que le processus pere attende son fils. En fais il doit attendre ses fils car plusieurs fils doivent travailler.

    Si j'integre ton code, je vais avoir en gros un fork pour chaque routeur car le pere va retourner dans le while(<FILE>) qui parse ma liste d'equipements. Comment coder proprement pour que j'ai tout le temps a un instant t 3 fils qui travaillent ? Et pour qu'a la fin le pere attende ses trois fils ?

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    J'ai creusé un peu le sujet, en utilisant ce que tu m'avais suggeré

    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
     
    #!/usr/bin/perl
     
    my $max_proc = 3;
     
    open (FILE, "liste_routeurs.txt") or die "Impossible d'ouvrir le fichier liste_routeurs.txt";
    while (<FILE>)
    {
      my $routeur = $_;
      chomp($routeur);
      fork_it($routeur);
    }
    close FILE;
     
    sub fork_it
    {
      my ($routeur) = @_;
      my $pid = fork;
     
      if ($pid < 0)  {  die ("Erreur de fork : $!\n"); }
      elsif ($pid == 0)
      { do_it($routeur); $max_proc++; exit 0; }
      else
      {
        $max_proc--;
        if($max_proc < 1) { wait(); }
      }
    }
     
    # Cette fonction fais les choses sur le routeur
    sub do_it
    {
      my ($routeur) = @_;
      print "$routeur\n";
      # Le sleep(2) me sert a simuler tout un tas d'autres taches que je fais sur le routeur
      sleep(2);
    }
    A present le script executer les taches 3 par 3, car $max_proc = 3.
    Le wait() du pere attend les deux processus fils.

    Cependant je dois ameliorer c'est que:
    - Il faudrait que le wait() puisse se debloquer des qu'un processus fils se termine (et non pas tous).
    - Que le pere attende que tous ses fils aient fini avant de finir.

    Est-ce que vous avez des suggestions

  8. #8
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Si tu es sous Linux (et je suis presque sûr que tu y es ) renseigne toi sur la fonction waitpid(), elle devrait beaucoup t'intéresser. Elle permet d'attendre la fin d'un processus en particulier. Donc il te suffit d'attendre la fin du premier processus que tu as lancé.

    Evidemment, cela pose un petit souci de programmation (il faut tester la bonne valeur de $pid), mais tu devrais trouver une solution. Au pire, demande nous
    "En essayant continuellement, on finit par réussir. Donc : plus ça rate, plus on a de chances que ça marche" (devise Shadock)
    Application :

    ainsi qu'à regarder la avant de poser une question.

    La rubrique Perl recrute, contactez-moi.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Justement j'y ai pensé aujourd'hui mais je n'ai pas trouvé de facon elegante de le faire. Peut etre mettre chaque pid dans une table de hashage...en fait je vois pas trop. Et j'ai pas tout lu sur le waitpid, ce que j'ai compris c'est que ca fait le wait pour un pid particulier.

    Sinon, le code que j'ai mis ce soir, je l'ai testé sur ma debian et ca marchait comme je voulais. Par contre au taf c'est un hpux et il se comportait pas de la meme maniere (enfin j'avais peut etre pas codé la meme chose).

  10. #10
    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
    Personnellement, j'adopterais plutôt une logique de queue : le père crée des fils en nombre limité puis commence à lire ton entrée et introduit les lignes à traiter dans une queue (un pipe par exemple), les fils lise dans la queue une ligne à la fois et la traite, mais ils ne meurent que lorsqu'ils reçoive une ligne le leur ordonnant (que tu fais envoyer par ton père en quantité appropriée lorsqu'il a fini de lire l'entrée, ensuite celui ci attend la mort de tous ses fils).
    Ca t'évite de consommer inutilement des ressources pour créer et supprimer des processus sans arrêt, c'est nettement plus efficace et ça consomme moins de ressources.

    --
    Jedaï

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Jedai, il me semble que c'est une tres bonne idée.

    Je vais essayer de reflechir et d'implementer ca, je crois me rappeller avoir vu des exemples quelque part quand je cherchais des infos sur les threads or sur fork.

    J'ai pour l'instant reussi, a faire mon script avec les threads grace a quelqu'un d'un autre forum.

    Cependant, vu qu'ici la solution proposée était avec le fork, je vais continuer a reflechir(surement ce week end) pour faire aboutir cette solution aussi.(curiosité intellectuelle)

Discussions similaires

  1. [langage] Script en Perl - besoin d'aide
    Par julfra dans le forum Langage
    Réponses: 8
    Dernier message: 13/05/2004, 14h47
  2. [langage] mkfifo en PERL ?
    Par Gogoye dans le forum Langage
    Réponses: 12
    Dernier message: 21/01/2004, 19h44
  3. [langage] Avis sur Perl
    Par micdie dans le forum Langage
    Réponses: 3
    Dernier message: 30/10/2003, 15h21
  4. [reseaux] Gestion des threads en perl
    Par totox17 dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 28/11/2002, 09h40
  5. [langage] Inclure de perl en c !!!
    Par ryo00 dans le forum Langage
    Réponses: 2
    Dernier message: 30/05/2002, 10h03

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