Problème rapidité de mise en pause

Problème rapidité de mise en pause - C - Programmation

Marsh Posté le 04-11-2009 à 23:08:57    

Bonjour,
 
Je suis en train de faire un petit shell. J'utilise pour cela un fork et la fonction execvp pour exécuter le programme. Lorsque mon programme est en cours d'exécution, mon shell est bloqué en attente du signal SIGCHLD (envoyé par son enfant). Je gère cette arrivée de signal à l'aide d'un traitant qui fait un loop grâce à des wait non bloquants (utile dans le cas où on a un pipe et plusieurs applis qui terminent en même temps et donc la possibilité de recevoir un seul SIGCHLD pour plusieurs morts).
 
Voici mon problème:
Je me mets en pause pour attendre le signal SIGCHLD qui va débloquer mon shell (le père). Le problème est que sur des pc modernes, la mise en pause, est plus longue que l'execution de certains programmes (genre ls) et donc le shell reçoit le signal SIGCHLD avant sa mise en pause. Il traite ce signal (donc le fils ne devient pas un zombie) mais malheureusement, le shell attend indéfiniment un signal permettant de le sortie du mode pause.
 
Est-ce qu'il y a moyen de résoudre ce problème ? La seule technique que j'ai trouvée est de faire un sleep avant le lancement de mon programme (donc vraiment pas une solution  :pt1cable: ).
 
Voici le code du traitant du signal SIGCHILD.
 

Code :
  1. void traitement_signaux_fin(int sig_id){
  2. 39         /* apparemment, si deux signaux SIGCHLD
  3. 40          * arrivent prèsque simultanément, le
  4. 41          * système en enverra qu'un au shell
  5. 42          * il faut donc libérer tous les
  6. 43          * programmes zombies avec un
  7. 44          * wait non bloquant
  8. 45          */
  9. 46         sig_id = 1;
  10. 47         while (waitpid (-1, NULL, WNOHANG) != -1);
  11. 48
  12. 49
  13. 50 }


Voici le code de la partie fork() + attente: (il y a aussi une gestion de la redirection dans le cas d'un pipe)
 

Code :
  1. 83                 id_fils = fork();
  2. 84
  3. 85                 /* si on est dans le père */
  4. 86                 if(id_fils){
  5. 87
  6. 88                         pause();
  7. 95
  8. 98                 }else{
  9. 108                         if(gestion_redirection(num_cmd,-1,desc_pipe_lecture)){
  10. 109                                 execvp((cmd->seq[num_cmd])[0],cmd->seq[num_cmd]);
  11. 110                                 perror("Erreur lors du lancement du programme" );
  12. 111                         }
  13. 123                 }

Reply

Marsh Posté le 04-11-2009 à 23:08:57   

Reply

Marsh Posté le 05-11-2009 à 09:57:25    

Au lieu de fork(), il existe vfork() qui peut être intéressant dans ce cas, car le processus père reste suspendu et il n'y pas besoin de faire une boucle d'attente de la fin du processus fils.
 
Edit: Oups, je vois que vfork() est deprecated (obsolète), mais que l'on peut utiliser posix_spawn() à la place.


Message édité par olivthill le 05-11-2009 à 10:01:47
Reply

Marsh Posté le 14-11-2009 à 09:54:44    

ok merci,
 
effectivement, vfork() ou posix_spawn() mettent le processus père en pause mais sont quand même assez limité et ne font pas le même travail que fork().
 
de toute manière, je n'ai pas résolu ce problème et je pense que si on veut vraiment un appel bloquant efficace, on doit utiliser wait() et non pas pause().

Reply

Sujets relatifs:

Leave a Replay

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