problème de fils

problème de fils - C - Programmation

Marsh Posté le 08-04-2006 à 19:22:48    

Bonjour;
je suis en tarin de réaliser un programme C qui simule un shell. J'ai commancé par creer une procédure "readcmd"
qui lits de l'entrée stnadard une commande tapé par l'utilisateur et la stocke dans une "struct cmdline *l;
Bon mon programme réalise déjà pas mal de chose.
Ce que je voudrais faire maintenant, c'est de lui donner la possibilité d'afficher à l'ecran la terminaiseon d'un processus lancé en tache de fond.
C'est à dire, grace à la fonction "signal", je demande à mon programme d'afficher une phrase qui indique explicitement la terminaison d'un processus fils:  
signal(SIGCHLD,afficher_terminaison);
 
 
 
voila mon programme pour que les choses soient claires:
 

Code :
  1. /*
  2. * Copyright (C) 2002, Simon Nieuviarts
  3. */
  4. #include <signal.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <sys/wait.h>
  11. #include <unistd.h>
  12. #include <stdio.h>
  13. #include "readcmd.h"
  14. #define N 100
  15. int main(){
  16. int desc_sor,desc_ent;//c'est un descripteur du fichier vers lequel on redirige la sortie(ou l'entrée respectivement)
  17. int tuyau[2],length;
  18. pid_t tab_pid[N];//un tableau qui contiendra les pid des processus lancés en background
  19. char* tab_com[N];//un tableau qui contiendra les nom des processus lancés en background
  20. int comp = 0; //un compteur commun pour les deux tableaux précédants
  21. pid_t res,pid;
  22. int* status;
  23. int arg=0; //c'est pour parcourir les arguments d'une commande
  24. void afficher_terminaison() //pour le SIGCHILD
  25. {
  26.      printf("le processus lancé en background est s'est terminé \n" );
  27. }
  28. while (1) {
  29.         struct cmdline *l;
  30.  int i, j;
  31.  printf("shell> " );
  32.  l = readcmd();
  33.  /* If input stream closed, normal termination */
  34.  /*if (!l) {
  35.             printf("exit\n" );
  36.   exit(0);
  37.  }*/
  38.  if (l->err) {
  39.   /* Syntax error, read another command */
  40.   printf("error: \a %s\n", l->err);
  41.   continue;
  42.  }
  43.  if (l->in){
  44.                    printf("in: %s\n", l->in);
  45.                    desc_ent = open(l->in,O_RDONLY);
  46.  }
  47.         if (l->out){
  48.                    printf("out: %s\n", l->out);
  49.                    desc_sor = open(l->out,O_WRONLY|O_CREAT);
  50.         } 
  51.  /* Display each command of the pipe */
  52.  for (i=0; l->seq[i]!=0; i++) {
  53.   char **cmd = l->seq[i];
  54.   printf("seq[%d]: ", i);
  55.   for (j=0; cmd[j]!=0; j++) {
  56.    printf("%s ", cmd[j]);
  57.   }
  58.   printf("\n" );
  59.  }
  60.                
  61.                 if (strcmp(l->seq[0][0] , "exit" ) == 0)
  62.                         {exit(0);}
  63.      
  64.        /*creation d'un pipe au cas ou on a 2 commandes separées par un pipe*/
  65.        if (l->seq[1] != 0)
  66.        {
  67.             pid = fork();
  68.             if (pid > 0) waitpid(pid,NULL,WUNTRACED);
  69.             if (pid == 0 ) //"pid" est le pid du processus à gauche du pipe         
  70.             {
  71.                if(pipe(tuyau)==-1) {
  72.                      printf("erreur a la creation du pipe\n" );
  73.                      exit(2);
  74.                }
  75.                res = fork();
  76.                if(res == 0) { //"res" est le pid du processus à droite du pipe
  77.                     /* je suis le processu à doite */
  78.                     close(tuyau[1]);
  79.                     close(0);
  80.                     dup(tuyau[0]);
  81.                     printf("ici2" );
  82.                     execvp(l->seq[1][0],l-> seq[1]);
  83.                     printf("probleme dans le processus droit\n" );
  84.                     exit(1);
  85.                }
  86.                
  87.                if(res==-1) {
  88.                     printf("erreur a la creation du processus droit\n" );
  89.                     exit(2);
  90.                }
  91.                //processus gauche
  92.                close(tuyau[0]);
  93.                close(1);
  94.                dup(tuyau[1]);
  95.                printf("ici1" );
  96.                execvp(l->seq[0][0],l-> seq[0]);
  97.                printf("probleme dans le processus gauche\n" );
  98.                exit(1);
  99.             }
  100.        }
  101.        else
  102.        { 
  103. /*seq[i] est la ième commande dans la suite des commandes séparés par des pipes,
  104. et seq[i][0] nous donne le nom du processus correspondant à cette commande*/               
  105.                   if (l->seq[0] != 0) {
  106.                   pid = fork();
  107.                   if ((pid == 0) && (l->out != NULL))
  108.                   {
  109.                      close(1);
  110.                      dup2(desc_sor,1);
  111.                   };
  112.                   if ((pid == 0) && (l->in != NULL))
  113.                   {
  114.                      close(0);
  115.                      dup2(desc_ent,0);
  116.                   };
  117.                   if (pid != 0) // Le père
  118.                   {
  119.                       if (strcmp(l->seq[0][0] , "liste_ps" ) == 0)
  120.                       {
  121.                            printf("\n" );
  122.                            printf("pid      " );
  123.                            printf("commande" );
  124.                            printf("\n" );
  125.                            for (i = 0;i<comp; i++)
  126.                            {  printf("%d      ",tab_pid[i]);
  127.                               printf("%s      ",tab_com[i]);
  128.                               printf("\n" );
  129.                            }
  130.                            printf("\n" );
  131.                        }
  132.                        
  133.                   }
  134.                 arg = 0; //réinitialisation de arg     
  135.                 while ( l->seq[0][arg] != 0) { arg++;};//(arg -1) est le nombre d'arguments de la commande (avec le nom de la commande compris)
  136.                 if (strcmp(l->seq[0][arg -1] , "&" ) != 0)
  137.                 {
  138.                   /*on n'attend le fils que si le  processus correspondant n'est
  139.                   pas lancé en background*/
  140.                   waitpid(pid,status,WUNTRACED);
  141.                   if (pid == 0)
  142.                   {
  143.                      execvp(l->seq[0][0],l-> seq[0]);
  144.                      if (strcmp(l->seq[0][0] , "liste_ps" ) != 0)
  145.                      {//liste_ps est une commande que nous avons fabriqueé, donc il ne faut pas la considérer comme incorrecte
  146.                         printf("commande incorrecte \a \n" );
  147.                      } 
  148.                      exit(1);
  149.                   }
  150.                 }
  151.                 else
  152.                 {
  153.                   signal(SIGCHLD,afficher_terminaison);
  154.                   waitpid(pid,status,WNOHANG);
  155.                   l-> seq[0][arg - 1] = NULL; 
  156.                   tab_pid[comp] = pid;
  157.                   length = strlen(l->seq[0][0]) + 1;
  158.                   tab_com[comp] = malloc(length);
  159.                   strcpy(tab_com[comp],l->seq[0][0]);
  160.                   comp++;
  161.                   if (pid == 0)
  162.                   { 
  163.                      execvp(l->seq[0][0],l-> seq[0]);
  164.                      printf("commande incorrecte \a \n" );
  165.                      exit(1);
  166.                   }
  167.                 }
  168.                }
  169. }
  170. }
  171. }


 
 
 
