mbarekh | 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 :
- /*
- * Copyright (C) 2002, Simon Nieuviarts
- */
- #include <signal.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <stdio.h>
- #include "readcmd.h"
- #define N 100
- int main(){
- int desc_sor,desc_ent;//c'est un descripteur du fichier vers lequel on redirige la sortie(ou l'entrée respectivement)
- int tuyau[2],length;
- pid_t tab_pid[N];//un tableau qui contiendra les pid des processus lancés en background
- char* tab_com[N];//un tableau qui contiendra les nom des processus lancés en background
- int comp = 0; //un compteur commun pour les deux tableaux précédants
- pid_t res,pid;
- int* status;
- int arg=0; //c'est pour parcourir les arguments d'une commande
- void afficher_terminaison() //pour le SIGCHILD
- {
- printf("le processus lancé en background est s'est terminé \n" );
- }
- while (1) {
- struct cmdline *l;
- int i, j;
- printf("shell> " );
- l = readcmd();
- /* If input stream closed, normal termination */
- /*if (!l) {
- printf("exit\n" );
- exit(0);
- }*/
- if (l->err) {
- /* Syntax error, read another command */
- printf("error: \a %s\n", l->err);
- continue;
- }
- if (l->in){
- printf("in: %s\n", l->in);
- desc_ent = open(l->in,O_RDONLY);
- }
- if (l->out){
- printf("out: %s\n", l->out);
- desc_sor = open(l->out,O_WRONLY|O_CREAT);
- }
- /* Display each command of the pipe */
- for (i=0; l->seq[i]!=0; i++) {
- char **cmd = l->seq[i];
- printf("seq[%d]: ", i);
- for (j=0; cmd[j]!=0; j++) {
- printf("%s ", cmd[j]);
- }
- printf("\n" );
- }
-
- if (strcmp(l->seq[0][0] , "exit" ) == 0)
- {exit(0);}
-
- /*creation d'un pipe au cas ou on a 2 commandes separées par un pipe*/
- if (l->seq[1] != 0)
- {
- pid = fork();
- if (pid > 0) waitpid(pid,NULL,WUNTRACED);
- if (pid == 0 ) //"pid" est le pid du processus à gauche du pipe
- {
- if(pipe(tuyau)==-1) {
- printf("erreur a la creation du pipe\n" );
- exit(2);
- }
- res = fork();
- if(res == 0) { //"res" est le pid du processus à droite du pipe
- /* je suis le processu à doite */
- close(tuyau[1]);
- close(0);
- dup(tuyau[0]);
- printf("ici2" );
- execvp(l->seq[1][0],l-> seq[1]);
- printf("probleme dans le processus droit\n" );
- exit(1);
- }
-
- if(res==-1) {
- printf("erreur a la creation du processus droit\n" );
- exit(2);
- }
- //processus gauche
- close(tuyau[0]);
- close(1);
- dup(tuyau[1]);
- printf("ici1" );
- execvp(l->seq[0][0],l-> seq[0]);
- printf("probleme dans le processus gauche\n" );
- exit(1);
- }
- }
- else
- {
- /*seq[i] est la ième commande dans la suite des commandes séparés par des pipes,
- et seq[i][0] nous donne le nom du processus correspondant à cette commande*/
- if (l->seq[0] != 0) {
- pid = fork();
- if ((pid == 0) && (l->out != NULL))
- {
- close(1);
- dup2(desc_sor,1);
- };
- if ((pid == 0) && (l->in != NULL))
- {
- close(0);
- dup2(desc_ent,0);
- };
- if (pid != 0) // Le père
- {
- if (strcmp(l->seq[0][0] , "liste_ps" ) == 0)
- {
- printf("\n" );
- printf("pid " );
- printf("commande" );
- printf("\n" );
- for (i = 0;i<comp; i++)
- { printf("%d ",tab_pid[i]);
- printf("%s ",tab_com[i]);
- printf("\n" );
- }
- printf("\n" );
- }
-
- }
- arg = 0; //réinitialisation de arg
- while ( l->seq[0][arg] != 0) { arg++;};//(arg -1) est le nombre d'arguments de la commande (avec le nom de la commande compris)
- if (strcmp(l->seq[0][arg -1] , "&" ) != 0)
- {
- /*on n'attend le fils que si le processus correspondant n'est
- pas lancé en background*/
- waitpid(pid,status,WUNTRACED);
- if (pid == 0)
- {
- execvp(l->seq[0][0],l-> seq[0]);
- if (strcmp(l->seq[0][0] , "liste_ps" ) != 0)
- {//liste_ps est une commande que nous avons fabriqueé, donc il ne faut pas la considérer comme incorrecte
- printf("commande incorrecte \a \n" );
- }
- exit(1);
- }
- }
- else
- {
- signal(SIGCHLD,afficher_terminaison);
- waitpid(pid,status,WNOHANG);
- l-> seq[0][arg - 1] = NULL;
- tab_pid[comp] = pid;
- length = strlen(l->seq[0][0]) + 1;
- tab_com[comp] = malloc(length);
- strcpy(tab_com[comp],l->seq[0][0]);
- comp++;
- if (pid == 0)
- {
- execvp(l->seq[0][0],l-> seq[0]);
- printf("commande incorrecte \a \n" );
- exit(1);
- }
- }
- }
- }
- }
- }
|
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
|