Les mécanismes d'exécution / processus, ordonnancement
Scripts
Section titled “Scripts”Scripts code
Section titled “Scripts code”ExempleFork.c
Section titled “ExempleFork.c”/* ---------------------------------------------------------------------------* Schéma de création de processus.* Création d'un processus fils et test pour exécuter un code différent* dans le père et dans le fils.*/#include <stdio.h> /* Pour perror */#include <stdlib.h> /* Pour exit */#include <unistd.h> /* Pour fork, getpid, getppid, sleep */#include <sys/types.h> /* Pour pid_t (fork, getpid, getppid) */#include <sys/wait.h> /* Pour wait */
int main(void) { pid_t ident; ident = fork(); if (ident == -1) { // pb système perror("fork"); return EXIT_FAILURE;
} /* A partir de cette ligne, il y deux processus */ printf("Cette ligne sera affichée deux fois\n"); if (ident > 0) { /* Code exécuté uniquement par le pere */ // sleep(2); /* le pere dort pendant 2 secondes */ printf("Je suis le père avant wait\n");
int status; // dans la variable status seront stockés: // le type de fin (normal ou anormal), la raison de fin, le code de retour // https://www.geeksforgeeks.org/wait-system-call-c/ wait(&status); // WEXITSTATUS permet d'extraire le code de retour printf("Je suis le père après wait, le code de retour de mon fils est %d \n",WEXITSTATUS(status)); } else {
/* Code exécuté uniquement par le fils */ //sleep(5); /* le fils dort pendant 5 secondes */ printf("Je suis le fils\n");
// soit on remplace le contenu de l'image mémoire par le programme ci dessous //execlp("/bin/ls","ls","-al",NULL);
// soit on affiche le message suivant et on retourne un code de retour arbitraire (ici 23) printf("Je suis le fils juste avant de mourir\n"); exit(23); } return EXIT_SUCCESS;}Minishell.c
Section titled “Minishell.c”#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/wait.h>
/* * Code issu mais adapté du tuto : https://segfault42.github.io/posts/minishell/ */
/* Fonction qui découpe la chaine raw_cmd en un tableau de sous chaines : programme + agruments *//* Vous n'avez pas besoin de comprendre cette fcontion */static char **split(char *raw_cmd, char *limit){ char *ptr = NULL; char **cmd = NULL; size_t idx = 0; // size_t = entioer non signé (d'au moins 16 bits)
// split sur les espaces ptr = strtok(raw_cmd, limit); // ca tokenise (sépare) la chaine en sous chaines séparée par un des caractères de limit
while (ptr) { cmd = (char **)realloc(cmd, ((idx + 1) * sizeof(char *))); // grosso modo, ca essaye d'ajouter une case au tableau char*[] cmd cmd[idx] = strdup(ptr); // on stocke dans la case idx du tableau cmd, le pointeur vers une copie de la chaine ptr = strtok(NULL, limit); // on passe au token suivant ++idx; } // On alloue un element qu'on met a NULL a la fin du tableau cmd = (char **)realloc(cmd, ((idx + 1) * sizeof(char *))); cmd[idx] = NULL; return (cmd);}
/* Fonction pour libérer la mémoire occupée par un tableau de chaines */static void free_array(char **array){ for (int i = 0; array[i]; i++) { free(array[i]); array[i] = NULL; } free(array); array = NULL;}
/* Fonction qui execute la commande contenue dans cmd[0] avec éventuellement les arguments cmd[1], ... cmd[n]. * La commande est exécutée dans un nouveau processus (créé via fork). La commande est chargée via execve. * Le processus père attend la fin de l'exécution de la commande avant de redonner la main */static void exec_cmd(char **cmd){ pid_t pid = 0; int status = 0;
// On fork pid = fork(); if (pid == -1) perror("fork"); // Si le fork a reussit, le processus pere attend l'enfant (process fork) else if (pid > 0) { // On block le processus parent jusqu'a ce que l'enfant termine puis // on kill le processus enfant waitpid(pid, &status, 0); kill(pid, SIGTERM); } else { // Le processus enfant execute la commande ou exit si execve echoue if (execve(cmd[0], cmd, NULL) == -1) perror("shell"); exit(EXIT_FAILURE); }}
/* Programme principal du shell avec la boucle*/int main(){ char buffer[2048]; char **cmd = NULL;
// ecriture d'un prompt sur la sortie standard i.e. 1 write(1, "$> ", 3);
// lecture de STDIN en boucle // si on lit quit (+ retour à la ligne) , on sort while ( strcmp(fgets(buffer, sizeof(buffer)-1, stdin) ,"quit\n") != 0 ) { /*printf("cmd = %s\n", buffer); write(1, "$> ", 3);*/
cmd = split(buffer, " \n\t");
// Execute la commande en faisant un fork (voir ci-dessus la fonction exec_cmd(...) */ if (cmd[0] != NULL) exec_cmd(cmd);
// ecriture d'un prompt sur la sortie standard i.e. 1 write(1, "$> ", 3); free_array(cmd);
}
printf("Bye \n");}