Proposez des structures de données pour représenter toutes ces informations. De plus, proposez un ensemble de fonctions permettant de manipuler ces structures.
Il est nécessaire de rediriger les signaux SIGINT, SIGTSTP et SIGCHLD envoyés au mini-shell par le système. Un signal SIGINT est envoyé à chaque fois que l’utilisateur fait un control-C au clavier. Un signal SIGTSTP est envoyé lors d’un control-Z. Enfin le signal SIGCHLD est envoyé à chaque fois que l’exécution d’un programme lancé dans le mini-shell a terminé ou a été bloquée.
Ce traitant redirige le signal vers le processus qui est en avant-plan afin de provoquer sa terminaison.void sigint_handler(int sig);
Ce traitant redirige le signal vers le processus qui est en avant-plan afin de le suspendre.void sigstp_handler(int sig);
Ce traitant recherche tous les jobs terminés ou stoppés. Il détermine si le job a été stoppé, terminé par un signal ou a terminé normalement son exécution. Selon les cas, les structures de données sont mises à jour de façon appropriée et un message est affiché sur la sortie standard pour renseigner sur l’état du job.void sigchld_handler(int sig);
qui permet d’associer un traitant à un signal donné.typedef void handler_t(int); int signal_wrapper(int signum, handler_t *handler);
Organisation du code du gestionnaire de travaux
Les fichiers sources d’un squelette de l’implantation d’un gestionnaire de travaux sont disponibles dans cette archive. Vous y trouverez :
- un Makefile ;
- mshell.c : contient entre autre le main() ;
- cmd.c, cmd.h : contient les commandes fg, bg, stop...
- jobs.c, jobs.h : contient la librairie gérant les structures de données associées aux jobs ;
- sighandlers.c, sighandlers.h : contient les traitants de signaux ;
- common.c, common.h : contient des données et fonctions communs aux différents fichiers.
A priori, vous n’avez à modifier que les fichiers cmd.c et sighandlers.c. Les squelettes des fonctions à implémenter sont déjà donnés ; aucune autre fonction n’est nécessaire.
Le mini-shell peut fonctionner en mode verbose (mshell -v) ce qui permet d’avoir des informations sur les handlers, fonctions sollicités, etc. Une variable globale verbose est prévue à cet effet. Pensez à l’utiliser ! Le fichier jobs.c contient un exemple de son utilisation, à vous de voir selon les situations quelles informations afficher.Commandes du mini-shell
Le mini-shell offre un certain nombre de commandes :
- exit permet de quitter le mini-shell
- stop permet d’arrêter un job
- kill permet de provoquer la terminaison d’un job
- bg envoie un job en arrière-plan
- fg met un job en avant-plan
- jobs donne des informations sur les jobs courants
Exercice 7 La commande fg est invoquée soit par fg pid ou fg jidLe prototype de la fonction implémentant la commande fg est le suivant :
void do_fg(char **argv);argv contient la chaîne de caractères correspondant à la commande tapée dans le mini-shell, comme par exemple "fg %1". Une fonction treat_argv() est mise à votre disposition pour chercher un job dans la liste des travaux en fonction d’un pid ou d’un jid. Son prototype est :
struct job_t * treat_argv(char **argv);La valeur NULL est retournée si aucun job n’a été trouvé.
Lorsqu’un job est exécuté en avant-plan, l’utilisateur n’a pas la main. Pour pouvoir implémenter ce comportement, écrivez une fonction
void waitfg(pid_t pid)qui bloque tant le job pid n’est pas mis en arrière-plan.
La fonction do_fg() envoie le signal approprié au job qui doit être passé en avant-plan, met à jour les informations associées au job et bloque tant que le job n’est pas passé en arrière-plan. Donnez son implémentation.
Les commandes bg, stop et kill sont invoquées sur le même modèle que fg et sont respectivement implémentées par :
void do_bg(char **argv); void do_stop(char **argv); void do_kill(char **argv);Donnez leurs implémentations.
Exercice 8 La commande exit permet de sortir du mini-shell. Le prototype de la fonction qui implémente exit est le suivant :Inspirez-vous du comportement du shell que vous utilisez habituellement (cette remarque est d’ailleurs aussi valable pour toutes les autres commandes). Par exemple, que se passe-t-il lorsque vous faites un exit dans un shell alors qu’un job de ce shell est arrêté ?void do_exit();
Exercice 9 La commande jobs affiche l’état de tous les jobs lancés dans le mini-shell, voyez l’exemple donné en début de document.La fonction qui implémente cette commande a pour prototype :
void do_jobs();Implémentez cette fonction.
![]()
![]()
![]()