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 :

Récursivité et fils en parallèle


Sujet :

C

  1. #1
    Membre actif
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Points : 271
    Points
    271
    Par défaut Récursivité et fils en parallèle
    Bonjour,
    je dois développer un programme qui exécute la copie de fichiers en parallèle (avec des processus fils et non des threads). Ca fonctionne couci-couca, étant donné que ce sont des relations père-fils, je ne peux pas utiliser de boucle mais une récursivité, si je ne me trompe pas?

    Donc en gros, l'utilisateur lancera le programme: ./copie texte1.txt texte2.txt texte3.txt

    Le premier fils s'occupe de la copie du fichier texte1.txt, le 2ème texte2.txt,...

    Tous utilisent la fonction copie.

    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
    int traitement(int debut,int argc, char *argv[]){
      int p = fork();
      if (p == -1){
        perror("Erreur de fork()");
      }
      if (p == 0){
        printf("%d %s\n",debut,argv[debut]);
        copie(argv[debut]);
      }
      else{
        debut ++;
        if (debut < argc){
          traitement(debut,argc,argv);
        }
        else{
          return 0;
        }
      }
      return -1; //erreur
    }
     
    int main(int argc, char * argv[]){
      if (argc <= 2){
        perror("Entrez au moins un argument!");
      }
      else{
        if (traitement(1,argc,argv) ==0 ){
          wait(0);
        }
        else{ 
          perror("Erreur de traitement");
          return -1;
        }
      }
      return 0;
    }
    Les copies ont bien lieu mais je ne comprends pas bien le retour qu'il me fait:
    ./ex2 texte.txt texte2.txt texte3.txt
    1 texte.txt
    2 texte2.txt
    Erreur de traitement: Success
    3 texte3.txt
    Erreur de traitement: Success
    Erreur de traitement: Success
    Erreur de traitement: Success
    Pourquoi revient-il dans le main tant qu'il n'a pas fini?

    Merci d'avance

    Edit: en fait j'ai compris, c'est le return -1 quand le fils s'exécute. Où pourrais-je mettre ce retour d'erreur ? Est-ce que ce code est acceptable?
    Utilisez les balises "Code" (alt+c).
    Nous avons répondu à votre question? Pensez au tag

    Le "lol" est aux boulets ce que le ";" est aux programmeurs

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu peux faire une boucle dans le père, pour le lancement de n processus fils.

    PS: Précise "processus fils" car thread == fil. Résultat, quand tu dis "avec des fils et non des threads" il m'a fallu un moment pour comprendre...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre actif
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Points : 271
    Points
    271
    Par défaut
    Je peux difficilement faire une boucle car je veux que les processus fils s'exécutent en même temps. Pas de la programmation séquentielle.

    Ici j'ai des processus fils en parallèles:
    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
        int pid1 = fork();
        if (pid1 ==-1){
          perror("Erreur de fork");
        }
        if (pid1 ==0){ //fils 1 
          sleep(5); //vérification du parallélisme
          copie(argv[1]);
          exit(0);
        }
        else{ //pere
          int pid2 = fork();
          if (pid2 ==-1){
    	perror("Erreur de fork");
          }
          if (pid2 ==0){ //fils 2
    	sleep(5);//vérification du parallélisme
    	copie(argv[2]);
    	exit(0);
          }
          else{ //pere
    	wait(0);
          }
         }
    Avec le sleep(5), je peux vérifier que c'est bien en même temps que les processus fils s'exécutent.

    Avec une boucle for (ou autre), j'aurai des processus fils qui s'exécuteront l'un après l'autre. (séquentielle)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      for (i =1; i < argc; i++){
        int p = fork();
        if (p == -1){
          perror("Erreur de fork()");
        }
        copie(argv[i]);
      }
    Donc je recherche le parallélisme sans savoir combien de fichiers je vais devoir traiter à l'avance, d'où l'idée d'une fonction récursive.

    Encore merci pour votre aide
    Utilisez les balises "Code" (alt+c).
    Nous avons répondu à votre question? Pensez au tag

    Le "lol" est aux boulets ce que le ";" est aux programmeurs

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par v4np13
    Bonjour,
    Ca fonctionne couci-couca, étant donné que ce sont des relations père-fils, je ne peux pas utiliser de boucle mais une récursivité, si je ne me trompe pas?
    Oui tu te trompes...

    Code en cours...

    Edit: en fait j'ai compris, c'est le return -1 quand le fils s'exécute. Où pourrais-je mettre ce retour d'erreur ? Est-ce que ce code est acceptable?
    Non il ne l'est pas car les fils retournent aussi dans le main et donc ca va un jour t'exploser à la figure ...

    Jc

  5. #5
    Membre habitué Avatar de Ksempac
    Inscrit en
    Février 2007
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 165
    Points : 185
    Points
    185
    Par défaut
    Je ne vois pas ce qui te fait dire que le for empeche la "parallelisation" de ton appli :

    Exemple de comportement possible avec le for et n = 4 :

    Le pere itere une fois -> Creation d'un fils
    Le pere itere une fois -> Creation d'un fils
    Le premier fils commence son execution
    Le second fils commence son execution
    Le pere itere une fois -> Creation d'un fils
    Le pere itere une fois -> Creation d'un fils
    Le premier fils continue son execution
    Le second fils continue son execution
    Le troisieme fils commence son execution
    Le troisieme fils commence son execution
    Le premier fils continue son execution
    Le second fils continue son execution
    Le troisieme fils continue son execution
    Le quatrieme fils continue son execution

    etc...

    Chaque processeur a le droit a un certain quota de temps processeur, apres quoi il est retiré du processeur pour laisser la place a un autre. Donc chaque processus ne fait qu'une partie de son job avant qu'un autre processus fasse lui aussi une partie de son job...C'est cela que tu appelles la "parallelisation" : Des processus qui se partagent le CPU.

    La veritable parallelisation concerne les systemes multi-coeurs et/ou multi-processeurs mais ca c'est un autre probleme

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par v4np13
    Je peux difficilement faire une boucle car je veux que les processus fils s'exécutent en même temps. Pas de la programmation séquentielle.
    ....
    Donc je recherche le parallélisme sans savoir combien de fichiers je vais devoir traiter à l'avance, d'où l'idée d'une fonction récursive.
    C'est strictement identique..

    Puisque tu fait une boucle de fork, tu lances (à la vitesse de la boucle, sans doute un peu plus rapide que une fonction récursive) des processus dfférents, qui chacun fera sa copie...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Voici un code qui peut faire ce que tu veux avec une boucle :

    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
    58
    59
    60
    61
    #include <unistd.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    void copie(char *f)
    {
        printf("Hello %s\n",f);
    }
     
    int lancement(char *file) 
    {
        printf("Forked\n");
        pid_t p = fork();
     
        if(p == -1) {
            perror("Erreur de fork()");
            return -1;
        }
     
        if(p==0) { 
            /*Fils*/
            copie(file);
            /* Fils termine */
            exit(EXIT_SUCCESS);
        }
        return 1;
    }
     
    int traitement(int argc, char *argv[])
    {
        int i;
        for(i=1;i<argc;i++) {
            int res = lancement(argv[i]);
     
            if(res == -1) {
                return -1;
            }
        }
        return 0;
    }
     
    int main(int argc, char * argv[])
    {
        if (argc <= 2){
            perror("Entrez au moins un argument!");
        }
        else{
            if (traitement(argc,argv) == 0 ){
                int i;
                for(i=1;i<argc;i++) {
                    wait(NULL);
                }
            }
            else{ 
                perror("Erreur de traitement");
                return -1;
            }
        }
        return 0;
    }
    Jc

  8. #8
    Membre actif
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Points : 271
    Points
    271
    Par défaut
    Citation Envoyé par fearyourself
    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
    int main(int argc, char * argv[])
    {
        if (argc <= 2){
            perror("Entrez au moins un argument!");
        }
        else{
            if (traitement(argc,argv) == 0 ){
                int i;
                for(i=1;i<argc;i++) {
                    wait(NULL);
                }
            }
            else{ 
                perror("Erreur de traitement");
                return -1;
            }
        }
        return 0;
    }
    Tu pourrais m'expliquer la boucle de wait(NULL) ? Je pensais qu'un wait(0) suffisait.

    Merci
    Utilisez les balises "Code" (alt+c).
    Nous avons répondu à votre question? Pensez au tag

    Le "lol" est aux boulets ce que le ";" est aux programmeurs

  9. #9
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Un appel à wait attend qu'un fils termine... Donc si tu lances N fils, il faut N wait...

    Jc

  10. #10
    Membre actif
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Points : 271
    Points
    271
    Par défaut
    Je viens de faire des essais, la grosse différence avec ce que j'ai vu, c'est le exit(EXIT_SUCCESS);.

    Nous ne l'avons pas encore vu au cours, je suppose que je ne dois pas l'utiliser pour faire l'exercice. En fonction de si je le mets ou pas, le fils s'exécute plusieurs fois.

    Ca devrait être possible d'arriver au même résultat sans cette fameuse ligne? (le fonctionnement est fort similaire avec mon premier code, non?)
    Utilisez les balises "Code" (alt+c).
    Nous avons répondu à votre question? Pensez au tag

    Le "lol" est aux boulets ce que le ";" est aux programmeurs

  11. #11
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par v4np13
    Je viens de faire des essais, la grosse différence avec ce que j'ai vu, c'est le exit(EXIT_SUCCESS);.

    Nous ne l'avons pas encore vu au cours, je suppose que je ne dois pas l'utiliser pour faire l'exercice. En fonction de si je le mets ou pas, le fils s'exécute plusieurs fois.

    Ca devrait être possible d'arriver au même résultat sans cette fameuse ligne? (le fonctionnement est fort similaire avec mon premier code, non?)
    Oui mais je ne vois pas l'intérêt de le faire en récursivité...

    Jc

Discussions similaires

  1. Cours : algorithmes et récursivité
    Par Community Management dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 17/10/2018, 00h38
  2. Réponses: 8
    Dernier message: 15/09/2014, 14h11
  3. Problème de récursivité : relation père fils multiple
    Par relbeghdadi dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 26/01/2012, 12h37
  4. Gestion du port paralléle sous 2000
    Par kardex dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 05/01/2006, 19h47
  5. [DOM] suppression d'un noeud fils xml en JAVA
    Par alexandre54 dans le forum Format d'échange (XML, JSON...)
    Réponses: 5
    Dernier message: 20/03/2003, 09h44

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