Le problème est que lorsque j'exécute mon programme, la terminaison du premier processus fils se passe bien, mais à partir de la 2ème, il affiche la terminaison avant la fin réelle du processus fils.voila une trace de mon exécution:
 
ensibm:~/SEPC/little_shell>tst
shell> nedit &
seq[0]: nedit &  
shell> le processus lancé en background est s'est terminé  
shell> nedit  &
seq[0]: nedit &  
le processus lancé en background est s'est terminé  
shell>
 
ou bien essayez de l'exécuter vous meme pour mieux voir.
quelqu'un a une explication?
merci d'avance
 
 

Reply

Marsh Posté le 08-04-2006 à 19:22:48   

Reply

Marsh Posté le 08-04-2006 à 19:28:37    

je viens de remarquer qu'il y a beaucoup de fautes d'orthographe dans mon sujet. la honte !
désolé tout le monde...

Reply

Marsh Posté le 08-04-2006 à 23:48:40    

Il me semble que tu envoye le signal avant d'attendre la fin du processus:

Code :
  1. signal(SIGCHLD,afficher_terminaison);
  2.                  waitpid(pid,status,WNOHANG);


en plus tu ne vérifie pas que waitpid retourne un pid valide.

Reply

Marsh Posté le 09-04-2006 à 00:50:07    

nargy a écrit :

Il me semble que tu envoye le signal avant d'attendre la fin du processus:

Code :
  1. signal(SIGCHLD,afficher_terminaison);
  2.                  waitpid(pid,status,WNOHANG);


en plus tu ne vérifie pas que waitpid retourne un pid valide.


 
 
 
 
mais je n'envoie aucun signal.je dis juste à mon programme qu'il doit effectuer la fonction "afficher_terminaison" quand il reçoit la signal sigchild.
est ce que ça s'exécute correctement chez toi?

Reply

Marsh Posté le 09-04-2006 à 00:58:23    

ha ouais, nawak, pour la peine je sort mon compilo, et....
ça compile pas, entre autre il manque le fichier readcmd.h


Message édité par nargy le 09-04-2006 à 00:58:43
Reply

Marsh Posté le 09-04-2006 à 01:01:40    

il y a aussi la définition de la fonction afficher_terminaison() dans le main() !

Reply

Marsh Posté le 09-04-2006 à 02:25:06    

#
/*
#
* Copyright (C) 2002, Simon Nieuviarts
#
*/
 
 
...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed