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 :

Anneau de processus.


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2020
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2020
    Messages : 63
    Par défaut Anneau de processus.
    Bonjour. Alors voilà je dois écrire un programme qui prend en entrée un entier qu'un anneau de N processus doit se passer. A chaque passage dans un processus cet entier doit se décrémenter et lorsqu'il atteint 0 on renvoie le numéro de processus correspondant (compris entre 0 et N, pas le pid). J'ai écrit le code suivant :

    Code C : 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
    62
    63
    64
    65
    66
    67
    68
     
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include "/usr/include/linux/limits.h"
     
     
    void decremente (int a,int n)
    {
        int pid,reason;
        int tubes[n][2];
        int resultat;
     
        int new_value;
     
        int cpt=0;
     
        int lec,ecr;
     
        for (int j=0;j<n;j++){
            if(pipe(tubes[j]) == -1)
                perror("pipe");
        }
        for(int i=0;i<n;i++){
            switch(pid=fork()){
            case -1:
                perror("fork");
                break;
     
            case 0:
                lec=tubes[i][0];
                ecr=tubes[(i+1)%n][1];
     
                if(read(lec,&new_value,PIPE_BUF) == -1)
                    perror("read");
                close(lec);
                new_value--;
     
                if(new_value == 0){
                    resultat=i;
     
                } else {
                    if(write(ecr,&new_value,PIPE_BUF) == -1)
                        perror("write");
                }
                close (ecr);
                break;
     
            default:
                while(cpt < n){
                    if(wait(&reason)==-1)
                        perror("wait");
                }
                break;
            }
        }
        fprintf(stdout, "RESULTAT : %d\n",resultat);
    }
     
    int main (int argc, char**argv)
    {
        if(argc != 3)
           perror("Usage : ./exec <a> <n>");
     
        decremente(atoi(argv[1]),atoi(argv[2]));
    return 0;
    }

    Il semble qu'il y'ait un bloquage au niveau de mon read mais je ne comprends pas pourquoi. Du coup le résutat retourné vaut toujours 0.
    Merci pour 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,

    Il y a en effet "quelques" "petites" erreurs. Mettons nous à le place du code, et voyons pas à pas ce qu'il fait :
    1. nous arrivons vite ligne 25, où nous débutons une boucle de n fork à faire.
    2. plaçons nous dans le cas simple du père
      1. le fork a retourné un pid, on est donc ligne 51
      2. et dès la ligne 51 on a 2 problèmes :
        • notre père attaque une attente de n fils. Mais à cet instant on n'en a créé qu'un!! Et en plus le cpt n'est jamais modifié, donc finalement on attend une infinité de fils!!
        • Est-ce le bon endroit pour attendre la fin de ses fils? N'est-il pas mieux d'être sorti de la boucle de création des fils.
        • et penser à incrémenter un cpt est peut être une idée. On peut aussi utiliser un for() plutôt qu'un while() quand on sait combien d'itérations on veut faire, c'est bien plus simple.

    3. plaçons nous maintenant dans le cas du fils.
      1. on est donc ligne 32
      2. là on décide de lire dans le pipe[0] et d'écrire dans le pipe[1] (à cet instant i est nul pour ce fils, on en est qu'au tout début). Pourquoi pas, mais attention tous les processus doivent fermer les extrémités des pipes qu'ils n'utilisent pas sous peine de recevoir des messages qui ne sont pas pour eux.
      3. et on se met en attente de lecture.
      4. sauf que pour le moment rien de rien n'a été émis
      5. le fils se met donc en attente infinie.


    Donc après démarrage, on a rapidement 2 processus qui tous les deux attendent un miracle.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Je te conseillerais de décomposer un peu plus tes actions parce que tout faire dans "decrementer()" c'est presque comme tout faire dans le main()

    Par exemple tu pourraiis avoir une fonction "fils()" dédiée au travail d'un fils. Cette fonction aurait donc un pipe en entrée et un pipe en sortie.

    Accessoirement je ne vois pas trop à quoi sert ta variable "a" que la fonction reçoit. Et je ne pige pas trop le "on renvoie le numéro de processus correspondant". C'est qui ce "on" ? Et à qui et comment il renvoie sa valeur ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2020
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2020
    Messages : 63
    Par défaut
    Merci pour votre réponse Dalfab. J'avais corrigé les bêtises que vous évoquez dans votre premier paragraphe entre temps

    Pour ce qui est du reste, j'ai donc fait un write juste avant la création des processus. Le passage des valeurs entre les processus se fait plutôt bien ainsi que la décrémentation. Sauf que maintenant, à l'execution le "fprintf" qui est tout à la fin de mon code s'affiche a fois, et je ne comprends pas vraiment pourquoi.
    De plus, il s'affiche avec une valeur bizarre : normal, je modifie la variable "résultat" dans un processus fils, donc ce n'est pas la même variable résultat que je modifie ... Du coup il faut que je réfléchisse à comment signaler le résultat correctement. Il faut que je fasse un exit(i), mais je ne vois pas trop comment manipuler ensuite wait pour récupérer la valeur de i ..

    voici mon code dans l'état actuel des choses :
    Code c : 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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include "/usr/include/linux/limits.h"
     
     
    void decremente (int a,int n)
    {
        int pid,reason;
        int tubes[n][2];
        int resultat;
     
        int termine=0;
     
        int new_value=a;
     
        int cpt=0;
     
        int lec,ecr;
     
        for (int j=0;j<n;j++){
            if(pipe(tubes[j]) == -1)
                perror("pipe");
        }
        write(tubes[0][1],&a,sizeof(int));
        for(int i=0;i<n;i++){
            switch(pid=fork()){
            case -1:
                perror("fork");
                break;
     
            case 0:
                lec=tubes[i][0];
                ecr=tubes[(i+1)%n][1];
     
                if(read(lec,&new_value,sizeof(int)) == -1)
                    perror("read");
     
                printf("%d\n",new_value);
                close(lec);
     
                new_value--;
     
                if(new_value == 0){
                    exit(i);
                } else {
                    if(write(ecr,&new_value,sizeof(int)) == -1)
                        perror("write");
                }
                close (ecr);
                break;
     
            default:
                break;
            }
        }
        if(termine == 1){
            for(cpt=0;cpt<n;cpt++){
                if(wait(&reason)==-1)
                    perror("wait");
            } 
        }
        fprintf(stdout, "RESULTAT : %d\n",resultat);
    }
     
    int main (int argc, char**argv)
    {
        if(argc != 3)
           perror("Usage : ./exec <a> <n>");
     
        decremente(atoi(argv[1]),atoi(argv[2]));
    return 0;
    }

    Merci pour votre réponse Sve@r. Je vais suivre votre conseil et réorganiser mon programme pour qu'il soit plus aéré.
    En fait la variable a est une variable qui va se décrémenter au fur et à mesure qu'elle va passer entre les processus. Quand elle tombe à 0, le processus courant s'arrête avec un retour égal à i. Du coup je pensais faire un exit(i), mais je ne vois pas trop comment manipuler ensuite wait pour récupérer la valeur de i, pour l'affichage du résultat.

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par auloma Voir le message
    Du coup je pensais faire un exit(i), mais je ne vois pas trop comment manipuler ensuite wait pour récupérer la valeur de i, pour l'affichage du résultat.
    Ah ben faut voir la doc de wait(). On lui passe l'adresse d'un int et quand un fils fait exit(i) (i devant imérativement être compris entre 0 et 255) elle stocke ce "i" dans les 2 derniers bits de l'int.
    Et si le fils est interrompu via un kill(n), alors elle stocke ce "n" dans les 2 premiers bits de l'int.

    Donc suffit de regarder les 2 premies bits (0/pas 0) pour détecter si le fils s'est arrêté via exit/kill et selon récupérer les 2 premiers/derniers pour avoir la valeur de n ou de i.
    Et pour pas t'embêter avec les masques de bits tu as des macros WIFEXITED()/WIFSIGNALED() qui détectent exit/kill et WEXITSTATUS()/WTERMSIG() qui extraient le i ou le n selon le cas.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2020
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2020
    Messages : 63
    Par défaut
    Ouaip j'ai trouvé entre temps ! Je fais un exit(inidce) et dans le père je fais un wait(&raison) puis à resultat je donne la valeur WEXITSTATUS(raison) !
    Ca fonctionne nickel. Parcontre, algorithmiquement parlant, il semble y avoir un problème. En gros il n'y a pas d'anneau, cela se décrémente a fois puis sort de la boucle.
    Je pensais que cela venait de mon utilisation de modulo dans le fils mais en fait cela ne change pas grand chose, du coup je vois pas trop où est le soucis

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par auloma Voir le message
    Je pensais que cela venait de mon utilisation de modulo dans le fils mais en fait cela ne change pas grand chose, du coup je vois pas trop où est le soucis
    Peut-être que donner le code source nous aiderait à y voir plus clair...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

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

Discussions similaires

  1. Création d'un anneau de n processus
    Par ludocorpe dans le forum Débuter
    Réponses: 9
    Dernier message: 05/12/2016, 17h35
  2. Programmer un anneau de processus
    Par yazidbalde dans le forum Débuter
    Réponses: 1
    Dernier message: 29/06/2014, 13h12
  3. probleme avec les processus
    Par saidi dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 05/02/2003, 00h18
  4. [VB6] [Système] Tuer un processus courant
    Par mdoyer dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 22/10/2002, 14h47
  5. Réponses: 2
    Dernier message: 04/10/2002, 09h13

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