Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sde:laboratoare:04 [2019/03/12 19:37]
iuliana.marin [Liens vers des sections utiles]
— (current)
Line 1: Line 1:
-====== TP 4 - Processus ====== 
-===== Documents d'aide ===== 
-  * [[https://​www.slideshare.net/​alexandruradovici/​sde-tp-4-processus-135693677 | Diapositives]] 
-  * [[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab03-refcard.pdf | lab03-refcard.pdf]] 
-  * [[http://​elf.cs.pub.ro/​so/​res/​tutorial/​lab-03-procese/​| Processes]] 
-==== Agréable à lire ==== 
-  * TLPI - Chapitre 6, ''​ Processus '',​ Chapitre 26 ''​ Surveillance des processus enfants ''​ 
-  * WSP4 - Chapitre 6, ''​ Gestion des processus ''​ 
- 
-===== Liens vers des sections utiles ===== 
-  * [[# # Créer un processus Linux | Créer un processus]] 
-  * [[# Remplacement d'une image de processus sous Linux | Remplacement d'une image de processus]] 
-  * [[# En attente de la fin d'un processus sous Linux | En attente de la fin d'un processus] 
-  * [[#Terminer un processus sous Linux | Terminer un processus]] 
-  * [[# # Exemple (mon_système) | Exemple (mon_système)]] 
-  * [[# Descripteurs de fichiers de copie | Copie de descripteurs de fichiers]] 
-  * [[# Héritage des descripteurs de fichier après les opérations fork / exec | Héritage des descripteurs de fichier après les opérations fork / exec]] 
-  * [[# Variables d'​environnement sous Linux | Variables d'​environnement sous Linux]] 
- 
-===== Vue d'​ensemble des concepts ===== 
- 
-Un ** processus ** est un programme en cours d'​exécution. Les processus sont l'​unité primitive à travers laquelle le système d'​exploitation alloue des ressources aux utilisateurs. Chaque processus a un espace d'​adressage et un ou plusieurs threads. Plusieurs processus peuvent exécuter le même programme, mais deux processus sont complètement indépendants. 
- 
-Les informations de processus sont conservées dans une structure appelée "Bloc de contrôle de processus"​ ([[http://​en.wikipedia.org/​wiki/​Process_control_block|PCB]]),​ une pour chaque processus du système. Parmi les informations les plus importantes contenues par PCB, on trouve: 
-  * PID - identifiant du processus 
-  * Espace d'​adressage 
-  * registres généraux, ''​ PC ''​ (programme de comptage), ''​ SP ''​ (indicateur de pile) 
-  * ouvrir la table 
-  * [[so:​laboratoare-2013:​laborator-06| informations sur les signaux]] 
-    * liste des bloqués, ignorés ou en attente d'​envoi au processus 
-    * Gestionnaires de signaux 
-  * informations sur les systèmes de fichiers (répertoire racine, répertoire actuel) 
- 
- 
-Lors du lancement d'un programme, un processus sera créé dans le système d'​exploitation pour allouer les ressources nécessaires à l'​exécution du programme. Chaque système d'​exploitation fournit des appels système permettant de travailler avec des processus: création, fin, attente de fin. En même temps, il y a des appels à la duplication de descripteurs de ressources entre processus, ou à la fermeture de ces descripteurs. 
- 
-Les processus peuvent avoir une organisation:​ 
-  // hierarchical // - par exemple sous Linux - il existe une arborescence dans laquelle la racine est le processus ''​ init ''​ (pid = 1). 
-  * // non hiérarchique // - par exemple sous Windows. 
- 
-Généralement,​ un processus s'​exécute dans un environnement spécifié par un ensemble de ** variables d'​environnement **. Une variable d'​environnement est une paire 'NOM = valeur'​. Un processus peut vérifier ou définir la valeur d'une variable d'​environnement via une série d'​appels de bibliothèque ([[# variables d'​environnement dans Linux | Linux]], [[#​variables d'​environnement dans Windows | Windows]]). 
- 
-** Les canaux ** (canaux de communication) sont des mécanismes primitifs de communication entre processus. Un canal peut contenir une quantité limitée de données. L'​accès à ces données est de type FIFO (les données sont écrites à une extrémité du canal pour être lues à l'​autre extrémité). Le système d'​exploitation garantit la synchronisation entre les opérations de lecture et d'​écriture aux deux extrémités 
- ([[# tubes dans Linux | Linux]], [[# tubes dans Windows | Windows]]). 
- 
-Il existe deux types de tuyaux: 
-  * pipes **anonymous **: ne peuvent être utilisés que par des processus **associés** (un processus parent et un ou deux enfants) car ils ne sont accessibles que par héritage. Ces canaux n'​existent plus une fois que les processus ont terminé leur exécution. 
-  * **Name** pipes: ont un support physique - ils existent sous forme de fichiers de droits d'​accès. Par conséquent,​ ils existeront indépendamment du processus qui les crée et peuvent être utilisés par des processus indépendants. 
- 
-===== Processus sous Linux ===== 
- 
-Le lancement d'un programme implique les étapes suivantes: 
-  * Un nouveau processus "​fork"​ est créé - le processus enfant dispose d'une copie des ressources du processus parent. 
-  * Si vous souhaitez remplacer l'​image du processus enfant, vous pouvez la modifier en appelant une fonction de la famille ''​ exec* ''​. 
-==== Créer un processus Linux ==== 
- 
-Sous UNIX, un processus est créé à l’aide de l’appel système [[http://​linux.die.net/​man/​2/​fork|fork]]:​ 
-<code c> 
-pid_t fork(void); 
-</​code>​ 
-L'​effet crée un nouveau processus (le processus enfant), une copie du "​fork"​ (le processus parent). Le processus enfant reçoit un nouvel // identificateur de processus // (''​ PID ''​) du système d'​exploitation. 
- 
- 
-<note important>​ Cette fonction est appelée une fois et retourne (en cas de succès) deux fois: 
-   * Le parent retournera le pid du processus nouvellement créé (enfant). 
-   * Dans le processus enfant, l'​appel retournera 0. 
-</​note>​ 
-{{ so:​laboratoare:​fork.png?​300|}} 
-Pour connaître le «PID» du processus actuel et du processus parent, appelez les fonctions ci-dessous. 
- 
-La fonction [[http://​linux.die.net/​man/​3/​getpid|getpid]] renvoie le ''​ PID ''​ du processus appelant: 
-<code c> 
-pid_t getpid(void);​ 
-</​code>​ 
-La fonction [[http://​linux.die.net/​man/​3/​getppid|getppid]] renvoie le "​PID"​ du processus parent du processus appelant: 
-<code c> 
-pid_t getppid(void);​ 
-</​code>​ 
-==== Remplacement d'une image de processus sous Linux ==== 
- 
- 
-La famille de fonctions [[http://​linux.die.net/​man/​3/​exec|exec]] exécutera un nouveau programme, remplaçant l'​image du processus en cours par celle d'un fichier (exécutable). Cela signifie: 
-   * L'​espace adresse de processus sera remplacé par un nouveau créé spécifiquement pour l'​exécution de fichier. 
-   * Le '​PC'​ (le compteur de programme), le '​SP'​ (l'​indicateur de pile) et les registres généraux seront réinitialisés. 
-   * Les blocs de signaux ignorés et verrouillés sont réglés sur les valeurs par défaut, de même que les gestionnaires de signaux. 
-   * ''​ PID ''​ et les descripteurs de fichier qui n'ont pas activé l'​indicateur ''​ CLOSE_ON_EXEC ''​ restent inchangés (par défaut, ''​ CLOSE_ON_EXEC ''​ n'est pas défini). 
-<code c> 
- 
-int execl(const char *path, const char *arg, ...);  
-int execv(const char *path, char *const argv[]); 
-int execlp(const char *file, const char *arg, ...); 
- 
-</​code>​ 
- 
-Exemple d'​utilisation des fonctions ci-dessus: 
-<code c> 
-execl("/​bin/​ls",​ "​ls",​ "​-la",​ NULL); 
- 
-char *const argvec[] = {"​ls",​ "​-la",​ NULL}; 
-execv("/​bin/​ls",​ argvec); 
- 
-execlp("​ls",​ "​ls",​ "​-la",​ NULL); 
-</​code> ​ 
- 
-<note important>​ Le premier argument est le nom du programme. Le dernier argument de la liste de paramètres doit être NULL, que la liste soit sous la forme d'un vecteur (execv *) ou en tant qu'​argument variable (execl *). 
-</​note>​ 
- 
-''​ execl ''​ et ''​ execv ''​ ne recherchent pas le programme donné en tant que paramètre dans ''​ PATH '',​ il doit donc être accompagné du chemin complet. Les versions execlp et execvp recherchent le programme dans ''​ PATH ''​. 
- 
-Toutes les fonctions ''​ exec * ''​ sont implémentées par l'​appel système [[http://​linux.die.net/​man/​2/​execve|execve]]. 
-==== En attente de terminer un processus sous Linux ==== 
- 
-La famille de fonctions [[http://​linux.die.net/​man/​3/​waitpid|wait]] suspend l'​exécution du processus appelant jusqu'​à ce que le ou les processus spécifiés dans les arguments se soient terminés ou aient été arrêtés ("​SIGSTOP"​). 
-<code c> 
-pid_t waitpid(pid_t pid, int *status, int options); 
-</​code>​ 
-L’état du processus peut être trouvé en examinant ''​ status ''​ avec des macrodefines telles que [[http://​linux.die.net/​man/​3/​waitpid|WEXITSTATUS]],​ qui renvoie le code d'​erreur avec lequel le processus attendu a été achevé, en évaluant le plus insignifiant 8 bits. 
- 
-Il existe une version simplifiée qui attend la fin d’un processus enfant. Les séquences de code suivantes sont équivalentes:​ 
-<code c> 
-wait(&​status); ​                  ​| ​ waitpid(-1, &​status,​ 0); 
-</​code>​ 
- 
-Si vous souhaitez uniquement attendre la fin du processus enfant sans examiner l'​état,​ vous pouvez utiliser: 
-<code c> 
-wait(NULL); 
-</​code>​ 
- 
-==== Terminer un processus Linux ==== 
-Pour terminer le processus en cours, Linux fournit l'​appel système ''​exit''​. 
-<code c> 
-void exit(int status); 
-</​code>​ 
- 
-<spoiler Apeluri exit> 
-A partir d'un programme ''​ C '',​ il existe trois manières d'​appeler cet appel système: 
- 
-1. Appelez [[http://​linux.die.net/​man/​2/​exit|_exit]] [[[http://​linux.die.net/​man/​7/​standards|POSIX.1-2001]] ): 
-<code c> 
-void _exit(int status); 
-</​code>​ 
-2. Appelez [[http://​linux.die.net/​man/​2/​exit|_Exit]] depuis la bibliothèque standard ''​ C ''​ (selon [[http: //​en.wikipedia.org/​wiki/​C99 | C99]]): 
-<code c> 
-void _Exit(int status); 
-</​code>​ 
-3. L'​appel [[http://​linux.die.net/​man/​3/​exit|exit]] de la bibliothèque standard ''​C''​ (selon ''​C89'',​ ''​C99''​),​ celle décrite ci-dessus ci-dessus. 
- 
- 
-''​_exit (2)''​ et''​_Exit(2)''​ sont fonctionnellement équivalents (uniquement s'ils sont définis par des normes différentes):​ 
-   * le processus d'​appel se termine immédiatement 
-   * tous les descripteurs de processus de fichiers sont fermés 
-   * les enfants du procès sont "​nés"​ par "​init"​ 
-   * Un signal '​SIGCHLD'​ sera envoyé au processus parent. Il sera également rétabli à «statut» à la suite d'une fonction «wait» ou «waitpid». 
- 
-De plus, ''​exit(3)'':​ 
-   * supprimera tous les fichiers créés avec ''​tmpfile ()''​ 
-   * écrira les tampons ouverts et les fermera 
-</​spoiler>​ 
-<​note>​ Selon ''​ISO C'',​ un programme se terminant par ''​ return x ''​ dans ''​main()''​ aura le même comportement que ''​exit (x) ''​. </​note>​ 
- 
-Un processus dont le parent est terminé s'​appelle ** processus orphelin **. Ce processus est automatiquement adopté par le processus ''​ init '',​ mais il porte toujours le nom orphelin car le processus qui l'a créé à l'​origine n'​existe plus. 
- 
-Un processus terminé dont le parent n'a pas encore lu le statut de la terminaison est appelé processus **zombie **. Le processus entre dans un état final et les informations continuent d'​exister dans la table des processus afin de donner au parent la possibilité de vérifier le code avec lequel le processus s'est terminé. Lorsque le parent appelle l'​attente,​ les informations sur le processus disparaissent. Tout processus enfant passera par le statut de zombie à la fin. 
- 
-Pour terminer un autre processus dans le système, un signal sera envoyé à ce processus via l'​appel système [[http://​linux.die.net/​man/​2/​kill|kill]]. Plus de détails sur '​tuer'​ et les signaux dans [[so:​laboratoare-2013:​laborator-06 | signal lab]]. 
-==== Exemple (mon_système) ==== 
-<code c my_system.c>​ 
-#include <​stdlib.h>​ 
-#include <​stdio.h>​ 
- 
-#include <​sys/​types.h>​ 
-#include <​sys/​wait.h>​ 
-#include <​unistd.h>​ 
- 
-int my_system(const char *command) 
-{ 
- pid_t pid; 
- int status; 
- const char *argv[] = {command, NULL}; 
- 
- pid = fork(); 
- switch (pid) { 
- case -1: 
- /* error forking */ 
- return EXIT_FAILURE;​ 
- case 0: 
- /* child process */ 
- execvp(command,​ (char *const *) argv); 
- 
- /* only if exec failed */ 
- exit(EXIT_FAILURE);​ 
- default: 
- /* parent process */ 
- break; 
- } 
- 
- /* only parent process gets here */ 
- waitpid(pid,​ &​status,​ 0); 
- if (WIFEXITED(status)) 
- printf("​Child %d terminated normally, with code %d\n", 
- pid, WEXITSTATUS(status));​ 
- 
- return status; 
-} 
- 
-int main(void) { 
- my_system("​ls"​);​ 
- return 0; 
-} 
-</​code>​ 
-==== Copier les descripteurs de fichier ==== 
-[[http://​linux.die.net/​man/​2/​dup|dup]] duplique le descripteur de fichier ''​ oldfd ''​ et renvoie le nouveau descripteur de fichier, ou ''​ -1 ''​ en cas d'​erreur:​ 
-<code c> 
-int dup(int oldfd); 
-</​code>​ 
-[[http://​linux.die.net/​man/​2/​dup|dup2]] duplique le descripteur de fichier ''​ oldfd ''​ dans le descripteur de fichier '​newfd';​ si ''​ newfd ''​ existe, il sera fermé en premier. Retourne le nouveau descripteur de fichier, ou ''​ -1 ''​ en cas d'​erreur:​ 
-<code c> 
-int dup2(int oldfd, int newfd); 
-</​code>​ 
- 
-Les descripteurs de fichiers sont en réalité indexés dans la table de fichiers ouverte. La table est remplie avec les structures d'​informations de fichier. La duplication d'un descripteur de fichier signifie la duplication de l'​entrée dans la table de fichiers ouverte (c'​est-à-dire que 2 pointeurs situés à des positions différentes de la table pointeront sur la même structure de fichiers associée au fichier). Pour cette raison, toutes les informations associées à un fichier (verrou, curseur, drapeau) sont ** partagées ** par les deux descripteurs de fichier. Cela signifie que les opérations qui modifient ces informations sur l'un des descripteurs de fichier (par exemple, "​lseek"​) sont également visibles pour l'​autre fichier de descripteur (dupliqué). 
- 
-<note important>​ L'​indicateur ''​ CLOSE_ON_EXEC ''​ n'est pas partagé (cet indicateur n'est pas conservé dans la structure ci-dessus). </​note>​ 
- 
-=== Héritage des descripteurs de fichier après les opérations fork / exec === 
- 
-Les descripteurs de fichier du processus parent ** héritent ** du processus enfant après l'​appel '​fork'​. Après un appel à "​exec",​ les descripteurs de fichier sont conservés, à l'​exception de ceux pour lesquels l'​indicateur "​CLOSE_ON_EXEC " est activé. 
-<spoiler Détail du drapeau CLOSE_ON_EXEC>​ 
-**fcntl** 
-Pour définir l'​indicateur ''​ CLOSE_ON_EXEC '',​ la fonction [[http://​linux.die.net/​man/​3/​fcntl|fcntl]] est utilisée, avec un appel de formulaire: 
-<code c> 
-fcntl(file_descriptor,​ F_SETFD, FD_CLOEXEC);​ 
-</​code>​ 
- 
-**O_CLOEXEC** 
-''​ fcntl ''​ peut uniquement activer l'​indicateur ''​ FD_CLOEXEC ''​ pour les descripteurs de fichiers existants. Dans les applications multithreads,​ entre la création d'un descripteur de fichier et un appel "​fcntl",​ un appel "​exec"​ peut être placé sur un autre thread. 
-<code C> 
-/ * THREAD 1 */                   |/ * THREAD 2 */    ​ 
-fd = op_creare_fd() ​              | 
-                                  | exec(...) 
-fcntl(fd, F_SETFD, FD_CLOEXEC); ​  | 
-</​code>​ 
- 
-Comment, par défaut, les descripteurs de fichier sont hérités après un appel "​exec",​ bien que le programmeur ait voulu être incapable d'y accéder après "​exec",​ ne peut empêcher un appel "​exec"​ entre créer et fcntl. 
- 
-Pour résoudre cette situation critique, de nouvelles versions d'​appels système ont été introduites dans Linux 2.6.27 (2008): 
-<code C> 
-int dup3(int oldfd, int newfd, int flags); 
-int pipe2(int pipefd[2], int flags); 
-int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); 
-</​code>​ 
-Ces variations d'​appels système ajoutent le champ ''​ flags '',​ qui peut spécifier ''​ O_CLOEXEC ''​ pour créer et activer ''​ CLOSE_ON_EXEC ''​ en // mode atomique //. Le numéro du nom de l'​appel système spécifie le nombre de paramètres d'​appel. 
- 
-Les appels système qui créent des descripteurs de fichier ayant déjà reçu un paramètre '​flags'​ (par exemple, ''​ open ''​) ont uniquement été étendus pour accepter ''​O_CLOEXEC''​. 
-</​spoiler>​ 
-=====Variables d'​environnement sous Linux ===== 
- 
-Dans un programme, il est possible d'​accéder aux variables d'​environnement en mettant en surbrillance le troisième paramètre (facultatif) de la fonction ''​main'',​ comme dans l'​exemple suivant: 
-<code c> 
-int main(int argc, char **argv, char **environ) 
-</​code>​ 
- 
-Il désigne un vecteur de pointeurs sur des chaînes contenant les variables d'​environnement et leurs valeurs. Les caractères sont sous la forme ''​VARIABLE = VALUE''​. Le vecteur est fini avec ''​ NULL ''​. 
- 
-[[http://​linux.die.net/​man/​3/​getenv|getenv]] renvoie la valeur de la variable d'​environnement nommée ''​nom''​ ou ''​NULL''​ s'il n'y a pas de variable d'​environnement nommée: 
-<code c> 
-char* getenv(const char *name); 
-</​code>​ 
- 
-[[http://​linux.die.net/​man/​3/​setenv|setenv]] ajoute la variable nommée ''​ nom ''​ (si elle n'​existe pas déjà) et définit sa valeur sur ''​ valeur ''​. Si la variable existe et ''​ remplace ''​ e ''​ 0 '',​ l'​action de définition de la valeur de la variable est ignorée; si ''​ remplacer ''​ est différent de ''​ 0 '',​ la valeur de la variable devient ''​ valeur '':​ 
-<code c> 
-int setenv(const char *name, const char *value, int replace); 
-</​code>​ 
- 
-[[http://​linux.die.net/​man/​3/​unsetenv|unsetenv]] supprime la variable nommée ''​name''​ de l'​environnement:​ 
-<code c> 
-int unsetenv(const char *name); 
-</​code>​ 
- 
-===== Dépannage d'un processus ===== 
- 
-Des informations supplémentaires sur le dépannage d'un processus peuvent être trouvées 
-[[so:​laboratoare:​resurse:​gdb#​depanarea unui proces | ici]] 
-===== Exercices ===== 
- 
-Pour résoudre le labo, veuillez cloner [[https://​www.github.com/​upb-fils/​sde|repository]]. si vous en avez déjà un, lancez svp ''​ git pull ''​. 
- 
-<note tip> Pour vous aider à mettre en œuvre les exercices de laboratoire,​ il existe un fichier ''​ utils.h ''​ avec des fonctionnalités utiles dans le répertoire ''​ utils ''​ de l'​archive. </ note> 
- 
- 
-==== Exercice 1 - Système (1p) ==== 
- 
-Allez dans le répertoire ''​ 1-system ''​. 
-Le programme ''​ mon_système.c ''​ exécute une commande envoyée en tant que paramètre à l'aide de la fonction de bibliothèque [[http://​linux.die.net/​man/​3/​system|system]]. Le fonctionnement de [[http://​linux.die.net/​man/​3/​system|system]] est le suivant: 
-   * créer un nouveau processus avec [[http://​linux.die.net/​man/​2/​fork|fork]] 
-   * Le processus enfant s'​exécute en utilisant [[http://​linux.die.net/​man/​2/​execve | execve]], le programme ** ''​sh''​ ** avec les arguments -c ''​commande'',​ pendant que le processus parent attend la fin de l'​enfant. 
- 
-Compilez (en utilisant ''​make''​) et lancez le programme en donnant une commande en paramètre. 
-   * Exemple: <code bash> ./my_system pwd </​code>​ 
-Que faites-vous pour envoyer plus de paramètres à une commande? (par exemple: ''​ ls -la ''​) 
- 
-Pour voir combien d'​appels système [[http://​linux.die.net/​man/​2/​execve | execve]] est terminé, exécutez: 
-<code bash> strace -e execve,​clone -ff -o output ./my_system ls </​code>​ 
-    * ** Attention! ** Il n'y a pas de virgule dans l'​argument ''​ execve, clone ''​ 
-    * L'​argument ''​ -ff ''​ accompagné de ''​ -o output ''​ génère un fichier de sortie pour chaque processus. 
-       * Voir la page de manuel [[http://​linux.die.net/​man/​1/​strace|strace]] 
-Consultez la section [[# # Remplacement d’une image de processus sous Linux | Remplacement d’une image de processus sous Linux]] et du [[http://​linux.die.net/​man/​2/​execve | execve]]. 
- 
-Remplacez le ''​ système ''​ par ''​ execlp ''​. La fonction reçoit une commande, une liste d'​arguments (séparés par des virgules), puis NULL (le dernier paramètre correspond à la fin de la liste). 
- 
-Suivez la ligne avec TODO 1. 
- 
-==== Exercice 2 - Paramètres (2p) ==== 
- 
-Allez dans le répertoire ''​ 2-parameters ''​. 
- 
-Compilez le programme //​parameters.c//​ en utilisant la commande '​make'​. Que fait //​parameters.c//?​ 
- 
-Résolvez l'​exercice dans le fichier //​program.c//​. 
- 
-=== 2a. système (1p) === 
- 
-Utilisez la fonction ''​ système ''​ pour exécuter // paramètres // avec certains paramètres. 
- 
-<​note>​ Pour exécuter un programme à partir du répertoire en cours, préfixez l'​exécutable avec ./ (ex: ./​parameters) </ note> 
- 
-=== 2b. execl (1p) === 
- 
-Remplacez la fonction // system // par // execl //. Pourquoi le texte affiché par // printf // après // execl //? 
- 
-Suivez les lignes avec TODO 2. 
- 
-==== Exercice 3 - Exécuter (4p) ==== 
- 
-Allez dans le répertoire ''​ 3-run ''​. 
- 
-=== 3a - fork, exec (1p) === 
- 
-Utilisez les fonctions // fork // et // execl // pour exécuter la commande ''​ls''​ dans //run.c//. 
- 
-Suivez les lignes avec TODO 1. 
- 
-=== 3b - waitpid (1p) === 
- 
-Assurez-vous que // "ls a été exécuté"​ // apparaît après la fermeture du programme // ls //. (Indice: waitpid) 
- 
-Suivez les lignes avec TODO 2. 
- 
-=== 3c - statut de sortie (1p) === 
-Déplacez et modifiez la ligne avec TODO 3 afin que le code de sortie de // ls // soit affiché. (Indice: WEXITSTATUS) 
- 
- 
-=== 3d - waitpid (1p) === 
-Compilez le programme //​exitcode.c//​ en utilisant la commande ''​make''​. Exécutez le programme et affichez le code de sortie. Modifiez le programme //​exitcode.c//​ afin qu'il renvoie un autre code de sortie. 
- 
-Suivez les lignes avec TODO 4. 
- 
-==== Exercice 4 - orphelin (0.5p) ==== 
- 
-Allez dans le répertoire ''​ 4-orphan ''​ et inspectez la source ''​ orphan.c ''​. 
- 
-Compilez le programme (''​ make ''​) puis exécutez-le en utilisant la commande suivante: 
-<code bash> ./orphan </​code>​ 
-Ouvrez un autre terminal et lancez la commande: 
-<code bash> watch -d '(ps -al | grep -e orphan -e PID)' </​code>​ 
-Notez que pour le processus indiqué par l'​exécutable '​orphelin'​ (colonne CMD), le pid du processus parent (colonne '​PPID'​) devient 1 car le processus est adopté par ''​ init ''​ à la fin du processus. son parent. Pourquoi deux processus orphelins? 
- 
-==== Exercice 5 - zombie (0.5p) ==== 
- 
-Allez dans le répertoire ''​ 5-zombie ''​ et inspectez la source ''​ zombie.c ''​. 
- 
-Compilez le programme (''​ make ''​) puis exécutez-le en utilisant la commande suivante: 
-<code bash> ./zombie </​code>​ 
-  
-Ouvrez un autre terminal et lancez la commande: 
-<code bash> watch -d '(ps -al | grep -e orphan -e PID)' </​code>​ 
- 
-Notez que pour le processus indiqué par l'​exécutable zombie, la colonne '​CMD'​ devient '​zombie'​ '<​obsolète>​. Qu'​est-ce qui se passe vraiment? 
- 
-Modifiez le fichier //​zombie.c//​ afin que le processus ne devienne pas un zombie (indice: waitpid). 
- 
-Suivez les lignes avec TODO 1. 
- 
-==== Exercice 6 - Tiny-Shell (3p) ==== 
- 
-Allez dans le répertoire ''​ 3-minuscule ''​. 
- 
-Les sous-programmes suivants sont destinés à implémenter un shell minimal prenant en charge l'​exécution d'une commande // single // external avec plusieurs arguments et redirections. Shell doit fournir un soutien pour l'​utilisation et la définition de variables environnementales. 
- 
-// Note: // Pour quitter le petit shell, utilisez ''​ exit ''​ ou ''​ CTRL + D ''​. 
- 
-=== 6a. Exécution d'une commande simple (1p) === 
- 
-Créez un nouveau processus pour exécuter une commande simple. 
- 
-La fonction ''​ simple_cmd ''​ reçoit en argument un vecteur chaîne contenant la commande et ses paramètres. 
- 
-Voir l'​exemple [[#example (my_system) | mon_système]] et suivez les commentaires avec ''​ TODO 1 ''​ dans le code. 
-Pour tester, vous pouvez utiliser les commandes: <code bash> ./tiny 
-> pwd 
-> ls -al 
-> exit </​code>​ 
-=== 6b. Ajout du support pour la définition et le développement de variables d’environnement (1p) === 
- 
-Vous devez remplir les fonctions '​set_var'​ et '​expand';​ ils sont déjà appelés lorsque la ligne de commande est analysée. Les erreurs doivent être vérifiées dans ces fonctions. 
- 
-                  * Suivre les commentaires avec ''​ TODO 2 ''​ dans le code. 
-                  * Lisez la variable d'​environnement [[#​variabile de mediu in linux | Variables d'​environnement Linux]]. 
-              * Pour tester, vous pouvez utiliser les commandes suivantes: <code bash> ./tiny 
-> echo $HOME 
-> name=Makefile ​ 
-> echo $name  </​code>​ 
-=== 6c. Rediriger la sortie standard (1p) === 
- 
-Remplissez le champ ''​ do_redirect ''​ pour que tiny-shell prenne en charge la redirection de la sortie d'une commande (stdout) dans un fichier. 
- 
-Si le fichier spécifié par ''​ nomfichier ''​ n'​existe pas, il sera créé. S'il existe, il doit être tronqué. 
- 
-Lisez la section [[# Descripteurs de fichiers de copie | Copie de descripteurs de fichiers]] et suivez les commentaires avec le mot "TODO 3" dans le code. 
-Pour tester, vous pouvez utiliser les commandes: 
-<code bash> ./​tiny ​ 
-> ls -al > out 
-> cat out 
-> pwd > out 
-> cat out 
-</​code>​ 
- 
-<​hidden>​ 
-===== Soluții ===== 
- 
-[[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab03-sol.zip | lab03-sol.zip]] 
-</​hidden>​ 
-===== Ressources utiles ===== 
-  - [[http://​en.wikipedia.org/​wiki/​Fork_(operating_system)|Fork - Wikipedia]] 
-  - [[http://​www-h.eng.cam.ac.uk/​help/​tpl/​unix/​fork.html|About Fork and Exec]] 
-  - [[http://​www.yolinux.com/​TUTORIALS/​ForkExecProcesses.html|Fork,​ Exec and Process Control - YoLinux Tutorial]] 
- 
  
sde/laboratoare/04.1552412252.txt.gz · Last modified: 2019/03/12 19:37 by iuliana.marin
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0