commit 723cc358a4f1c84cc809fd077e6d80f6b1fd9b4e Author: Laureηt Date: Tue Jun 20 20:57:09 2023 +0200 init diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8f28a2c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gcc - Build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}/${fileBasenameNoExtension}", + "args": [ "laurent" ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + // { + // "description": "Enable fork following", + // "text": "-gdb-set follow-fork-mode child" + // } + ], + "preLaunchTask": "C/C++: gcc build active file", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..4956c3e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/TP1/TPprocessus.pdf b/TP1/TPprocessus.pdf new file mode 100644 index 0000000..643a910 Binary files /dev/null and b/TP1/TPprocessus.pdf differ diff --git a/TP1/api_systeme/dormir.c b/TP1/api_systeme/dormir.c new file mode 100644 index 0000000..d643afd --- /dev/null +++ b/TP1/api_systeme/dormir.c @@ -0,0 +1,17 @@ +#include +#include +#include + +// dormir durant n secondes : n fournie en argument +// sinon n=5 par défault +int main(int argc, char* argv[]) +{ + int delai = 5; + if (argc > 1 ) { + delai = atoi(argv[1]); + } + printf("\n - Processus %d va dormir durant %d secondes\n", getpid(), delai); + sleep(delai); + fflush(stdout); + return 0; +} diff --git a/TP1/api_systeme/fic_centaines.txt b/TP1/api_systeme/fic_centaines.txt new file mode 100644 index 0000000..a89c82a --- /dev/null +++ b/TP1/api_systeme/fic_centaines.txt @@ -0,0 +1,11 @@ +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 diff --git a/TP1/api_systeme/pere_fils.c b/TP1/api_systeme/pere_fils.c new file mode 100644 index 0000000..4b513b9 --- /dev/null +++ b/TP1/api_systeme/pere_fils.c @@ -0,0 +1,50 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Création de fils : fork et exit */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* manipulation des chaines */ + +#define NB_FILS 3 /* nombre de fils */ + +int main(int argc, char *argv[]) +{ + int fils, retour; + int duree_sommeil = 3; + char progname[]="pere_fils.c"; + + if (argc > 1) { + write(atoi(argv[1]), progname, strlen(progname)); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil + 1); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_exec.c b/TP1/api_systeme/pere_fils_exec.c new file mode 100644 index 0000000..e7e3edc --- /dev/null +++ b/TP1/api_systeme/pere_fils_exec.c @@ -0,0 +1,74 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* execl */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, wstatus, fils_termine; + + char ref_exec[]="./dormir"; /* exécutable */ + char arg0_exec[]="dodo"; /* argument0 du exec : nom donnée au processus */ + char arg1_exec[]="10"; /* argument0 du exec : durée de sommeil */ + + printf("Je suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + + /* mettre un executable inexistant pour le fils 2 */ + if (fils == 2) { + ref_exec[3] = 'a'; + } + + execl(ref_exec, arg0_exec, arg1_exec, NULL); + + /* on ne se retrouve ici que si exec échoue */ + printf("\n Processus fils numero %d : ERREUR EXEC\n", fils); + /* perror : affiche un message relatif à l'erreur du dernier appel systàme */ + perror(" exec "); + exit(fils); /* sortie avec le numéro di fils qui a échoué */ + } + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + fflush(stdout); + } + } + sleep(3); /* pour les besoins de l'outil de validation automatique */ + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_fflush.c b/TP1/api_systeme/pere_fils_fflush.c new file mode 100644 index 0000000..6dabc85 --- /dev/null +++ b/TP1/api_systeme/pere_fils_fflush.c @@ -0,0 +1,55 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Redirection et fflush */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + /* D'après le standard ISO le comportement du printf présente 2 cas : */ + /* - sortie interactive (terminal) : flot géré par ligne et \n provoque */ + /* la vidange du tampon langage */ + /* - sortie dans un fichier : flot géré par bloc et \n est traité comme */ + /* un caractère ordinaire. fflush(stdout) force la vidange du tampon. */ + + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + /* vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_heritage.c b/TP1/api_systeme/pere_fils_heritage.c new file mode 100644 index 0000000..ac622fe --- /dev/null +++ b/TP1/api_systeme/pere_fils_heritage.c @@ -0,0 +1,51 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Héritage et dupplication des données */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 4 /* nombre de fils */ + +int main() +{ + int fils, retour; + int cagnotte, patrimoine_fils; + int duree_sommeil = 4; + cagnotte = 10000 * NB_FILS; + patrimoine_fils = cagnotte / NB_FILS; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + printf("Je dispose de %d Euros, que je partage entre mes futurs fils\n", cagnotte); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d : mon pere m'a offert %d Euros\n", + fils, patrimoine_fils); + patrimoine_fils = patrimoine_fils * (fils + 1); + sleep(duree_sommeil); + printf("\n Processus fils numero %d - j'ai augmente mon patrimoine a %d Euros\n", + fils, patrimoine_fils); + exit(EXIT_SUCCESS); /* Te:rminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil+1); + + printf("\nProcessus Principal - le patrimoine total de mes fils est de %d\n", patrimoine_fils*NB_FILS); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_orphelin.c b/TP1/api_systeme/pere_fils_orphelin.c new file mode 100644 index 0000000..9894904 --- /dev/null +++ b/TP1/api_systeme/pere_fils_orphelin.c @@ -0,0 +1,43 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fils orphelins */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + exit(EXIT_SUCCESS); /* Terminaison normale */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_sans_exit.c b/TP1/api_systeme/pere_fils_sans_exit.c new file mode 100644 index 0000000..29d6883 --- /dev/null +++ b/TP1/api_systeme/pere_fils_sans_exit.c @@ -0,0 +1,42 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Absence du exit dans le fils, et conséquences */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 3; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + /* Le fils ne s'arrete pas ici */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_wait.c b/TP1/api_systeme/pere_fils_wait.c new file mode 100644 index 0000000..d82ce9b --- /dev/null +++ b/TP1/api_systeme/pere_fils_wait.c @@ -0,0 +1,66 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* wait : le père attend la fin de ses fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, wstatus, fils_termine; + int duree_sommeil = 300; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + /* Le fils 2 s'endort pendant une durée asse longue */ + if (fils == 2) { + sleep(duree_sommeil); + } + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + sleep(3); /* pour les besoins de l'outil de validation automatique */ + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pere_fils_zombie.c b/TP1/api_systeme/pere_fils_zombie.c new file mode 100644 index 0000000..af2909f --- /dev/null +++ b/TP1/api_systeme/pere_fils_zombie.c @@ -0,0 +1,42 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fils Zombie */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + exit(EXIT_SUCCESS); /* Terminaison normale */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_alarm_waitpid.c b/TP1/api_systeme/pf_alarm_waitpid.c new file mode 100644 index 0000000..e17b34f --- /dev/null +++ b/TP1/api_systeme/pf_alarm_waitpid.c @@ -0,0 +1,89 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* SIGALRM et waitpid pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ +#define D_ALARM 10 /* durée pour alarm */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigalrm(int signal_num) { + int fils_termine, wstatus; + + if (signal_num == SIGALRM) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + } + } + /* relancer alarm a cela n'est pas fait automatiquement */ + alarm(D_ALARM); + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 3; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGALRM, handler_sigalrm); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil * fils); + printf("\n Processus fils numero %d : je m\'arrête.\n", fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + alarm(D_ALARM); + /* faire ce qu'on veut jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_calmaxtab_fichier.c b/TP1/api_systeme/pf_calmaxtab_fichier.c new file mode 100644 index 0000000..743f7d9 --- /dev/null +++ b/TP1/api_systeme/pf_calmaxtab_fichier.c @@ -0,0 +1,115 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Calcul distribué du maximum d'un tableau : communication par fichier */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ +#define NB_FLEM_FILS 100000 +#define NB_ELEM NB_FILS*NB_FLEM_FILS + +/* calcul du max d'un sous-tableau */ +int cal_max_tab(int tab[], int i1, int i2) { + int i, max; + + max = tab[i1]; + + for (i = i1 + 1; i < i2; i++) { + if (tab[i]>max) { + max = tab[i]; + } + } + return max; +} + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, max, max_lu; + + int tab[NB_ELEM]; + + char fichier[] = "fic_3f_maxtab"; + + /* initialiser le tableau */ + for (int i=0; i < NB_ELEM; i++) { + tab[i] = i+1; + } + + /* ouvrir le fichier en écriture */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* calculer le max du sous-tableau */ + max = cal_max_tab(tab, (fils-1)*NB_FLEM_FILS, fils*NB_FLEM_FILS); + /* enregistrer le max en binaire */ + write(desc_fic, &max, sizeof(int)); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* fermer le fichier ouvert en ecriture */ + close(desc_fic); + + /* ouvrir le fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + max = 0; + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + /* lire les nouvelles valeurs communiquées par les fils */ + /* et calculer le max intermédiaire */ + while (read(desc_fic, &max_lu, sizeof(int))>0) { + if (max_lu > max) { + max = max_lu; + } + } + } + close(desc_fic); + printf("\nProcessus Principal termine. Max = %d\n", max); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_fichier_ecr_ouv_sep.c b/TP1/api_systeme/pf_fichier_ecr_ouv_sep.c new file mode 100644 index 0000000..b87a048 --- /dev/null +++ b/TP1/api_systeme/pf_fichier_ecr_ouv_sep.c @@ -0,0 +1,86 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : plusieurs ouvertures, écritures concurrentes */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_sep.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + sleep(duree_sommeil); + } + + close(desc_fic); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_fichier_ecr_ouv_uni.c b/TP1/api_systeme/pf_fichier_ecr_ouv_uni.c new file mode 100644 index 0000000..737d9c4 --- /dev/null +++ b/TP1/api_systeme/pf_fichier_ecr_ouv_uni.c @@ -0,0 +1,87 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : 1 seule ouverture en écriture partagée */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_uni.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en ecriture, avec autorisations rw- -r- ---*/ + /* avec création si le fichier n'existe pas : O_CREAT */ + /* avec vidange (raz du contenu) si le fichier existe: O_TRUNC */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + sleep(duree_sommeil); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c b/TP1/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c new file mode 100644 index 0000000..e505db4 --- /dev/null +++ b/TP1/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c @@ -0,0 +1,96 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : 1 seule ouverture en écriture partagée et lseek */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_uni_lseek.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en ecriture, avec autorisations rw- -r- ---*/ + /* avec création si le fichier n'existe pas : O_CREAT */ + /* avec vidange (raz du contenu) si le fichier existe: O_TRUNC */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + // fils 2 recule la tete de 4 octets + if (fils == 2) { + lseek(desc_fic, -4, SEEK_CUR); + } + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + // fils 1 avance la tete de 4 octets + if (fils == 1) { + lseek(desc_fic, 4, SEEK_CUR); + } + sleep(duree_sommeil); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_fichier_lec_ouv_sep.c b/TP1/api_systeme/pf_fichier_lec_ouv_sep.c new file mode 100644 index 0000000..c1d2055 --- /dev/null +++ b/TP1/api_systeme/pf_fichier_lec_ouv_sep.c @@ -0,0 +1,85 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée avec ouvertures séparées */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + sleep(NB_FILS - fils); + + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4)>0) { + + printf(" Processus fils numero %d a lu %s\n", + fils, buffer); + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + + close(desc_fic); + + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_fichier_lec_ouv_uni.c b/TP1/api_systeme/pf_fichier_lec_ouv_uni.c new file mode 100644 index 0000000..9771a75 --- /dev/null +++ b/TP1/api_systeme/pf_fichier_lec_ouv_uni.c @@ -0,0 +1,82 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée entre père et fils avec ouverture unique */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + /* Initialiser buffer avec 0 */ + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les lectures des differents fils : fils 3, fils 2, fils 1 */ + sleep(NB_FILS - fils); + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4) > 0) { + printf(" Processus fils numero %d a lu %s\n", fils, buffer); + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_fichier_lec_ouv_uni_lseek.c b/TP1/api_systeme/pf_fichier_lec_ouv_uni_lseek.c new file mode 100644 index 0000000..468aadf --- /dev/null +++ b/TP1/api_systeme/pf_fichier_lec_ouv_uni_lseek.c @@ -0,0 +1,92 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée avec ouverture unique et lssek */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + /* Initialiser buffer avec 0 */ + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les lectures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + if (fils == NB_FILS) { + lseek(desc_fic, 4, SEEK_SET); + } + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4) > 0) { + + printf(" Processus fils numero %d a lu %s\n", + fils, buffer); + if (fils == 1) { + lseek(desc_fic, 4, SEEK_CUR); + } + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigchld_mask.c b/TP1/api_systeme/pf_sigchld_mask.c new file mode 100644 index 0000000..144a423 --- /dev/null +++ b/TP1/api_systeme/pf_sigchld_mask.c @@ -0,0 +1,103 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* masquage et démasquage de SIGCHLD */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ +#define DELAI 10 + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int fils_termine, wstatus; + + if (signal_num == SIGCHLD) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + } + } + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + sigset_t ens_signaux; + + sigemptyset(&ens_signaux); + + /* ajouter SIGCHLD à ens_signaux */ + sigaddset(&ens_signaux, SIGCHLD); + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil * fils); + printf("\n Processus fils numero %d : je m\'arrête.\n", fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* faire ce qu'on veut jusqu'à la terminaison de tous les fils */ + do { + /* période durant laquelle on ne veut pas être embêté par SIGCHLD */ + printf("\nProcessus de pid %d : Je masque SIGCHLD durant %d secondes\n", getpid(), DELAI); + /* masquer les signaux définis dans ens_signaux : SIGCHLD */ + sigprocmask(SIG_BLOCK, &ens_signaux, NULL); + sleep(DELAI); + + /* période durant laquelle on peut traiter le signal SIGCHLD */ + printf("\nProcessus de pid %d : Je démasque SIGCHLD\n", getpid()); + /* démasquer les signaux définis dans ens_signaux : SIGCHLD */ + sigprocmask(SIG_UNBLOCK, &ens_signaux, NULL); + sleep(2); + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigchld_wait.c b/TP1/api_systeme/pf_sigchld_wait.c new file mode 100644 index 0000000..af7cd1e --- /dev/null +++ b/TP1/api_systeme/pf_sigchld_wait.c @@ -0,0 +1,76 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* utilisation de SIGCHLD pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int wstatus, fils_termine; + + fils_termine = wait(&wstatus); + nb_fils_termines++; + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 300; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(2 + duree_sommeil * (fils -1)); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigchld_wait_sig_perdu.c b/TP1/api_systeme/pf_sigchld_wait_sig_perdu.c new file mode 100644 index 0000000..87d4f4c --- /dev/null +++ b/TP1/api_systeme/pf_sigchld_wait_sig_perdu.c @@ -0,0 +1,83 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* utilisation de SIGCHLD pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int wstatus, fils_termine; + + printf("\nJ'ai reçu le signal %d\n", signal_num); + fils_termine = wait(&wstatus); + nb_fils_termines++; + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + sleep(3); + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + //if (fils==3) duree_sommeil++; + sleep(duree_sommeil); + printf("\n Processus fils numero %d s'arrete\n", + fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + //sleep(2); /* pour les besoins de l'outil de validation automatique */ + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigchld_waitpid_while.c b/TP1/api_systeme/pf_sigchld_waitpid_while.c new file mode 100644 index 0000000..c7f9e29 --- /dev/null +++ b/TP1/api_systeme/pf_sigchld_waitpid_while.c @@ -0,0 +1,80 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* SIGCHLD et waitpid pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ +#include + +#define NB_FILS 4 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_chld(int signal_num) { + int fils_termine, wstatus; + printf("\nJ'ai reçu le signal %d\n", signal_num); + if (signal_num == SIGCHLD) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + sleep(1); + } + } + +} + +/* Programme principal : Un pere qui cree 3 fils */ + +int main() +{ + int fils, pid; + int duree_sommeil = 2; + + signal(SIGCHLD, handler_chld); + + printf("Je suis le processus principal %d, de pere %d\n", getpid(), getppid()); + nb_fils_termines = 0; + + for (fils=1; fils<=NB_FILS; fils++) { + pid = fork(); + if (pid<0) { // erreur fork + printf("Erreur fork\n"); + exit(1); + } + else if (pid==0) { //fils + printf("\n Processus fils num %d, de pid %d, de pere %d.\n", fils, getpid(), getppid()); + if (fils == 4) { + duree_sommeil = 300; + } + sleep(duree_sommeil); + printf("\n Processus fils num %d termine\n", fils); + exit(fils); /* normalement 0, mais on veut illustrer WEXITSTATUS */ + } + else {//pere + printf("\nProcessus pere de pid %d a cree un fils numero %d, de pid %d \n", getpid(), fils, pid); + } + } + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigint.c b/TP1/api_systeme/pf_sigint.c new file mode 100644 index 0000000..e4632e4 --- /dev/null +++ b/TP1/api_systeme/pf_sigint.c @@ -0,0 +1,67 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 600; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigint_ign_dfl.c b/TP1/api_systeme/pf_sigint_ign_dfl.c new file mode 100644 index 0000000..a6be450 --- /dev/null +++ b/TP1/api_systeme/pf_sigint_ign_dfl.c @@ -0,0 +1,73 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT : SIG_IGN et SIG_DFL */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 600; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + if (fils == 1) { + signal(SIGINT, SIG_IGN); + } + else if (fils == 2) { + signal(SIGINT, SIG_DFL); + } + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigint_ign_dfl_exec.c b/TP1/api_systeme/pf_sigint_ign_dfl_exec.c new file mode 100644 index 0000000..d946c10 --- /dev/null +++ b/TP1/api_systeme/pf_sigint_ign_dfl_exec.c @@ -0,0 +1,80 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT : SIG_IGN et SIG_DFL avec exec */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 300; + + char ref_exec[]="./dormir"; /* exécutable */ + char arg0_exec[]="je dors"; /* argument0 du exec : nom donnée au processus */ + char arg1_exec[]="300"; /* argument0 du exec : durée de sommeil */ + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + if (fils == 1) { + signal(SIGINT, SIG_IGN); + } + else if (fils == 2) { + signal(SIGINT, SIG_DFL); + } + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + execl(ref_exec, arg0_exec, arg1_exec, NULL); + /* on ne se retrouve ici que si exec échoue */ + printf("\n Processus fils numero %d : ERREUR EXEC\n", fils); + /* perror : affiche un message relatif à l'erreur du dernier appel systàme */ + perror(" exec "); + exit(fils); /* sortie avec le numéro di fils qui a échoué */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/pf_sigint_tstp_cont.c b/TP1/api_systeme/pf_sigint_tstp_cont.c new file mode 100644 index 0000000..850d88e --- /dev/null +++ b/TP1/api_systeme/pf_sigint_tstp_cont.c @@ -0,0 +1,70 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler); + signal(SIGTSTP, handler); + signal(SIGCONT, handler); + signal(SIGQUIT, handler); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP1/api_systeme/sigaction_source_signal.c b/TP1/api_systeme/sigaction_source_signal.c new file mode 100644 index 0000000..46eba85 --- /dev/null +++ b/TP1/api_systeme/sigaction_source_signal.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +/* traitant sigaction, avec récupération du pid de l'émetteur du signal */ +void sigaction_sig (int num_sig, siginfo_t *siginfo, void * notused) { + int emetteur; + + // récupérer le numéro du porcessus qui a envoyé le signal + emetteur = siginfo->si_pid; + + printf("Processus %d a recu le signal %d envoye par le processus %d \n", getpid(), num_sig, emetteur); +} + +/* traitant qui peut être utilisé en modifiant l'initialisation de sigaction */ +void handler_sig (int num_sig) { + printf("Processus %d a recu le signal %d\n", getpid(), num_sig); +} + +/* Programme principal + * un père crée un fils et s'endort pendant 120 secondes + * le fils se termine après 3 secondes environs ==> envoi de SIGCHLD au père + * le père traite (traitant sigaction dessus) SIGCHLD, SIGINT, SIGTSTP et SIGCONT : + * afficahge du numéro du signal reçu et du pid de l'émetterur + * A tester avec CtrlC, CtrlZ, et envoie des signaux depuis un autre terminal */ + +int main() { + struct sigaction s; + + int pid, retval, duree_sommeil = 120; + + /* Il est très important d'initialiser sa_flags, éventuellement avec 0 */ + s.sa_flags = SA_SIGINFO; // pour récupérer les infos dans siginfo + s.sa_sigaction = sigaction_sig; + + /* On utilise soit sa_sigaction ou sa_handler */ + // s.sa_handler = handler_sig; + + retval = sigaction(SIGINT, &s, NULL); // 3eme paramètre à NULL, car on ne + retval = sigaction(SIGTSTP, &s, NULL); // souhaite pas récupérer l'ancien + retval = sigaction(SIGCONT, &s, NULL); // sigaction + retval = sigaction(SIGCHLD, &s, NULL); + + if(retval < 0) { + perror("sigaction failed"); + } + + pid = fork(); + switch (pid) { + case -1 : + printf("Erreur fork\n"); exit(1); + case 0 : //fils + sleep(3); + exit(0); + + default : //pere + printf("Je suis le processus %d et j'ai cree un fils de numéro %d\n", getpid(), pid); + printf("Je m'endors pendant %d secondes et je traite les signaux SIGINT, SIGTSTP, SIGCONT et SIGCHLD\n", duree_sommeil); + + int duree=0; + do { + sleep(1); // sleep est arrêté par la réception d'un signal + // on ne peut donc pas utiliser sleep(duree_sommeil) + duree++; + } while (duree < duree_sommeil); + } + return 0; +} diff --git a/TP1/fournitures/.vscode/launch.json b/TP1/fournitures/.vscode/launch.json new file mode 100644 index 0000000..f798eb3 --- /dev/null +++ b/TP1/fournitures/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gcc - Build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}/${fileBasenameNoExtension}", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: gcc build active file", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/TP1/fournitures/.vscode/tasks.json b/TP1/fournitures/.vscode/tasks.json new file mode 100644 index 0000000..4956c3e --- /dev/null +++ b/TP1/fournitures/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/TP1/fournitures/arguments.c b/TP1/fournitures/arguments.c new file mode 100644 index 0000000..5f09fcc --- /dev/null +++ b/TP1/fournitures/arguments.c @@ -0,0 +1,53 @@ +#include /* printf */ +#include /* EXIT_SUCCESS */ + +int main(int argc,char *argv[]) { + int i; + + printf("argc = %d\n",argc); + for (i=0; i +#include +#include +#include + +int main(int argc, char *argv[], char *arge[]) { + + int codeTerm; + pid_t pidFils, idFils; + + setenv("TEST", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 1); + + extern char **environ; + + printf("environ père = \n"); + for (char **p = environ; *p ; p++) { + printf("%s\n", *p); + } + + pidFils=fork(); + + if (pidFils == -1) { + printf("Erreur fork\n"); + exit(1); + } + + if (pidFils == 0) { + printf("environ fils = \n"); + for (char **p = arge; *p ; p++) { + printf("%s\n", *p); + } + } + else { + idFils=wait(&codeTerm); + + if (idFils == -1){ + perror("wait "); + exit(2); + } + + if (WEXITSTATUS(codeTerm) != 0) { + printf("[%d] (%d)\n", WEXITSTATUS(codeTerm), idFils); + } + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/TP1/fournitures/execls.c b/TP1/fournitures/execls.c new file mode 100644 index 0000000..639aa67 --- /dev/null +++ b/TP1/fournitures/execls.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + int codeTerm; + pid_t pidFils, idFils; + + pidFils=fork(); + + if (pidFils == -1) { + printf("Erreur fork\n"); + exit(1); + } + + if (pidFils == 0) { + execl("/usr/bin/ls", "-l", NULL); + } else { + idFils=wait(&codeTerm); + if (idFils == -1){ + perror("wait "); + exit(2); + } + + if (WEXITSTATUS(codeTerm) != 0) { + printf("[%d] (%d)\n", WEXITSTATUS(codeTerm), idFils); + } + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/TP1/fournitures/ez.c b/TP1/fournitures/ez.c new file mode 100644 index 0000000..e6a31c5 --- /dev/null +++ b/TP1/fournitures/ez.c @@ -0,0 +1,37 @@ +#include +#include +#include /* exit */ + +int main(int argc, char *argv[]) { + int tempsPere, tempsFils; + int v=10; /* utile pour la section 2.3 */ + pid_t pidFils; + + tempsPere=10; + tempsFils=5; + pidFils=fork(); + /* bonne pratique : tester systématiquement le retour des appels système */ + if (pidFils == -1) { + printf("Erreur fork\n"); + exit(1); + /* par convention, renvoyer une valeur > 0 en cas d'erreur, + * différente pour chaque cause d'erreur + */ + } + if (pidFils == 0) { /* fils */ + printf("processus %d (fils), de père %d, v=%d\n", getpid(), getppid(), v); + + v = 100; + sleep(tempsFils); + printf("fin du fils, v=%d\n", v); + exit(EXIT_SUCCESS); /* bonne pratique : + terminer les processus par un exit explicite */ + } + else { /* père */ + printf("processus %d (père), de père %d, v=%d\n", getpid(), getppid(), v); + + sleep(tempsPere); + printf("fin du père, v=%d\n", v); + } + return EXIT_SUCCESS; /* -> exit(EXIT_SUCCESS); pour le père */ +} \ No newline at end of file diff --git a/TP1/fournitures/fic_ent.txt b/TP1/fournitures/fic_ent.txt new file mode 100644 index 0000000..5837601 --- /dev/null +++ b/TP1/fournitures/fic_ent.txt @@ -0,0 +1 @@ + exit diff --git a/TP1/fournitures/fic_ref.txt b/TP1/fournitures/fic_ref.txt new file mode 100644 index 0000000..e69de29 diff --git a/TP1/fournitures/fic_res.txt b/TP1/fournitures/fic_res.txt new file mode 100644 index 0000000..e69de29 diff --git a/TP1/fournitures/forktest.c b/TP1/fournitures/forktest.c new file mode 100644 index 0000000..5618a9e --- /dev/null +++ b/TP1/fournitures/forktest.c @@ -0,0 +1,11 @@ +#include /* printf */ +#include /* fork */ +#include /* EXIT_SUCCESS */ + +int main() { + fork(); printf("fork 1 : processus %d, de père %d\n", getpid(), getppid()); + fork(); printf("fork 2 : processus %d, de père %d\n", getpid(), getppid()); + fork(); printf("fork 3 : processus %d, de père %d\n", getpid(), getppid()); + //sleep(180); + return EXIT_SUCCESS; +} diff --git a/TP1/fournitures/miniminishell.c b/TP1/fournitures/miniminishell.c new file mode 100644 index 0000000..7a40ecf --- /dev/null +++ b/TP1/fournitures/miniminishell.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + + int codeTerm; + pid_t pidFils, idFils; + char buf[31]; + + while (1) { + printf(">>> "); + int ret = scanf("%s", buf); + + if (ret != 1) { + printf("\n"); + break; + } else if (!strcmp("exit", buf)) { // on quitte le shell + break; + } + + if (strcmp(buf, "")) { // si buf est vide on fait rien + pidFils = fork(); + + if (pidFils == -1) { + printf("ERROR fork\n"); + exit(1); + } + + if (pidFils == 0) { + execlp(buf, " ", NULL); + exit(2); // si execlp échoue on exit avec une erreur + } else { + idFils = wait(&codeTerm); // on attend la fin de l'exec de la commande + + if (idFils == -1){ + perror("wait "); + exit(3); + } + + if (WEXITSTATUS(codeTerm) == 0) { + printf("SUCCES\n"); + } else { + printf("ECHEC\n"); + } + } + } + } + + printf("Salut\n"); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/TP1/fournitures/verif/Notice.html b/TP1/fournitures/verif/Notice.html new file mode 100644 index 0000000..11dde01 --- /dev/null +++ b/TP1/fournitures/verif/Notice.html @@ -0,0 +1,30 @@ + + + + + + + + + + +

Avertissement

+

Le script de vérification verif.sh doit être considéré comme un simple outil mis à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, et non comme une application de validation automatique de votre travail. Simplement, si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation effective. Et inversement.

+

En particulier :

+
    +
  • il est inutile de modifier le script pour qu'il donne une réponse OK : la validation se fera sur nos propres outils.
  • +
  • le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers de manière intempestive, le script de vérification peut devenir invalide. Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis contre ce genre d'accidents.
  • +
  • en revanche, le script de vérification fonctionne bien avec des réponses correctes. Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être quasi-certains que cela ne découle pas d'une erreur dans le script de test.
  • +
+

Conventions de nommage

+

Pour que le script de vérification verif.sh puisse être appliqué :

+
    +
  • le fichier source du programme à vérifier doit être exactement nommé miniminishell.c
  • +
  • le répertoire contenant verif.sh ne devra pas être modifié, en dehors de l'ajout du fichier source.
  • +
+

Appel et résultats du script de vérification

+

Le script verif.sh doit être lancé depuis un terminal, le répertoire courant étant le répertoire contenant verif.sh.

+

Si la vérification échoue le script affiche KO ou KOOK, sinon il affiche OK. Le message KOOK doit être compris comme indiquant une forte présomption d'erreur, mais pas comme une certitude d'erreur. Vous pouvez consulter le script pour voir le test qui a levé ce (gros) soupçon... Notez que la mention OK est une condition nécessaire pour que la réponse soit juste, mais que ce n'est pas une condition suffisante. En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification ne devrait afficher aucun warning suite à la compilation.

+

Lorsque le script verif.sh se termine, il affiche un message OK, KO ou KOOK. Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut tuer le processus exécutant le script.

+ + diff --git a/TP1/fournitures/verif/Notice.md b/TP1/fournitures/verif/Notice.md new file mode 100644 index 0000000..28caa5f --- /dev/null +++ b/TP1/fournitures/verif/Notice.md @@ -0,0 +1,50 @@ +Avertissement +------------- +Le script de vérification `verif.sh` doit être considéré comme un simple outil mis à votre +disposition, pour vous fournir une indication quant à la viabilité de vos réponses, et non +comme une application de validation automatique de votre travail. Simplement, si vous passez +la vérification, vous pouvez avoir bon espoir quant à l'évaluation effective. Et inversement. + +En particulier : + + - il est inutile de modifier le script pour qu'il donne une réponse `OK` : la validation + se fera sur nos propres outils. + - le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées + à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers + de manière intempestive, le script de vérification peut devenir invalide. + Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis + contre ce genre d'accidents. + - en revanche, le script de vérification fonctionne bien avec des réponses correctes. + Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être + quasi-certains que cela ne découle pas d'une erreur dans le script de test. + +Conventions de nommage +---------------------- + +Pour que le script de vérification `verif.sh` puisse être appliqué : + + - le fichier source du programme à vérifier doit être **exactement** nommé `miniminishell.c` + - le répertoire contenant `verif.sh` ne devra pas être modifié, en dehors de l'ajout du + fichier source. + + +Appel et résultats du script de vérification +-------------------------------------------- + +Le script `verif.sh` doit être lancé depuis un terminal, le répertoire courant étant le +répertoire contenant `verif.sh`. + +Si la vérification échoue le script affiche `KO` ou `KOOK`, sinon il affiche `OK`. +Le message `KOOK` doit être compris comme indiquant une forte présomption d'erreur, mais +pas comme une certitude d'erreur. Vous pouvez consulter le script pour voir le test qui +a levé ce (gros) soupçon... +Notez que la mention `OK` est une condition nécessaire pour que la réponse soit juste, +mais que ce n'est pas une condition suffisante. +En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification +ne devrait afficher aucun warning suite à la compilation. + + +Lorsque le script `verif.sh` se termine, il affiche un message `OK`, `KO` ou `KOOK`. + Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut + tuer le processus exécutant le script. + \ No newline at end of file diff --git a/TP1/fournitures/verif/a/b/core b/TP1/fournitures/verif/a/b/core new file mode 100644 index 0000000..2e4af40 --- /dev/null +++ b/TP1/fournitures/verif/a/b/core @@ -0,0 +1,8 @@ +a +foo +lala.o +miniminishell.c +ms +Notice.html +Notice.md +verif.sh diff --git a/TP1/fournitures/verif/a/bar b/TP1/fournitures/verif/a/bar new file mode 100644 index 0000000..006a705 --- /dev/null +++ b/TP1/fournitures/verif/a/bar @@ -0,0 +1,3 @@ +ls +qdshjdhkjsq +more \ No newline at end of file diff --git a/TP1/fournitures/verif/a/hurz b/TP1/fournitures/verif/a/hurz new file mode 100644 index 0000000..84ec034 --- /dev/null +++ b/TP1/fournitures/verif/a/hurz @@ -0,0 +1 @@ +nnnnnnnnnnnnnnnnnnn \ No newline at end of file diff --git a/TP1/fournitures/verif/a/kro.o b/TP1/fournitures/verif/a/kro.o new file mode 100644 index 0000000..e69de29 diff --git a/TP1/fournitures/verif/a/pfurz b/TP1/fournitures/verif/a/pfurz new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/TP1/fournitures/verif/a/pfurz @@ -0,0 +1 @@ +2 diff --git a/TP1/fournitures/verif/a/s b/TP1/fournitures/verif/a/s new file mode 100644 index 0000000..2e4af40 --- /dev/null +++ b/TP1/fournitures/verif/a/s @@ -0,0 +1,8 @@ +a +foo +lala.o +miniminishell.c +ms +Notice.html +Notice.md +verif.sh diff --git a/TP1/fournitures/verif/foo b/TP1/fournitures/verif/foo new file mode 100644 index 0000000..28a37f1 --- /dev/null +++ b/TP1/fournitures/verif/foo @@ -0,0 +1,15 @@ +a +foo +lala.o +miniminishell.c +ms +Notice.html +Notice.md +verif.sh +>>> SUCCES +>>> >>> SUCCES +>>> ECHEC +>>> SUCCES +>>> SUCCES +>>> +Salut diff --git a/TP1/fournitures/verif/lala.o b/TP1/fournitures/verif/lala.o new file mode 100644 index 0000000..e8c4d10 --- /dev/null +++ b/TP1/fournitures/verif/lala.o @@ -0,0 +1,8 @@ +Notice.html +Notice.md +a +foo +lala.o +miniminishell.c +ms +verif.sh diff --git a/TP1/fournitures/verif/miniminishell.c b/TP1/fournitures/verif/miniminishell.c new file mode 100644 index 0000000..7a40ecf --- /dev/null +++ b/TP1/fournitures/verif/miniminishell.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + + int codeTerm; + pid_t pidFils, idFils; + char buf[31]; + + while (1) { + printf(">>> "); + int ret = scanf("%s", buf); + + if (ret != 1) { + printf("\n"); + break; + } else if (!strcmp("exit", buf)) { // on quitte le shell + break; + } + + if (strcmp(buf, "")) { // si buf est vide on fait rien + pidFils = fork(); + + if (pidFils == -1) { + printf("ERROR fork\n"); + exit(1); + } + + if (pidFils == 0) { + execlp(buf, " ", NULL); + exit(2); // si execlp échoue on exit avec une erreur + } else { + idFils = wait(&codeTerm); // on attend la fin de l'exec de la commande + + if (idFils == -1){ + perror("wait "); + exit(3); + } + + if (WEXITSTATUS(codeTerm) == 0) { + printf("SUCCES\n"); + } else { + printf("ECHEC\n"); + } + } + } + } + + printf("Salut\n"); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/TP1/fournitures/verif/verif.sh b/TP1/fournitures/verif/verif.sh new file mode 100644 index 0000000..9aa2282 --- /dev/null +++ b/TP1/fournitures/verif/verif.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# PM, le 31/3/21 + +export PATH=.:$PATH +rep=`pwd` +res=OK + +gcc -Wall miniminishell.c -o ms +ms < a/bar > foo + +if [ ! \( -f foo \) ] ; then +res=KO +fi + +grep -v '>>>' foo | grep -v 'Salut'| sort > a/b/core +sort lala.o > a/s +diff a/b/core a/s +if [ $? -ne 0 ] ; then +res=KO +fi + +if [ \( `grep '^>>>' foo | wc -l` -lt 3 \) -o \( `grep 'SUCCES' foo | wc -l` -lt 2 \) -o \( `grep 'ECHEC' foo | wc -l` -lt 1 \) ] ; then +res=KO +fi + +if [ `grep '^Salut' foo | wc -l` -ne 1 ] ; then +res=KOOK +fi + +echo $res diff --git a/TP1/fournitures/vmsh1.sh b/TP1/fournitures/vmsh1.sh new file mode 100644 index 0000000..df2e9ae --- /dev/null +++ b/TP1/fournitures/vmsh1.sh @@ -0,0 +1,68 @@ +#!/bin/sh +# ZH 30/3/21 ; PM 2/4/21 +verifer() { + sed -i '/^$/d' $fres + sed -i '/^$/d' $fref + sed -i 's/\(^>>>.*\)\(SUCCES\).*/\1\n\2/g' $fres + sed -i 's/\(^>>>.*\)\(ECHEC\).*/\1\n\2/g' $fres + sed -i '/^>>>/d' $fres + sed -i '/^>>>/d' $fres + sed -i '/^Salut/d' $fres + sres=$(cut -d' ' -f1 $1) + sref=$(cut -d' ' -f1 $2) + if [ "$sres" != "$sref" ]; then + echo '' + echo "---Erreur: $3" + echo "$sres" + echo "<>" + echo "$sref" + else + echo "---Succès: $3\n" + fi +} + +if [ -n "$1" -a -x "$1" ]; then + fent=fic_ent.txt + fref=fic_ref.txt + fres=fic_res.txt + #pwd + echo pwd exit > $fent + # echo pwd > $fent + $1 <$fent >$fres + pwd > $fref + echo SUCCES >> $fref + verifer $fres $fref pwd + #date + echo date exit > $fent + # echo date > $fent + $1 <$fent >$fres + date > $fref + echo SUCCES >> $fref + verifer $fres $fref date + #erreur :argument absent + echo grep exit > $fent + # echo grep > $fent + echo '' >$fres + $1 <$fent 2>>$fres >>$fres + grep 2> $fref + echo ECHEC >> $fref + verifer $fres $fref grep + #erreur : commande non trouvée + echo bonjour exit > $fent + # echo bonjour > $fent + echo '' >$fres + $1 <$fent 2>>$fres >>$fres + bonjour 2> $fref + echo ECHEC >> $fref + sed -i "/vmsh1/d" $fref + verifer $fres $fref bonjour + #erreur : commande vide + echo '' exit > $fent + #echo '' > $fent + echo '' >$fres + $1 <$fent 2>>$fres >>$fres + echo '' >$fref + verifer $fres $fref "commande vide" +else + echo "USAGE : $0 nom_executable" +fi \ No newline at end of file diff --git a/TP1/fournitures/we.c b/TP1/fournitures/we.c new file mode 100644 index 0000000..c31bdc6 --- /dev/null +++ b/TP1/fournitures/we.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include /* wait */ + +int main(int argc, char *argv[]) { + int tempsFils, codeTerm; + pid_t pidFils, idFils; + + tempsFils=10; + pidFils=fork(); + /* bonne pratique : tester systématiquement le retour des appels système */ + if (pidFils == -1) { + printf("Erreur fork\n"); + exit(1); + /* par convention, renvoyer une valeur > 0 en cas d'erreur, + * différente pour chaque cause d'erreur + */ + } + if (pidFils == 0) { /* fils */ + printf("processus %d (fils), de père %d\n", getpid(), getppid()); + sleep(tempsFils); + printf("fin du fils\n"); + exit(EXIT_SUCCESS); + } + else { /* père */ + printf("processus %d (père), de père %d\n", getpid(), getppid()); + idFils=wait(&codeTerm); + if (idFils == -1) { + perror("wait "); + exit(2); + } + if (WIFEXITED(codeTerm)) { + printf("[%d] fin fils %d par exit %d\n",codeTerm,idFils,WEXITSTATUS(codeTerm)); + } else { + printf("[%d] fin fils %d par signal %d\n",codeTerm,idFils,WTERMSIG(codeTerm)); + } + printf("fin du père\n"); + } + return EXIT_SUCCESS; /* -> exit(EXIT_SUCCESS); pour le père */ +} \ No newline at end of file diff --git a/TP1/processus.html b/TP1/processus.html new file mode 100644 index 0000000..3aebe4f --- /dev/null +++ b/TP1/processus.html @@ -0,0 +1,1929 @@ + + + + + +Processus Unix + + + + + + + + + + + + + + + + + + + + + +
+ +
+

Gestion des processus Unix

+
+ + + +
+ +
+ +Auteur: Zouheir HAMROUNI + +
+ + + +
+

Unix : concepts fondamentaux

+
+

+Unix met en oeuvre plusieurs concepts fondamentaux : +

    +
  • +Les processus : pour la gestion des traitements (exécutions de programmes). +Ce concept encapsule l’exécution d’un programme de façon à assurer l’allocation et le contrôle +des ressources nécessaires à cette exécution (processeur(s), mémoires, +périphériques, fichiers, pipes, sockets…). Plusieurs processus peuvent +exister en parallèle et se partager de façon optimisée ces ressources. +
  • +
    +
  • Les fichiers : pour la gestion des données, ce concept permet d’assurer une rémanence et +un contrôle des données des usagers du système. +
  • +
    +
  • +La gestion dynamique des processus et fichiers dans une structure +arborescente. En effet, tout processus est un descendant d’un processus +père, et appartient à une arborescence qui a pour racine le processus +initial (numéro 1) ; et tout fichier est placé dans une arborescence de +répertoires ayant une racine unique. +
  • +
    +
  • La protection des ressources : Tout processus s’exécute pour un usager appartenant à un groupe. +Tout fichier possède de la même manière un créateur identifié. L’identification d’un usager +définit ainsi une capacité d’accès de cet usager aux ressources du système via les processus +qu’il engendrera. +
  • +
    +
  • +La transparence de l’architecture matérielle : ce principe consiste à masquer +les particularités des architectures supports. Le noyau système définit par exemple un système +de gestion d’exceptions (déroutements et interruptions), et des signaux indépendants de tout +processeur matériel. +
  • +
+ +
+
+
+

1 Etape 1 : Les Processus

+Un processus est une instance d'exécution d'un programme (un programme +en cours d'exécution). Ce concept encapsule l’exécution d’un programme +de manière à assurer l’allocation et le contrôle +des ressources nécessaires à cette exécution (temps processeur, mémoire, + +périphériques, fichiers, pipes, sockets…). Plusieurs processus peuvent +exister en parallèle et se partager de façon optimisée ces ressources. +

+Les processus sont organisés dans une structure arborescente : tout +processus est un descendant d’un processus père, et appartient à une +arborescence qui a pour racine le processus initial. +

+Chaque processus Unix possède un numéro "pid" (process id), et un +processus père (son créateur, et son supérieur dans l'arborescence des +processus). Le processus initial (racine de l'arborescence) porte le +numéro 1. +

+Nous allons nous intéresser aux primitives de base de gestion des +processus. Par défaut, et sauf précision contraire, ces primitives sont +définies dans "unistd.h", fichier à référencer en début du code. +

#include <unistd.h>
+
+ +
+

1.1 Identification : getpid() et getppid()

+
+ +
    +
  • +pid_t getpid() : retourne le pid du processus appelant (pid_t : synonyme d'entier). +
  • +
  • +pid_t getppid() : retourne le pid du père du processus appelant. +
  • +
+

Chaque processus peut donc connaître son numéro (pid) et le numéro de son père (ppid). +

+
+ +
+

1.2 La primitive sleep()

+
+ +unsigned int sleep(int n) : endort le processus +appelant pour une durée de n secondes. Cette durée peut être écourtée +dès qu'un signal non ignoré est reçu. +

+sleep() renvoie zéro si le temps prévu s'est écoulé, ou le nombre de secondes restantes si l'appel a été interrompu. +

+Nous l'utiliserons pour faire durer les processus testés pendant un temps choisi. + +

+
+ +
+

1.3 La primitive exit()

+
+ +void exit(int n) : met fin au processus appelant avec n comme code de retour. +

Par convention, le code de retour est : +

    +
  • +est égal à 0 (EXIT_SUCCESS : constante prédéfinie) après un comportement correct +
  • +
  • +est différent de 0 pour indiquer une erreur +
  • +
+
+
+ +
+

1.4 Création d'un processus : fork()

+
+Un processus peut créer un fils en appelant la primitive fork() : +

+pid_t fork() : crée dynamiquement un nouveau processus (fils) qui s'exécute de façon +concurrente avec le processus qui le crée (processus père). Ce processus fils hérite du processus +père les attributs suivants : +

    +
  • + même code +
  • +
  • + une copie de la zone de données du père +
  • +
  • + environnement d'exécution +
  • +
  • + priorité +
  • +
  • + descripteurs de fichiers ouverts +
  • +
  • + traitement des signaux +
  • +
+Après exécution du fork(), on se trouve avec deux processus (un père et un fils) +ayant le même code et +la même image de données. En cas de succès, la primitive fork() renvoie deux valeurs différentes : +
    +
  • + dans le code du père : la valeur de retour indique le pid du fils créé (>0) +
  • +
  • + dans le code du fils : la valeur de retour est égale à 0 +
  • +
+ + En cas d'échec (nombre maximum de processus atteint) : aucun fils n'est créé et la valeur de retour du fork() est égale à -1 + + +

Même si le père et son fils ont le même code, on peut différencier les traitements effectués +par l'un et par l'autre en se basant sur la valeur de retour du fork. +

+Le code suivant illustre ce concept : le processus principal crée 3 fils, en +répétant le même traitement à l'intérieur d'une boucle "for" dans laquelle il passe 3 fois. +

+Au premier passage (fils=1), le processus principal exécute la primitive fork(), +dont on doit traiter les 3 cas de retour : +

    +
  • +retour = -1 : le fork() a échoué et aucun fils n'a été créé. Dans ce cas, le processus principal s'arrête en faisant appel à la primitive exit() et en y indiquant une valeur d'arrêt différente de 0 (par convention). Il est important +de prévoir le traitement du retour d'erreur de toute primitive système. +
  • +
    +
  • +retour >= 0 : le fork() a créé un processus fils qui hérite du même code que son père. La valeur de retour n'est pas la même dans les deux codes : +
  • +
    +
      +
    • +retour = 0 : on se trouve dans le code du fils, qui va exécuter la séquence à l'intérieur du +"if (retour == 0)" : +
    • +
        +
      • +affiche son numéro, son pid et le pid de son père +
      • +
      • +s'endort pendant 3 secondes +
      • +
      • +et s'arrête en faisant appel à la primitive exit(). Par conséquent, le fils, +même s'il hérite de la +totalité du code de son père, ne va jamais entrer de nouveau dans la boucle "for". +Nous verrons plus loin ce qu'il se passe si on enlève l'appel à exit(). +
      • +
      +

      +

    • +retour > 0 : on se trouve dans le code du père, qui affiche le numéro et le pid du fils qu'il vient +de créer, et repart dans la boucle "for". +
    • +
    +
+Le même traitement se répète lors du deuxième et du troisième passage dans la boucle "for". +

+

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* Création de fils : fork et exit */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 
+  8 #define NB_FILS 3     /* nombre de fils */
+  9 
+ 10 int main()
+ 11 {
+ 12     int fils, retour ;
+ 13     int duree_sommeil = 2 ;
+ 14 
+ 15     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 16 
+ 17     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 18         retour = fork() ;
+ 19 
+ 20         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 21         if (retour < 0) {   /* échec du fork */
+ 22             printf("Erreur fork\n") ;
+ 23             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 24             exit(1) ;
+ 25         }
+ 26 
+ 27         /* fils */
+ 28         if (retour == 0) {
+ 29             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 30                     fils, getpid(), getppid()) ;
+ 31             sleep(duree_sommeil) ;
+ 32             /* Important : terminer un processus par exit */
+ 33             exit(EXIT_SUCCESS) ;   /* Terminaison normale (0 = sans erreur) */
+ 34         }
+ 35 
+ 36         /* pere */
+ 37         else {
+ 38             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 39                     getpid(), fils, retour) ;
+ 40         }
+ 41     }
+ 42     sleep(duree_sommeil) ;
+ 43     return EXIT_SUCCESS ;
+ 44 }
+
+ +

Pour valider cet exercice, il faut : + +

    +
  • +Compiler le code ci-dessus : gcc -Wall -o nom_executable pere_fils.c +
  • +
  • +lancer l'outil de validation "apisys" dans un terminal shell +
  • +
  • +se placer sur le bon exercice (commandes p et s) et lancer son exécution +
  • +
  • +répondre aux questions posées +
  • +
+ +

Visualiser l'interprétation des résultats

+ + +
+
+ +
+

1.5 Importance du exit()

+
+ +

Dans l'exemple dessus, le code du fils est délimité entre le "if (retour == 0)" et exit(EXIT_SUCCESS). Ce qui permet de séparer clairement le code exécuté par le père de celui du fils. +

+Si on reprend le même code que dessus et on supprime le exit(EXIT_SUCCESS), on abtient un comprtement très différent des fils. +

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* Absence du exit dans le fils, et conséquences */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 
+  8 #define NB_FILS 3     /* nombre de fils */
+  9 
+ 10 int main()
+ 11 {
+ 12     int fils, retour ;
+ 13     int duree_sommeil = 3 ;
+ 14 
+ 15     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 16 
+ 17     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 18         retour = fork() ;
+ 19 
+ 20         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 21         if (retour < 0) { 
+ 22             printf("Erreur fork\n") ;
+ 23             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 24             exit(1) ;
+ 25         }
+ 26 
+ 27         /* fils */
+ 28         if (retour == 0) {
+ 29             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 30                     fils, getpid(), getppid()) ;
+ 31             /* Le fils ne s'arrete pas ici */
+ 32         }
+ 33 
+ 34         /* pere */
+ 35         else {
+ 36             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 37                     getpid(), fils, retour) ;
+ 38         }
+ 39     }
+ 40     sleep(duree_sommeil) ;
+ 41     return EXIT_SUCCESS ;
+ 42 }
+
+ +

+Testez ce code dans l'outil "apisys" (comme indiqué plus haut), et répondez aux questions posées. +

Visualiser l'interprétation des résultats

+ + +
+
+ + +
+

1.6 Héritage des données

+
+Comme indiqué dessus, le processus fils hérite d'une copie de la zone de données de son père. +Il possède donc une copie de toutes les variables du code. Pour une variable donnée, +la valeur vue par le fils est la même que celle vue par le père tant que cette variable +n'est pas modifiée. Car dès que la avriable est modifiée par le père ou par le fils, +la copie du fils devient forcément différente de celle du père. +

+Le code suivant reprend le premier code présenté plus haut en ajoutant une variable appelée "patrimoine_fils", +que le père initialise à 10000, comme cadeau de naissance qu'il réserve à chaque nouveau fils. +

+Chaque fils, fait fructifier son patrimoine, modifie donc la variable patrimoine_fils, et l'affiche avant de s'arrêter. +

+De son côté, le père essaie de calculer le patrimoine total de ses fils en lisant la variable +patrimoine_fils, mais malheureusement pour lui, il n'a accès qu'à sa propore copie, et pas +à celles de ses fils. +

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* Héritage et dupplication des données */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 
+  8 #define NB_FILS 3     /* nombre de fils */
+  9 #define DELAI 3
+ 10 
+ 11 int main()
+ 12 {
+ 13     int fils, retour ;
+ 14     int cagnotte, patrimoine_fils ;
+ 15     int duree_sommeil = 3 ;
+ 16     cagnotte = 30000 ;
+ 17     patrimoine_fils = cagnotte / NB_FILS ;
+ 18 
+ 19     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 20     printf("Je dispose de %d Euros, que je partage entre mes futurs fils\n", cagnotte) ;
+ 21 
+ 22     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 23         retour = fork() ;
+ 24 
+ 25         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 26         if (retour < 0) {   /* échec du fork */
+ 27             printf("Erreur fork\n") ;
+ 28             exit(1) ;
+ 29         }
+ 30 
+ 31         /* fils */
+ 32         if (retour == 0) {
+ 33             printf("\n    Processus fils numero %d : mon pere m'a offert %d Euros\n", 
+ 34                     fils, patrimoine_fils) ;
+ 35             patrimoine_fils = patrimoine_fils * (fils + 1) ;   
+ 36             sleep(duree_sommeil) ;
+ 37             printf("\n    Processus fils numero %d - j'ai augmente mon patrimoine a %d Euros\n", 
+ 38                     fils, patrimoine_fils) ;
+ 39             exit(EXIT_SUCCESS) ;   /* Te:rminaison normale (0 = sans erreur) */
+ 40         }
+ 41 
+ 42         /* pere */
+ 43         else {
+ 44             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 45                     getpid(), fils, retour) ;
+ 46         }
+ 47     }
+ 48     sleep(duree_sommeil+1) ;
+ 49 
+ 50     printf("\nProcessus Principal - le patrimoine total de mes fils est de %d\n", patrimoine_fils*NB_FILS) ;
+ 51     return EXIT_SUCCESS ;
+ 52 }
+
+ +

+Testez ce code dans l'outil "apisys" (comme indiqué plus haut), et répondez aux questions posées. +

Visualiser l'interprétation des résultats

+ +
+
+ + +
+

1.7 Héritage des descripteurs

+
+

+Chaque processus échange des informations avec son environnement (écran, clavier, +fichiers, etc) sous la forme de suites d’octets (ou flots d’entrées/sorties). +L'accès à chaque canal de communication (lecture/écriture) se fait par l'intermédiaire d'un descripteur (numéro >=0). +

+

+Par défaut, Unix/Linux gère trois flots d’entrée/sortie : +

    +
  • +l’entrée standard (flot numéro 0), stdin, associée au clavier, +
  • +
  • +la sortie standard (flot numéro 1), stdout, associée à l’écran, +
  • +
  • +la sortie erreur standard (flot numéro 2), stderr, associée aussi à l’écran. +
  • +
+
+Il est possible de modifier ces associations pour un processus : par exemple, associer la sortie +standad à un fichier, de manère à ce que les messages ne s'affichent plus à l'écran, +mais s'écrivent dans ce fichier. +

Cette modification ne nécessite pas la modification du code, +et se fait simplement avec un mécanisme appelé redirection : +

    +
  • +la sortie standard peut être redéfinie à l’aide du caractère > : dans la commande +suivante, le résultat du ls est redirigé dans le fichier fic +
    ls > fic 
    +
    +
  • +
  • +il est possible d'ajouter à un fichier le résultat d'une commande : dans la commande suivante, +le résultat du ls -l s'ajoute au fichier fic +
    ls -l >> fic 
    +
    +
  • +
  • +en Bourne shell, sh ou bash, la sortie erreur standard peut être redirigée par +2> : la commande suivante écrit les messages d’erreurs éventuellement +engendrés par l’exécution de rm dans le fichier fic +
    rm toto 2> ficerreur
    +
    +
  • +
  • +l’entrée standard peut être redirigée par < : les commandes suivantes +réalisent une lecture d'un caractère au clavier et son affichage, en passant par la variable c +
    read c; echo $c  
    +
    +Dans cette seconde version, la lecture est faite dans le fichier fic +
    read c < fic ; echo $c  
    +
    +
  • +
+
+

Un processus fils hérite de tous les descripteurs ouverts dans son père (entrées/sorties +standard, fichiers, etc.). +

    +
  • +Nous avons vu lors des exécutions précédentes que les messages +du père et ceux des différents fils sont affichés dans le même terminal (sortie standard). +
  • +

    +

  • +De même, tout descripteur de fichier ouvert par le père est hérité par ses fils, +y compris lorsque ce fichier est ouvert par redirection. +
  • +
+

+Pour illustrer cela, on reprend le premier programme pere_fils.c et on l'exécute en redirigeant +la sortie standard dans un fichier : (pere_fils > fic_sortie). +

Après exécution, on peut remarquer : +

    +
  • +aucun message n'est affiché dans le terminal d'exécution +
  • +
  • +les messages qui devaient s'afficher dans le terminal d'exécution se trouvent +maintenant dans le fichier "fic_sortie" +
  • +
  • +mais, certains messages sont en double ou en triple +
  • +
+

L'explication de ce dernier point, se trouve dans le fonctionnement du "printf". +D'après le standard ISO, le comprtement du "printf" n'est pas le même pour la sortie +standard et pour un fichier ordinaire : +

    +
  • +dans le cas d'une sortie interactive (terminal), le flot est géré par ligne +et \n provoque la vidange du tampon langage +
  • +
  • +dans le cas d'une sortie dans un fichier ordinaire, le flot est géré par + bloc +(pour limiter les échanges avec le fichier) : '\n' est traité comme un +caractère ordinaire et ne commande plus la vidange du buffer. +
  • +
+

+Chaque fils hérite du tampon (zone mémoire) de sortie du père, qui contient les messages +déjà envoyés par le père et non vidangés, auxquels va s'ajouter le message du fils. +Par conséquent, chaque fils va envoyer un flot de données contenant, en plus de son propre +message, les messages antérieurs du père. C'est pour cela que certains messages se +strouvent en 3 exemplaires (réaffichés par les fils 2 et 3), et d'autres en double +exemplaire (réaffichés par le fils 3). +

    +
  • +Le fis nuéro 1 récupère un tampon qui contient le premeir message du père +
  • +
  • +Le fis nuéro 2 récupère un tampon qui contient +
      +
    • +le premeir message du père +
    • +
    • +le message affiché par le père lors du premier passage dans la boucle +
    • +
    +
  • +
  • +Le fis nuéro 3 récupère un tampon qui contient +
      +
    • +le premeir message du père +
    • +
    • +le message affiché par le père lors du premier passage dans la boucle +
    • +
    • +le message affiché par le père lors du deuxième passage dans la boucle +
    • +
    +
  • +
+

+Pour forcer la vidange du tampon de sortie, on fait un appel explicite à fflush(stdout) après +chaque printf du père. Ainsi, le fils créé hérite d'un tampon vide et ne dupplique plus +l'affichage des messages de son père. +

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* Redirection et fflush */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 
+  8 #define NB_FILS 3     /* nombre de fils */
+  9 
+ 10 int main()
+ 11 {
+ 12     int fils, retour ;
+ 13     int duree_sommeil = 2 ;
+ 14 
+ 15     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 16 
+ 17     /* Vidange du tampon de sortie pour que le fils le récupère vide        */
+ 18     /* D'après le standard ISO le comportement du printf présente 2 cas :   */
+ 19     /* - sortie interactive (terminal) : flot géré par ligne et \n provoque */
+ 20     /*   la vidange du tampon langage 
+ 21     /* - sortie dans un fichier : flot géré par bloc et \n est traité comme */
+ 22     /*   un caractère ordinaire. fflush(stdout) force la vidange du tampon. */
+ 23 
+ 24     fflush(stdout) ;
+ 25 
+ 26     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 27         retour = fork() ;
+ 28 
+ 29         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 30         if (retour < 0) {   /* échec du fork */
+ 31             printf("Erreur fork\n") ;
+ 32             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 33             exit(1) ;
+ 34         }
+ 35 
+ 36         /* fils */
+ 37         if (retour == 0) {
+ 38             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 39                     fils, getpid(), getppid()) ;
+ 40             sleep(duree_sommeil) ;
+ 41             /* Important : terminer un processus par exit */
+ 42             exit(EXIT_SUCCESS) ;   /* Terminaison normale (0 = sans erreur) */
+ 43         }
+ 44 
+ 45         /* pere */
+ 46         else {
+ 47             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 48                     getpid(), fils, retour) ;
+ 49             /* vidange du tampon de sortie pour que le fils le récupère vide */
+ 50             fflush(stdout) ;
+ 51         }
+ 52     }
+ 53     sleep(duree_sommeil) ;
+ 54     return EXIT_SUCCESS ;
+ 55 }
+
+
+
+
+ +

Testez ce code dans l'outil "apisys" et vérifiez que les messages ne sont +plus duppliqués. + +

+

1.8 Fils orphelin

+
+

+Lorsque le processus père se termine (disparait) avant son fils, ce dernier devient orphelin, +et est rattaché (adopté) au processus initial portant le numéro 1. +

+

+On reprend le programme initial pere_fils.c, et on fait durer les fils plus +longtemps que le père, en agissant sur le paramètre du sleep. +

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* Fils orphelins */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 
+  8 #define NB_FILS 3     /* nombre de fils */
+  9 
+ 10 int main()
+ 11 {
+ 12     int fils, retour ;
+ 13     int duree_sommeil = 120 ;
+ 14 
+ 15     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 16 
+ 17     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 18         retour = fork() ;
+ 19 
+ 20         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 21         if (retour < 0) {   /* échec du fork */
+ 22             printf("Erreur fork\n") ;
+ 23             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 24             exit(1) ;
+ 25         }
+ 26 
+ 27         /* fils */
+ 28         if (retour == 0) {
+ 29             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 30                     fils, getpid(), getppid()) ;
+ 31             sleep(duree_sommeil) ;
+ 32             exit(EXIT_SUCCESS) ;       /* Terminaison normale */
+ 33         }
+ 34 
+ 35         /* pere */
+ 36         else {
+ 37             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 38                     getpid(), fils, retour) ;
+ 39         }
+ 40     }
+ 41     sleep(1) ;
+ 42     return EXIT_SUCCESS ;
+ 43 }
+
+

+Si on exécute ce nouveau code, et on tape +la commande "ps l" dans un autre terminal, on peut voir dans la colonne "PPID" +du tableau affiché, que les 3 fils ont pour père le processus 1. + +

+
+ +
+

1.9 Fils zombie

+
+

+Lorsque un processus fils se termine sans que son père prenne connaissance de cette +terminaison, ce fils reste présent et entre dans un état zombie. +

+

+On reprend le programme initial pere_fils.c, et on fait durer le père plus +longtemps que les fils, en agissant sur le paramètre du sleep. +

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* Fils Zombie */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 
+  8 #define NB_FILS 3     /* nombre de fils */
+  9 
+ 10 int main()
+ 11 {
+ 12     int fils, retour ;
+ 13     int duree_sommeil = 120 ;
+ 14 
+ 15     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 16 
+ 17     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 18         retour = fork() ;
+ 19 
+ 20         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 21         if (retour < 0) {   /* échec du fork */
+ 22             printf("Erreur fork\n") ;
+ 23             exit(1) ;
+ 24         }
+ 25 
+ 26         /* fils */
+ 27         if (retour == 0) {
+ 28             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 29                     fils, getpid(), getppid()) ;
+ 30             exit(EXIT_SUCCESS) ;   /* Terminaison normale */
+ 31         }
+ 32 
+ 33         /* pere */
+ 34         else {
+ 35             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 36                     getpid(), fils, retour) ;
+ 37         }
+ 38     }
+ 39     sleep(duree_sommeil) ;
+ 40     return EXIT_SUCCESS ;
+ 41 }
+
+

+Si on exécute ce nouveau code, et on tape +la commande "ps l" dans un autre terminal, on peut voir dans la colonne STAT +du tableau affiché, que les 3 fils sont dans l'état zombie (Z, ou Z+) et dans la +dernière colonne le terme "defunct" ajouté après leur nom. + +

+
+ +
+

1.10 wait()

+
+Souvent, le processus père a besoin de prendre connaissance de la terminaison +des fils qu'il a créés, et d'en connaître le code ou la cause de fin. La primitive +wait() (définie dans sys/wait.h) permet de réaliser +cette opération. +

+pid_t wait(int *status) permet d'attendre (de façon bloquante) la terminaison +d'un fils du processus appelant (terminé avec exit ou tué par un signal). Elle : +

    +
  • renvoie le pid du fils qui s'est arrêté ou a été arrêté +
  • +

    +

  • indique dans le paramètre status, passé par référence, le code de terminaison (exit) +ou le numéro du signal ayant tué le fils. L'accès à ces informations est facilité par des macros : +
      +
    • +WIFEXITED(status) est vrai si le fils s'est terminé avec exit +
    • +
    • WEXITSTATUS(status) renvoie la valeur du exit +
    • +
    • WIFSIGNALED(status) est vrai si le fils a été tué par un signal +
    • +
    • WTERMSIG(status) renvoie le numéro du signal ayant tué le fils +
    • +
    +
  • +
+

Le code suivant reprend le code initial en y modifiant les points suivants : +

    +
  • les fils 1 et 3 terminent immédiatement sans attente +
  • +
  • le fils 2 s'en dort pendant une durée assez longue +
  • +
  • les 3 fils renvoient leur numéro (respectivement 1, 2, 3) comme valeur de fin +
  • +
  • le processus principal (père) attend la fin de ses 3 fils, et affiche pour chacun d'eux : +
      +
    • la cause de teminaison : avec exit, ou tué par un signal : +
    • +
    • la valuer du exit ou le numéro du signal +
    • +
    +
  • +
+
  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* wait : le père attend la fin de ses fils */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 #include <sys/wait.h> /* wait */
+  8 
+  9 #define NB_FILS 3     /* nombre de fils */
+ 10 
+ 11 int main(
+ 12 {
+ 13     int fils, retour, wstatus, fils_termine ;
+ 14     int duree_sommeil = 300;
+ 15 
+ 16     printf("\nJe suis le processus principal de pid %d\n", getpid()) ;
+ 17     /* Vidange du tampon de sortie pour que le fils le récupère vide        */
+ 18     fflush(stdout) ;
+ 19 
+ 20     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 21         retour = fork() ;
+ 22 
+ 23         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 24         if (retour < 0) {   /* échec du fork */
+
+ 25             printf("Erreur fork\n") ;
+ 26             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 27             exit(1) ;
+ 28         }
+ 29 
+ 30         /* fils */
+ 31         if (retour == 0) {
+ 32             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 33                     fils, getpid(), getppid()) ;
+ 34             /* Le fils 2 s'endort pendant une durée asse longue */
+ 35             if (fils == 2) {
+ 36                 sleep(duree_sommeil) ;
+ 37             }
+ 38             exit(fils) ;  /* normalement exit(0), mais on veut illustrer WEXITSTATUS */
+ 39         }
+ 40 
+ 41         /* pere */
+ 42         else {
+ 43             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 44                     getpid(), fils, retour) ;
+ 45         }
+ 46     }
+ 47 
+ 48     sleep(3) ;   /* pour les besoins de l'outil de validation automatique */
+ 49 
+ 50     /* attendre la fin des fils */
+ 51     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 52         /* attendre la fin d'un fils */
+ 53         fils_termine = wait(&wstatus) ;
+ 54 
+ 55         if WIFEXITED(wstatus) {   /* fils terminé avec exit */
+
+ 56             printf("\nMon fils de pid %d a termine avec exit %d\n", 
+ 57                     fils_termine, WEXITSTATUS(wstatus)) ;
+ 58         }
+ 59         else if WIFSIGNALED(wstatus) {  /* fils tué par un signal */
+ 60             printf("\nMon fils de pid %d a ete tue par le signal %d\n", 
+ 61                     fils_termine, WTERMSIG(wstatus)) ;
+ 62         }
+ 63     }
+ 64     printf("\nProcessus Principal termine\n") ;
+ 65     return EXIT_SUCCESS ;
+ 66 }
+
+

Testez ce code dans l'outils "apisys" et répondez aux questions posées. +

+
+ +
+

1.11 execl()

+
+Les primitives exec constituent une famille de primitives permettant +le lancement de l’exécution d’un nouveau programme par le processus appelant. +Cela n’entraîne pas la création d’un nouveau processus mais seulement le chargement et +le lancement d’un nouveau programme exécutable, en lieu et place du programme effectuant +l’appel à la primitive exec. +

On parle de recouvrement : +le nouveau programme recouvre (remplace complètement) le processus appelant. +

+int execl(char *ref, char *arg0, char *arg1,..., char *argn, NULL) +

+

+int execlp(char *ref, char *arg0, char *arg1,..., char *argn, NULL) +

+permettent le lancement de l’exécution du fichier exécutable dont : +

    +
  • +le nom est indiqué par le premier paramètre "ref" +
  • +
  • +la liste des arguments fournie dans "arg0", "arg1",…,"argn" +
  • +
+

execlp effectue une recherche de l'exécutable dans tous les répertoires de PATH. +

+ref doit référencer un fichier qui existe et qui est exécutable. +Le paramètre "arg0" est obligatoire et pointe en général sur une chaîne +identique à celle pointée par "ref". +

+Le comportement de la primitive execl est le suivant : +

    +
  • +si l'exécutable référencé par ref existe, il sera chargé et lancé en +en lieu et place du processus courant, sans aucun retour dans ce dernier. +
  • +
  • +sinon, on continue à exécuter le code du processus appelant, et dans ce cas il faut traiter +l'erreur. +
  • +
+

+On reprend l'exempe initial, et on : +

    +
  • +remplace dans les fils, l'appel à "sleep()" par l'exécution +du programme "dormir" qui fait la même chose. +
  • +
  • +introduit une petite erreur dans le nom de l'exécutable pour le fils 2 +
  • +
  • +ajoute dans le père une boucle d'attente de la terminaison des 3 fils, +en affichant pour chacun le mode d'arrêt et la valeur correspondante +
  • +
+Ce qui donne le code ci-dessous. +

+

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* execl */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 #include <sys/wait.h> /* wait */
+  8 
+  9 #define NB_FILS 3     /* nombre de fils */
+ 10 
+ 11 int main()
+ 12 {
+ 13     int fils, retour, wstatus, fils_termine ;
+ 14 
+ 15     char ref_exec[]="./dormir" ; /* exécutable  */
+ 16     char arg0_exec[]="je dors" ;   /* argument0 du exec : nom donnée au processus */
+ 17     char arg1_exec[]="3" ;       /* argument0 du exec : durée de sommeil */
+ 18 
+ 19     printf("Je suis le processus principal de pid %d\n", getpid()) ;
+ 20     /* Vidange du tampon de sortie pour que le fils le récupère vide        */
+ 21     fflush(stdout) ;
+ 22 
+ 23     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 24         retour = fork() ;
+ 25 
+ 26         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 27         if (retour < 0) {   /* échec du fork */
+ 28             printf("Erreur fork\n") ;
+ 29             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 30             exit(1) ;
+ 31         }
+ 32 
+ 33         /* fils */
+ 34         if (retour == 0) {
+ 35 
+ 36          /* mettre un executable inexistant pour le fils 2 */
+ 37             if (fils == 2) {
+ 38                 ref_exec[3] = 'a' ;
+ 39             }
+ 40 
+ 41             execl(ref_exec, arg0_exec, arg1_exec, NULL) ;
+ 42 
+ 43             /* on ne se retrouve ici que si exec échoue */
+ 44             printf("\n     Processus fils numero %d : ERREUR EXEC\n", fils) ;
+ 45             /* perror : affiche un message relatif à l'erreur du dernier appel systàme */
+ 46             perror("     exec ") ;
+ 47             exit(fils) ;   /* sortie avec le numéro di fils qui a échoué */ 
+ 48         }
+ 49         /* pere */
+ 50         else {
+ 51             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 52                     getpid(), fils, retour) ;
+ 53             fflush(stdout) ;
+ 54         }
+ 55     }
+ 56     sleep(3) ;   /* pour les besoins de l'outil de validation automatique */
+ 57 
+ 58     /* attendre la fin des fils */
+ 59     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 60         /* attendre la fin d'un fils */
+ 61         fils_termine = wait(&wstatus) ;
+ 62 
+ 63         if WIFEXITED(wstatus) {   /* fils terminé avec exit */
+ 64             printf("\nMon fils de pid %d a termine avec exit %d\n", 
+ 65                     fils_termine, WEXITSTATUS(wstatus)) ;
+ 66         }
+ 67         else if WIFSIGNALED(wstatus) {  /* fils tué par un signal */
+ 68             printf("\nMon fils de pid %d a ete tue par le signal %d\n", 
+ 69                     fils_termine, WTERMSIG(wstatus)) ;
+ 70         }
+ 71     }
+ 72     printf("\nProcessus Principal termine\n") ;
+ 73     return EXIT_SUCCESS ;
+ 74 }
+
+ +

+Testez ce code dans l'outil "apisys" (comme indiqué plus haut), et répondez aux questions posées. +

Visualiser l'interprétation des résultats

+ + +
+
+ +
+

1.12 execv()

+
+ +

+int execv(char *ref, char *argv[]) +

+permet le lancement de l’exécution du fichier exécutable dont le nom est "ref", +avec comme arguments les chaînes pointées par argv[0], +

argv[1],...,argv[n]. argv[n+1] doit être contenir "NULL". +

Le code suivant reprend le code précédent en remplaçant l'appel à + execl par execv, et en utilisant un tableau de pointeurs sur les +arguments du exec. +

Contrairement au code précédent, on uilise ici la même référence pour +les paramètres "ref" et argv[0](ce qui est souvent le cas). +

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* execv */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 #include <sys/wait.h> /* wait */
+  8 #include <string.h>   /* opérations sur les chaines */
+  9 
+ 10 #define NB_FILS 3     /* nombre de fils */
+ 11 
+ 12 int main()
+ 13 {
+ 14     int fils, retour, wstatus, fils_termine ;
+ 15 
+ 16     char *argv[8] ;               /* tableau de pointeurs sur les arguments du exec */
+ 17     char args_exec[8][16] ;         /* tableau des arguments du exec */
+ 18     strcpy(args_exec[0], "./dormir") ;   /* arg0 */
+ 19     argv[0] = args_exec[0] ;         /* ponteur sur arg0 */
+ 20     strcpy(args_exec[1], "3") ;      /* arg1 : durée de sommeil */
+ 21     argv[1] = args_exec[1] ;         /* ponteur sur arg1 */
+ 22     argv[2] = NULL ;               /* dernier pointeur = NULL */
+ 23 
+ 24     printf("Je suis le processus principal de pid %d\n", getpid()) ;
+ 25     /* Vidange du tampon de sortie pour que le fils le récupère vide        */
+ 26     fflush(stdout) ;
+ 27 
+ 28     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 29         retour = fork() ;
+ 30 
+ 31         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 32         if (retour < 0) {   /* échec du fork */
+ 33             printf("Erreur fork\n") ;
+ 34             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 35             exit(1) ;
+ 36         }
+ 37 
+ 38         /* fils */
+ 39         if (retour == 0) {
+ 40 
+ 41             /* mettre un executable inexistant pour le fils 2 */
+ 42             if (fils == 2) {
+ 43                 args_exec[0][3] = 'a' ;
+ 44             }
+ 45 
+ 46             execv(argv[0], argv) ;   /* argv[0] utilisé comme nom de l'exécutable */
+ 47 
+ 48             /* on ne se retrouve ici que si exec échoue */
+ 49             printf("\n     Processus fils numero %d : ERREUR EXEC\n", fils) ;
+ 50             /* perror : affiche un message relatif à l'erreur du dernier appel systàme */
+ 51             perror("     exec ") ;
+ 52             exit(fils) ;   /* sortie avec le numéro di fils qui a échoué */ 
+ 53         }
+ 54         /* pere */
+ 55         else {
+ 56             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 57                     getpid(), fils, retour) ;
+ 58             fflush(stdout) ;
+ 59         }
+ 60     }
+ 61     sleep(3) ;   /* pour les besoins de l'outil de validation automatique */
+ 62 
+ 63     /* attendre la fin des fils */
+ 64     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 65         /* attendre la fin d'un fils */
+ 66         fils_termine = wait(&wstatus) ;
+ 67 
+ 68         if WIFEXITED(wstatus) {   /* fils terminé avec exit */
+ 69             printf("\nMon fils de pid %d a termine avec exit %d\n", 
+ 70                     fils_termine, WEXITSTATUS(wstatus)) ;
+ 71         }
+ 72         else if WIFSIGNALED(wstatus) {  /* fils tué par un signal */
+ 73             printf("\nMon fils de pid %d a ete tue par le signal %d\n", 
+ 74                     fils_termine, WTERMSIG(wstatus)) ;
+ 75         }
+ 76     }
+ 77     printf("\nProcessus Principal termine\n") ;
+ 78     return EXIT_SUCCESS ;
+ 79 }
+
+

+Dans les deux versions précédentes, le fichier exécutable est trouvé grâce à son chemin +complet (./dormir). +

+execlp et execvp sont deux variantes de respectivement execl et execv, mais avec +recherche du fichier exécutable dans la liste des répertoires contenue dans la variable PATH. +

+
+
+

1.13 Conservation des descripteurs

+
+Les descripteurs ouverts avant l'appel à une primitive exec +le restent, et sont donc accessibles par l'exécutable lancé avec exec. +

+On peut illustrer cela en exécutant l'avant dernier programme en redirigeant +la sortie standard dans un fichier. +

+Mais l'appel à execl écrase le tampon de sortie ; ce qui induit un +risque de perte d’information. Par exemple, si on introduit, dans le +fils, l'affichage d'un message avant l'appel à execl, ce message risque +de ne pas s'afficher s'il ne se +termine pas avec '\n' ou si l'exécution se fait avec redirection. +

+Pour forcer le vidage de ce tampon avant l’appel à execl on utilise la fonction fflush() de la bibliothèque standard stdio.h. +

+Ce qui donne le code suivant : +

+

  1 /* Exemple d'illustration des primitives Unix : Un père et ses fils */
+  2 /* execl et fflush */
+  3 
+  4 #include <stdio.h>    /* entrées sorties */
+  5 #include <unistd.h>   /* pimitives de base : fork, ...*/
+  6 #include <stdlib.h>   /* exit */
+  7 #include <sys/wait.h> /* wait */
+  8 
+  9 #define NB_FILS 3     /* nombre de fils */
+ 10 
+ 11 int main()
+ 12 {
+ 13     int fils, retour, wstatus, fils_termine ;
+ 14 
+ 15     char ref_exec[]="./dormir" ; /* exécutable  */
+ 16     char arg0_exec[]="je dors" ;   /* argument0 du exec : nom donnée au processus */
+ 17     char arg1_exec[]="3" ;       /* argument0 du exec : durée de sommeil */
+ 18 
+ 19     printf("Je suis le processus principal de pid %d\n", getpid()) ;
+ 20     /* Vidange du tampon de sortie pour que le fils le récupère vide        */
+ 21     fflush(stdout) ;
+ 22 
+ 23     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 24         retour = fork() ;
+ 25 
+ 26         /* Bonne pratique : tester systématiquement le retour des appels système */
+ 27         if (retour < 0) {   /* échec du fork */
+ 28             printf("Erreur fork\n") ;
+ 29             /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */
+ 30             exit(1) ;
+ 31         }
+ 32 
+ 33         /* fils */
+ 34         if (retour == 0) {
+ 35             printf("\n     Processus fils numero %d, de pid %d, de pere %d.\n", 
+ 36                     fils, getpid(), getppid()) ;
+ 37 
+ 38             /* Précaution en cas d'une exécution avec redirection :                 */
+ 39             /* Vidange du tampon de sortie avant qu'il ne soit écrasé par exec      */
+ 40             /* D'après le standard ISO le comportement du printf présente 2 cas :   */
+ 41             /* - sortie interactive (terminal) : flot géré par ligne et \n provoque */
+ 42             /*   la vidange du tampon langage */
+ 43             /* - sortie dans un fichier : flot géré par bloc et \n est traité comme */
+ 44             /*   un caractère ordinaire. fflush(stdout) force la vidange du tampon. */
+ 45             fflush(stdout) ;
+ 46 
+ 47          /* executable inexistant pour le fils 2 */
+ 48             if (fils == 2) {
+ 49                 ref_exec[3] = 'a' ;
+ 50             }
+ 51 
+ 52             execl(ref_exec, arg0_exec, arg1_exec, NULL) ;
+ 53 
+ 54             /* on ne se retrouve ici que si exec échoue */
+ 55             printf("\n     Processus fils numero %d : ERREUR EXEC\n", fils) ;
+ 56             /* perror : affiche un message relatif à l'erreur du dernier appel systàme */
+ 57             perror("     exec ") ;
+ 58             exit(fils) ;   /* sortie avec le numéro di fils qui a échoué */ 
+ 59         }
+ 60         /* pere */
+ 61         else {
+ 62             printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", 
+ 63                     getpid(), fils, retour) ;
+ 64             fflush(stdout) ;
+ 65         }
+ 66     }
+ 67     sleep(3) ;   /* pour les besoins de l'outil de validation automatique */
+ 68 
+ 69     /* attendre la fin des fils */
+ 70     for (fils = 1 ; fils <= NB_FILS ; fils++) {
+ 71         /* attendre la fin d'un fils */
+ 72         fils_termine = wait(&wstatus) ;
+ 73 
+ 74         if WIFEXITED(wstatus) {   /* fils terminé avec exit */
+ 75             printf("\nMon fils de pid %d a termine avec exit %d\n", 
+ 76                     fils_termine, WEXITSTATUS(wstatus)) ;
+ 77         }
+ 78         else if WIFSIGNALED(wstatus) {  /* fils tué par un signal */
+ 79             printf("\nMon fils de pid %d a ete tue par le signal %d\n", 
+ 80                     fils_termine, WTERMSIG(wstatus)) ;
+ 81         }
+ 82     }
+ 83     printf("\nProcessus Principal termine\n") ;
+ 84     return EXIT_SUCCESS ;
+ 85 }
+
+ +
+
+ +
+
+ + + + + + +
+ + + + \ No newline at end of file diff --git a/TP1/processus_files/jquery.js b/TP1/processus_files/jquery.js new file mode 100644 index 0000000..c941a5f --- /dev/null +++ b/TP1/processus_files/jquery.js @@ -0,0 +1,166 @@ +/*! + * jQuery JavaScript Library v1.4.3 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Oct 14 23:10:06 2010 -0400 + */ +(function(E,A){function U(){return false}function ba(){return true}function ja(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ga(a){var b,d,e=[],f=[],h,k,l,n,s,v,B,D;k=c.data(this,this.nodeType?"events":"__events__");if(typeof k==="function")k=k.events;if(!(a.liveFired===this||!k||!k.live||a.button&&a.type==="click")){if(a.namespace)D=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var H=k.live.slice(0);for(n=0;nd)break;a.currentTarget=f.elem;a.data=f.handleObj.data; +a.handleObj=f.handleObj;D=f.handleObj.origHandler.apply(f.elem,arguments);if(D===false||a.isPropagationStopped()){d=f.level;if(D===false)b=false}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(Ha,"`").replace(Ia,"&")}function ka(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Ja.test(b))return c.filter(b, +e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function la(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var k in e[h])c.event.add(this,h,e[h][k],e[h][k].data)}}})}function Ka(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)} +function ma(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?La:Ma,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function ca(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Na.test(a)?e(a,h):ca(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)? +e(a,""):c.each(b,function(f,h){ca(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(na.concat.apply([],na.slice(0,b)),function(){d[this]=a});return d}function oa(a){if(!da[a]){var b=c("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";da[a]=d}return da[a]}function ea(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var u=E.document,c=function(){function a(){if(!b.isReady){try{u.documentElement.doScroll("left")}catch(i){setTimeout(a, +1);return}b.ready()}}var b=function(i,r){return new b.fn.init(i,r)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,k=/\S/,l=/^\s+/,n=/\s+$/,s=/\W/,v=/\d/,B=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,D=/^[\],:{}\s]*$/,H=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,G=/(?:^|:|,)(?:\s*\[)+/g,M=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,j=/(msie) ([\w.]+)/,o=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false, +q=[],t,x=Object.prototype.toString,C=Object.prototype.hasOwnProperty,P=Array.prototype.push,N=Array.prototype.slice,R=String.prototype.trim,Q=Array.prototype.indexOf,L={};b.fn=b.prototype={init:function(i,r){var y,z,F;if(!i)return this;if(i.nodeType){this.context=this[0]=i;this.length=1;return this}if(i==="body"&&!r&&u.body){this.context=u;this[0]=u.body;this.selector="body";this.length=1;return this}if(typeof i==="string")if((y=h.exec(i))&&(y[1]||!r))if(y[1]){F=r?r.ownerDocument||r:u;if(z=B.exec(i))if(b.isPlainObject(r)){i= +[u.createElement(z[1])];b.fn.attr.call(i,r,true)}else i=[F.createElement(z[1])];else{z=b.buildFragment([y[1]],[F]);i=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,i)}else{if((z=u.getElementById(y[2]))&&z.parentNode){if(z.id!==y[2])return f.find(i);this.length=1;this[0]=z}this.context=u;this.selector=i;return this}else if(!r&&!s.test(i)){this.selector=i;this.context=u;i=u.getElementsByTagName(i);return b.merge(this,i)}else return!r||r.jquery?(r||f).find(i):b(r).find(i); +else if(b.isFunction(i))return f.ready(i);if(i.selector!==A){this.selector=i.selector;this.context=i.context}return b.makeArray(i,this)},selector:"",jquery:"1.4.3",length:0,size:function(){return this.length},toArray:function(){return N.call(this,0)},get:function(i){return i==null?this.toArray():i<0?this.slice(i)[0]:this[i]},pushStack:function(i,r,y){var z=b();b.isArray(i)?P.apply(z,i):b.merge(z,i);z.prevObject=this;z.context=this.context;if(r==="find")z.selector=this.selector+(this.selector?" ": +"")+y;else if(r)z.selector=this.selector+"."+r+"("+y+")";return z},each:function(i,r){return b.each(this,i,r)},ready:function(i){b.bindReady();if(b.isReady)i.call(u,b);else q&&q.push(i);return this},eq:function(i){return i===-1?this.slice(i):this.slice(i,+i+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(i){return this.pushStack(b.map(this,function(r,y){return i.call(r, +y,r)}))},end:function(){return this.prevObject||b(null)},push:P,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var i=arguments[0]||{},r=1,y=arguments.length,z=false,F,I,K,J,fa;if(typeof i==="boolean"){z=i;i=arguments[1]||{};r=2}if(typeof i!=="object"&&!b.isFunction(i))i={};if(y===r){i=this;--r}for(;r0)){if(q){for(var r=0;i=q[r++];)i.call(u,b);q=null}b.fn.triggerHandler&&b(u).triggerHandler("ready")}}},bindReady:function(){if(!p){p=true;if(u.readyState==="complete")return setTimeout(b.ready, +1);if(u.addEventListener){u.addEventListener("DOMContentLoaded",t,false);E.addEventListener("load",b.ready,false)}else if(u.attachEvent){u.attachEvent("onreadystatechange",t);E.attachEvent("onload",b.ready);var i=false;try{i=E.frameElement==null}catch(r){}u.documentElement.doScroll&&i&&a()}}},isFunction:function(i){return b.type(i)==="function"},isArray:Array.isArray||function(i){return b.type(i)==="array"},isWindow:function(i){return i&&typeof i==="object"&&"setInterval"in i},isNaN:function(i){return i== +null||!v.test(i)||isNaN(i)},type:function(i){return i==null?String(i):L[x.call(i)]||"object"},isPlainObject:function(i){if(!i||b.type(i)!=="object"||i.nodeType||b.isWindow(i))return false;if(i.constructor&&!C.call(i,"constructor")&&!C.call(i.constructor.prototype,"isPrototypeOf"))return false;for(var r in i);return r===A||C.call(i,r)},isEmptyObject:function(i){for(var r in i)return false;return true},error:function(i){throw i;},parseJSON:function(i){if(typeof i!=="string"||!i)return null;i=b.trim(i); +if(D.test(i.replace(H,"@").replace(w,"]").replace(G,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(i):(new Function("return "+i))();else b.error("Invalid JSON: "+i)},noop:function(){},globalEval:function(i){if(i&&k.test(i)){var r=u.getElementsByTagName("head")[0]||u.documentElement,y=u.createElement("script");y.type="text/javascript";if(b.support.scriptEval)y.appendChild(u.createTextNode(i));else y.text=i;r.insertBefore(y,r.firstChild);r.removeChild(y)}},nodeName:function(i,r){return i.nodeName&&i.nodeName.toUpperCase()=== +r.toUpperCase()},each:function(i,r,y){var z,F=0,I=i.length,K=I===A||b.isFunction(i);if(y)if(K)for(z in i){if(r.apply(i[z],y)===false)break}else for(;F";a=u.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var s=u.createElement("div"); +s.style.width=s.style.paddingLeft="1px";u.body.appendChild(s);c.boxModel=c.support.boxModel=s.offsetWidth===2;if("zoom"in s.style){s.style.display="inline";s.style.zoom=1;c.support.inlineBlockNeedsLayout=s.offsetWidth===2;s.style.display="";s.innerHTML="
";c.support.shrinkWrapBlocks=s.offsetWidth!==2}s.innerHTML="
t
";var v=s.getElementsByTagName("td");c.support.reliableHiddenOffsets=v[0].offsetHeight=== +0;v[0].style.display="";v[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&v[0].offsetHeight===0;s.innerHTML="";u.body.removeChild(s).style.display="none"});a=function(s){var v=u.createElement("div");s="on"+s;var B=s in v;if(!B){v.setAttribute(s,"return;");B=typeof v[s]==="function"}return B};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength", +cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var pa={},Oa=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?pa:a;var e=a.nodeType,f=e?a[c.expando]:null,h=c.cache;if(!(e&&!f&&typeof b==="string"&&d===A)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]= +c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==A)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?pa:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);else if(d)delete f[e];else for(var k in a)delete a[k]}},acceptData:function(a){if(a.nodeName){var b= +c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){if(typeof a==="undefined")return this.length?c.data(this[0]):null;else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===A){var e=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(e===A&&this.length){e=c.data(this[0],a);if(e===A&&this[0].nodeType===1){e=this[0].getAttribute("data-"+a);if(typeof e=== +"string")try{e=e==="true"?true:e==="false"?false:e==="null"?null:!c.isNaN(e)?parseFloat(e):Oa.test(e)?c.parseJSON(e):e}catch(f){}else e=A}}return e===A&&d[1]?this.data(d[0]):e}else return this.each(function(){var h=c(this),k=[d[0],b];h.triggerHandler("setData"+d[1]+"!",k);c.data(this,a,b);h.triggerHandler("changeData"+d[1]+"!",k)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=c.data(a,b);if(!d)return e|| +[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===A)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this, +a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var qa=/[\n\t]/g,ga=/\s+/,Pa=/\r/g,Qa=/^(?:href|src|style)$/,Ra=/^(?:button|input)$/i,Sa=/^(?:button|input|object|select|textarea)$/i,Ta=/^a(?:rea)?$/i,ra=/^(?:radio|checkbox)$/i;c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this, +a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(s){var v=c(this);v.addClass(a.call(this,s,v.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ga),d=0,e=this.length;d-1)return true;return false}, +val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var B=c.makeArray(v);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),B)>=0});if(!B.length)this.selectedIndex=-1}else this.value=v}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return A;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==A;b=e&&c.props[b]||b;if(a.nodeType===1){var h=Qa.test(b);if((b in a||a[b]!==A)&&e&&!h){if(f){b==="type"&&Ra.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Sa.test(a.nodeName)||Ta.test(a.nodeName)&&a.href?0:A;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return A;a=!c.support.hrefNormalized&&e&& +h?a.getAttribute(b,2):a.getAttribute(b);return a===null?A:a}}});var X=/\.(.*)$/,ha=/^(?:textarea|input|select)$/i,Ha=/\./g,Ia=/ /g,Ua=/[^\w\s.|`]/g,Va=function(a){return a.replace(Ua,"\\$&")},sa={focusin:0,focusout:0};c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var k=a.nodeType?"events":"__events__",l=h[k],n=h.handle;if(typeof l=== +"function"){n=l.handle;l=l.events}else if(!l){a.nodeType||(h[k]=h=function(){});h.events=l={}}if(!n)h.handle=n=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(n.elem,arguments):A};n.elem=a;b=b.split(" ");for(var s=0,v;k=b[s++];){h=f?c.extend({},f):{handler:d,data:e};if(k.indexOf(".")>-1){v=k.split(".");k=v.shift();h.namespace=v.slice(0).sort().join(".")}else{v=[];h.namespace=""}h.type=k;if(!h.guid)h.guid=d.guid;var B=l[k],D=c.event.special[k]||{};if(!B){B=l[k]=[]; +if(!D.setup||D.setup.call(a,e,v,n)===false)if(a.addEventListener)a.addEventListener(k,n,false);else a.attachEvent&&a.attachEvent("on"+k,n)}if(D.add){D.add.call(a,h);if(!h.handler.guid)h.handler.guid=d.guid}B.push(h);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,k=0,l,n,s,v,B,D,H=a.nodeType?"events":"__events__",w=c.data(a),G=w&&w[H];if(w&&G){if(typeof G==="function"){w=G;G=G.events}if(b&&b.type){d=b.handler;b=b.type}if(!b|| +typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in G)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[k++];){v=f;l=f.indexOf(".")<0;n=[];if(!l){n=f.split(".");f=n.shift();s=RegExp("(^|\\.)"+c.map(n.slice(0).sort(),Va).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(B=G[f])if(d){v=c.event.special[f]||{};for(h=e||0;h=0){a.type= +f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return A;a.result=A;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)=== +false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){e=a.target;var k,l=f.replace(X,""),n=c.nodeName(e,"a")&&l==="click",s=c.event.special[l]||{};if((!s._default||s._default.call(d,a)===false)&&!n&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[l]){if(k=e["on"+l])e["on"+l]=null;c.event.triggered=true;e[l]()}}catch(v){}if(k)e["on"+l]=k;c.event.triggered=false}}},handle:function(a){var b,d,e; +d=[];var f,h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var k=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ha.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=va(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===A||f===e))if(e!=null||f){a.type="change";a.liveFired= +A;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",va(a))}},setup:function(){if(this.type=== +"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ha.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ha.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}u.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){sa[b]++===0&&u.addEventListener(a,d,true)},teardown:function(){--sa[b]=== +0&&u.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=A}var k=b==="one"?c.proxy(f,function(n){c(this).unbind(n,k);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var l=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g,j,o,m,p,q){p=0;for(var t=m.length;p0){C=x;break}}x=x[g]}m[p]=C}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,k=true;[0,0].sort(function(){k=false;return 0});var l=function(g,j,o,m){o=o||[];var p=j=j||u;if(j.nodeType!==1&&j.nodeType!==9)return[];if(!g||typeof g!=="string")return o;var q=[],t,x,C,P,N=true,R=l.isXML(j),Q=g,L;do{d.exec("");if(t=d.exec(Q)){Q=t[3];q.push(t[1]);if(t[2]){P=t[3]; +break}}}while(t);if(q.length>1&&s.exec(g))if(q.length===2&&n.relative[q[0]])x=M(q[0]+q[1],j);else for(x=n.relative[q[0]]?[j]:l(q.shift(),j);q.length;){g=q.shift();if(n.relative[g])g+=q.shift();x=M(g,x)}else{if(!m&&q.length>1&&j.nodeType===9&&!R&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){t=l.find(q.shift(),j,R);j=t.expr?l.filter(t.expr,t.set)[0]:t.set[0]}if(j){t=m?{expr:q.pop(),set:D(m)}:l.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&j.parentNode?j.parentNode:j,R);x=t.expr?l.filter(t.expr, +t.set):t.set;if(q.length>0)C=D(x);else N=false;for(;q.length;){t=L=q.pop();if(n.relative[L])t=q.pop();else L="";if(t==null)t=j;n.relative[L](C,t,R)}}else C=[]}C||(C=x);C||l.error(L||g);if(f.call(C)==="[object Array]")if(N)if(j&&j.nodeType===1)for(g=0;C[g]!=null;g++){if(C[g]&&(C[g]===true||C[g].nodeType===1&&l.contains(j,C[g])))o.push(x[g])}else for(g=0;C[g]!=null;g++)C[g]&&C[g].nodeType===1&&o.push(x[g]);else o.push.apply(o,C);else D(C,o);if(P){l(P,p,o,m);l.uniqueSort(o)}return o};l.uniqueSort=function(g){if(w){h= +k;g.sort(w);if(h)for(var j=1;j0};l.find=function(g,j,o){var m;if(!g)return[];for(var p=0,q=n.order.length;p":function(g,j){var o=typeof j==="string",m,p=0,q=g.length;if(o&&!/\W/.test(j))for(j=j.toLowerCase();p=0))o||m.push(t);else if(o)j[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var j=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=j[1]+(j[2]||1)-0;g[3]=j[3]-0}g[0]=e++;return g},ATTR:function(g,j,o, +m,p,q){j=g[1].replace(/\\/g,"");if(!q&&n.attrMap[j])g[1]=n.attrMap[j];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,j,o,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=l(g[3],null,null,j);else{g=l.filter(g[3],j,o,true^p);o||m.push.apply(m,g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== +true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,j,o){return!!l(o[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== +g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,j){return j===0},last:function(g,j,o,m){return j===m.length-1},even:function(g,j){return j%2===0},odd:function(g,j){return j%2===1},lt:function(g,j,o){return jo[3]-0},nth:function(g,j,o){return o[3]- +0===j},eq:function(g,j,o){return o[3]-0===j}},filter:{PSEUDO:function(g,j,o,m){var p=j[1],q=n.filters[p];if(q)return q(g,o,j,m);else if(p==="contains")return(g.textContent||g.innerText||l.getText([g])||"").indexOf(j[3])>=0;else if(p==="not"){j=j[3];o=0;for(m=j.length;o=0}},ID:function(g,j){return g.nodeType===1&&g.getAttribute("id")===j},TAG:function(g,j){return j==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== +j},CLASS:function(g,j){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(j)>-1},ATTR:function(g,j){var o=j[1];o=n.attrHandle[o]?n.attrHandle[o](g):g[o]!=null?g[o]:g.getAttribute(o);var m=o+"",p=j[2],q=j[4];return o==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&o!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,j,o,m){var p=n.setFilters[j[2]]; +if(p)return p(g,o,j,m)}}},s=n.match.POS,v=function(g,j){return"\\"+(j-0+1)},B;for(B in n.match){n.match[B]=RegExp(n.match[B].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[B]=RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[B].source.replace(/\\(\d+)/g,v))}var D=function(g,j){g=Array.prototype.slice.call(g,0);if(j){j.push.apply(j,g);return j}return g};try{Array.prototype.slice.call(u.documentElement.childNodes,0)}catch(H){D=function(g,j){var o=j||[],m=0;if(f.call(g)==="[object Array]")Array.prototype.push.apply(o, +g);else if(typeof g.length==="number")for(var p=g.length;m";var o=u.documentElement;o.insertBefore(g,o.firstChild);if(u.getElementById(j)){n.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:A:[]};n.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}o.removeChild(g); +o=g=null})();(function(){var g=u.createElement("div");g.appendChild(u.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(j,o){var m=o.getElementsByTagName(j[1]);if(j[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(j){return j.getAttribute("href",2)};g=null})();u.querySelectorAll&& +function(){var g=l,j=u.createElement("div");j.innerHTML="

";if(!(j.querySelectorAll&&j.querySelectorAll(".TEST").length===0)){l=function(m,p,q,t){p=p||u;if(!t&&!l.isXML(p))if(p.nodeType===9)try{return D(p.querySelectorAll(m),q)}catch(x){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var C=p.id,P=p.id="__sizzle__";try{return D(p.querySelectorAll("#"+P+" "+m),q)}catch(N){}finally{if(C)p.id=C;else p.removeAttribute("id")}}return g(m,p,q,t)};for(var o in g)l[o]=g[o]; +j=null}}();(function(){var g=u.documentElement,j=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,o=false;try{j.call(u.documentElement,":sizzle")}catch(m){o=true}if(j)l.matchesSelector=function(p,q){try{if(o||!n.match.PSEUDO.test(q))return j.call(p,q)}catch(t){}return l(q,null,null,[p]).length>0}})();(function(){var g=u.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length=== +0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(j,o,m){if(typeof o.getElementsByClassName!=="undefined"&&!m)return o.getElementsByClassName(j[1])};g=null}}})();l.contains=u.documentElement.contains?function(g,j){return g!==j&&(g.contains?g.contains(j):true)}:function(g,j){return!!(g.compareDocumentPosition(j)&16)};l.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var M=function(g, +j){for(var o=[],m="",p,q=j.nodeType?[j]:j;p=n.match.PSEUDO.exec(g);){m+=p[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;p=0;for(var t=q.length;p0)for(var h=d;h0},closest:function(a, +b){var d=[],e,f,h=this[0];if(c.isArray(a)){var k={},l,n=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:n})}h=h.parentNode;n++}}return d}k=$a.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h|| +!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}}); +c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling", +d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Wa.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||Ya.test(e))&&Xa.test(a))f=f.reverse();return this.pushStack(f,a,Za.call(arguments).join(","))}}); +c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===A||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var xa=/ jQuery\d+="(?:\d+|null)"/g, +$=/^\s+/,ya=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,za=/<([\w:]+)/,ab=/\s]+\/)>/g,O={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"], +area:[1,"",""],_default:[0,"",""]};O.optgroup=O.option;O.tbody=O.tfoot=O.colgroup=O.caption=O.thead;O.th=O.td;if(!c.support.htmlSerialize)O._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==A)return this.empty().append((this[0]&&this[0].ownerDocument||u).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this, +d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})}, +unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a= +c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*")); +c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(xa,"").replace(cb,'="$1">').replace($, +"")],e)[0]}else return this.cloneNode(true)});if(a===true){la(this,b);la(this.find("*"),b.find("*"))}return b},html:function(a){if(a===A)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(xa,""):null;else if(typeof a==="string"&&!Aa.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!O[(za.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ya,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?l.cloneNode(true):l)}k.length&&c.each(k,Ka)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:u;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===u&&!Aa.test(a[0])&&(c.support.checkClone|| +!Ba.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h= +d.length;f0?this.clone(true):this).get();c(d[f])[b](k);e=e.concat(k)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||u;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||u;for(var f=[],h=0,k;(k=a[h])!=null;h++){if(typeof k==="number")k+="";if(k){if(typeof k==="string"&&!bb.test(k))k=b.createTextNode(k);else if(typeof k==="string"){k=k.replace(ya,"<$1>");var l=(za.exec(k)||["",""])[1].toLowerCase(),n=O[l]||O._default, +s=n[0],v=b.createElement("div");for(v.innerHTML=n[1]+k+n[2];s--;)v=v.lastChild;if(!c.support.tbody){s=ab.test(k);l=l==="table"&&!s?v.firstChild&&v.firstChild.childNodes:n[1]===""&&!s?v.childNodes:[];for(n=l.length-1;n>=0;--n)c.nodeName(l[n],"tbody")&&!l[n].childNodes.length&&l[n].parentNode.removeChild(l[n])}!c.support.leadingWhitespace&&$.test(k)&&v.insertBefore(b.createTextNode($.exec(k)[0]),v.firstChild);k=v.childNodes}if(k.nodeType)f.push(k);else f=c.merge(f,k)}}if(d)for(h=0;f[h];h++)if(e&& +c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,k=0,l;(l=a[k])!=null;k++)if(!(l.nodeName&&c.noData[l.nodeName.toLowerCase()]))if(d=l[c.expando]){if((b=e[d])&&b.events)for(var n in b.events)f[n]? +c.event.remove(l,n):c.removeEvent(l,n,b.handle);if(h)delete l[c.expando];else l.removeAttribute&&l.removeAttribute(c.expando);delete e[d]}}});var Ca=/alpha\([^)]*\)/i,db=/opacity=([^)]*)/,eb=/-([a-z])/ig,fb=/([A-Z])/g,Da=/^-?\d+(?:px)?$/i,gb=/^-?\d/,hb={position:"absolute",visibility:"hidden",display:"block"},La=["Left","Right"],Ma=["Top","Bottom"],W,ib=u.defaultView&&u.defaultView.getComputedStyle,jb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===A)return this; +return c.access(this,a,b,true,function(d,e,f){return f!==A?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),k=a.style,l=c.cssHooks[h];b=c.cssProps[h]|| +h;if(d!==A){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!l||!("set"in l)||(d=l.set(a,d))!==A)try{k[b]=d}catch(n){}}}else{if(l&&"get"in l&&(f=l.get(a,false,e))!==A)return f;return k[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==A)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]= +e[f]},camelCase:function(a){return a.replace(eb,jb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=ma(d,b,f);else c.swap(d,hb,function(){h=ma(d,b,f)});return h+"px"}},set:function(d,e){if(Da.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return db.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"": +b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=d.filter||"";d.filter=Ca.test(f)?f.replace(Ca,e):d.filter+" "+e}};if(ib)W=function(a,b,d){var e;d=d.replace(fb,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return A;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};else if(u.documentElement.currentStyle)W=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b], +h=a.style;if(!Da.test(f)&&gb.test(f)){d=h.left;e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f};if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var kb=c.now(),lb=/)<[^<]*)*<\/script>/gi, +mb=/^(?:select|textarea)/i,nb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ob=/^(?:GET|HEAD|DELETE)$/,Na=/\[\]$/,T=/\=\?(&|$)/,ia=/\?/,pb=/([?&])_=[^&]*/,qb=/^(\w+:)?\/\/([^\/?#]+)/,rb=/%20/g,sb=/#.*$/,Ea=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ea)return Ea.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d= +b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(k,l){if(l==="success"||l==="notmodified")h.html(f?c("
").append(k.responseText.replace(lb,"")).find(f):k.responseText);d&&h.each(d,[k.responseText,l,k])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& +!this.disabled&&(this.checked||mb.test(this.nodeName)||nb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, +getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", +script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),k=ob.test(h);b.url=b.url.replace(sb,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ia.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| +!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+kb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var l=E[d];E[d]=function(m){f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);if(c.isFunction(l))l(m);else{E[d]=A;try{delete E[d]}catch(p){}}v&&v.removeChild(B)}}if(b.dataType==="script"&&b.cache===null)b.cache= +false;if(b.cache===false&&h==="GET"){var n=c.now(),s=b.url.replace(pb,"$1_="+n);b.url=s+(s===b.url?(ia.test(b.url)?"&":"?")+"_="+n:"")}if(b.data&&h==="GET")b.url+=(ia.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");n=(n=qb.exec(b.url))&&(n[1]&&n[1]!==location.protocol||n[2]!==location.host);if(b.dataType==="script"&&h==="GET"&&n){var v=u.getElementsByTagName("head")[0]||u.documentElement,B=u.createElement("script");if(b.scriptCharset)B.charset=b.scriptCharset;B.src= +b.url;if(!d){var D=false;B.onload=B.onreadystatechange=function(){if(!D&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){D=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);B.onload=B.onreadystatechange=null;v&&B.parentNode&&v.removeChild(B)}}}v.insertBefore(B,v.firstChild);return A}var H=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!k||a&&a.contentType)w.setRequestHeader("Content-Type", +b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}n||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(G){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& +c.triggerGlobal(b,"ajaxSend",[w,b]);var M=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){H||c.handleComplete(b,w,e,f);H=true;if(w)w.onreadystatechange=c.noop}else if(!H&&w&&(w.readyState===4||m==="timeout")){H=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| +c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&g.call&&g.call(w);M("abort")}}catch(j){}b.async&&b.timeout>0&&setTimeout(function(){w&&!H&&M("timeout")},b.timeout);try{w.send(k||b.data==null?null:b.data)}catch(o){c.handleError(b,w,null,o);c.handleComplete(b,w,e,f)}b.async||M();return w}},param:function(a,b){var d=[],e=function(h,k){k=c.isFunction(k)?k():k;d[d.length]=encodeURIComponent(h)+ +"="+encodeURIComponent(k)};if(b===A)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)ca(f,a[f],b,e);return d.join("&").replace(rb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",[b,a])},handleComplete:function(a, +b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),e=a.getResponseHeader("Etag"); +if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});if(E.ActiveXObject)c.ajaxSettings.xhr= +function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var da={},tb=/^(?:toggle|show|hide)$/,ub=/^([+\-]=)?([\d+.\-]+)(.*)$/,aa,na=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",3),a,b,d);else{a= +0;for(b=this.length;a=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, +d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* +Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(h){return f.step(h)} +this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var f=this;a=c.fx;e.elem=this.elem;if(e()&&c.timers.push(e)&&!aa)aa=setInterval(a.tick,a.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; +this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(l,n){f.style["overflow"+n]=h.overflow[l]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| +this.options.show)for(var k in this.options.curAnim)c.style(this.elem,k,this.options.orig[k]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= +c.timers,b=0;b-1;e={};var s={};if(n)s=f.position();k=n?s.top:parseInt(k,10)||0;l=n?s.left:parseInt(l,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+k;if(b.left!=null)e.left=b.left-h.left+l;"using"in b?b.using.call(a, +e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Fa.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||u.body;a&&!Fa.test(a.nodeName)&& +c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==A)return this.each(function(){if(h=ea(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=ea(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); +c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(h){var k=c(this);k[d](e.call(this,h,k[d]()))});return c.isWindow(f)?f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b]:f.nodeType===9?Math.max(f.documentElement["client"+ +b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]):e===A?parseFloat(c.css(f,d)):this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/TP2/.vscode/launch.json b/TP2/.vscode/launch.json new file mode 100644 index 0000000..f798eb3 --- /dev/null +++ b/TP2/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gcc - Build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}/${fileBasenameNoExtension}", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: gcc build active file", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/TP2/.vscode/tasks.json b/TP2/.vscode/tasks.json new file mode 100644 index 0000000..4956c3e --- /dev/null +++ b/TP2/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/TP2/TPsignaux.pdf b/TP2/TPsignaux.pdf new file mode 100644 index 0000000..9a0cf1e Binary files /dev/null and b/TP2/TPsignaux.pdf differ diff --git a/TP2/api_systeme/dormir.c b/TP2/api_systeme/dormir.c new file mode 100644 index 0000000..d643afd --- /dev/null +++ b/TP2/api_systeme/dormir.c @@ -0,0 +1,17 @@ +#include +#include +#include + +// dormir durant n secondes : n fournie en argument +// sinon n=5 par défault +int main(int argc, char* argv[]) +{ + int delai = 5; + if (argc > 1 ) { + delai = atoi(argv[1]); + } + printf("\n - Processus %d va dormir durant %d secondes\n", getpid(), delai); + sleep(delai); + fflush(stdout); + return 0; +} diff --git a/TP2/api_systeme/fic_centaines.txt b/TP2/api_systeme/fic_centaines.txt new file mode 100644 index 0000000..a89c82a --- /dev/null +++ b/TP2/api_systeme/fic_centaines.txt @@ -0,0 +1,11 @@ +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 diff --git a/TP2/api_systeme/pere_fils.c b/TP2/api_systeme/pere_fils.c new file mode 100644 index 0000000..4b513b9 --- /dev/null +++ b/TP2/api_systeme/pere_fils.c @@ -0,0 +1,50 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Création de fils : fork et exit */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* manipulation des chaines */ + +#define NB_FILS 3 /* nombre de fils */ + +int main(int argc, char *argv[]) +{ + int fils, retour; + int duree_sommeil = 3; + char progname[]="pere_fils.c"; + + if (argc > 1) { + write(atoi(argv[1]), progname, strlen(progname)); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil + 1); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_exec.c b/TP2/api_systeme/pere_fils_exec.c new file mode 100644 index 0000000..e7e3edc --- /dev/null +++ b/TP2/api_systeme/pere_fils_exec.c @@ -0,0 +1,74 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* execl */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, wstatus, fils_termine; + + char ref_exec[]="./dormir"; /* exécutable */ + char arg0_exec[]="dodo"; /* argument0 du exec : nom donnée au processus */ + char arg1_exec[]="10"; /* argument0 du exec : durée de sommeil */ + + printf("Je suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + + /* mettre un executable inexistant pour le fils 2 */ + if (fils == 2) { + ref_exec[3] = 'a'; + } + + execl(ref_exec, arg0_exec, arg1_exec, NULL); + + /* on ne se retrouve ici que si exec échoue */ + printf("\n Processus fils numero %d : ERREUR EXEC\n", fils); + /* perror : affiche un message relatif à l'erreur du dernier appel systàme */ + perror(" exec "); + exit(fils); /* sortie avec le numéro di fils qui a échoué */ + } + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + fflush(stdout); + } + } + sleep(3); /* pour les besoins de l'outil de validation automatique */ + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_fflush.c b/TP2/api_systeme/pere_fils_fflush.c new file mode 100644 index 0000000..6dabc85 --- /dev/null +++ b/TP2/api_systeme/pere_fils_fflush.c @@ -0,0 +1,55 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Redirection et fflush */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + /* D'après le standard ISO le comportement du printf présente 2 cas : */ + /* - sortie interactive (terminal) : flot géré par ligne et \n provoque */ + /* la vidange du tampon langage */ + /* - sortie dans un fichier : flot géré par bloc et \n est traité comme */ + /* un caractère ordinaire. fflush(stdout) force la vidange du tampon. */ + + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + /* vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_heritage.c b/TP2/api_systeme/pere_fils_heritage.c new file mode 100644 index 0000000..ac622fe --- /dev/null +++ b/TP2/api_systeme/pere_fils_heritage.c @@ -0,0 +1,51 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Héritage et dupplication des données */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 4 /* nombre de fils */ + +int main() +{ + int fils, retour; + int cagnotte, patrimoine_fils; + int duree_sommeil = 4; + cagnotte = 10000 * NB_FILS; + patrimoine_fils = cagnotte / NB_FILS; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + printf("Je dispose de %d Euros, que je partage entre mes futurs fils\n", cagnotte); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d : mon pere m'a offert %d Euros\n", + fils, patrimoine_fils); + patrimoine_fils = patrimoine_fils * (fils + 1); + sleep(duree_sommeil); + printf("\n Processus fils numero %d - j'ai augmente mon patrimoine a %d Euros\n", + fils, patrimoine_fils); + exit(EXIT_SUCCESS); /* Te:rminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil+1); + + printf("\nProcessus Principal - le patrimoine total de mes fils est de %d\n", patrimoine_fils*NB_FILS); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_orphelin.c b/TP2/api_systeme/pere_fils_orphelin.c new file mode 100644 index 0000000..9894904 --- /dev/null +++ b/TP2/api_systeme/pere_fils_orphelin.c @@ -0,0 +1,43 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fils orphelins */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + exit(EXIT_SUCCESS); /* Terminaison normale */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_sans_exit.c b/TP2/api_systeme/pere_fils_sans_exit.c new file mode 100644 index 0000000..29d6883 --- /dev/null +++ b/TP2/api_systeme/pere_fils_sans_exit.c @@ -0,0 +1,42 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Absence du exit dans le fils, et conséquences */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 3; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + /* Le fils ne s'arrete pas ici */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_wait.c b/TP2/api_systeme/pere_fils_wait.c new file mode 100644 index 0000000..d82ce9b --- /dev/null +++ b/TP2/api_systeme/pere_fils_wait.c @@ -0,0 +1,66 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* wait : le père attend la fin de ses fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, wstatus, fils_termine; + int duree_sommeil = 300; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + /* Le fils 2 s'endort pendant une durée asse longue */ + if (fils == 2) { + sleep(duree_sommeil); + } + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + sleep(3); /* pour les besoins de l'outil de validation automatique */ + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pere_fils_zombie.c b/TP2/api_systeme/pere_fils_zombie.c new file mode 100644 index 0000000..af2909f --- /dev/null +++ b/TP2/api_systeme/pere_fils_zombie.c @@ -0,0 +1,42 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fils Zombie */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + exit(EXIT_SUCCESS); /* Terminaison normale */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_alarm_waitpid.c b/TP2/api_systeme/pf_alarm_waitpid.c new file mode 100644 index 0000000..e17b34f --- /dev/null +++ b/TP2/api_systeme/pf_alarm_waitpid.c @@ -0,0 +1,89 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* SIGALRM et waitpid pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ +#define D_ALARM 10 /* durée pour alarm */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigalrm(int signal_num) { + int fils_termine, wstatus; + + if (signal_num == SIGALRM) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + } + } + /* relancer alarm a cela n'est pas fait automatiquement */ + alarm(D_ALARM); + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 3; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGALRM, handler_sigalrm); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil * fils); + printf("\n Processus fils numero %d : je m\'arrête.\n", fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + alarm(D_ALARM); + /* faire ce qu'on veut jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_calmaxtab_fichier.c b/TP2/api_systeme/pf_calmaxtab_fichier.c new file mode 100644 index 0000000..743f7d9 --- /dev/null +++ b/TP2/api_systeme/pf_calmaxtab_fichier.c @@ -0,0 +1,115 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Calcul distribué du maximum d'un tableau : communication par fichier */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ +#define NB_FLEM_FILS 100000 +#define NB_ELEM NB_FILS*NB_FLEM_FILS + +/* calcul du max d'un sous-tableau */ +int cal_max_tab(int tab[], int i1, int i2) { + int i, max; + + max = tab[i1]; + + for (i = i1 + 1; i < i2; i++) { + if (tab[i]>max) { + max = tab[i]; + } + } + return max; +} + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, max, max_lu; + + int tab[NB_ELEM]; + + char fichier[] = "fic_3f_maxtab"; + + /* initialiser le tableau */ + for (int i=0; i < NB_ELEM; i++) { + tab[i] = i+1; + } + + /* ouvrir le fichier en écriture */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* calculer le max du sous-tableau */ + max = cal_max_tab(tab, (fils-1)*NB_FLEM_FILS, fils*NB_FLEM_FILS); + /* enregistrer le max en binaire */ + write(desc_fic, &max, sizeof(int)); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* fermer le fichier ouvert en ecriture */ + close(desc_fic); + + /* ouvrir le fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + max = 0; + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + /* lire les nouvelles valeurs communiquées par les fils */ + /* et calculer le max intermédiaire */ + while (read(desc_fic, &max_lu, sizeof(int))>0) { + if (max_lu > max) { + max = max_lu; + } + } + } + close(desc_fic); + printf("\nProcessus Principal termine. Max = %d\n", max); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_fichier_ecr_ouv_sep.c b/TP2/api_systeme/pf_fichier_ecr_ouv_sep.c new file mode 100644 index 0000000..b87a048 --- /dev/null +++ b/TP2/api_systeme/pf_fichier_ecr_ouv_sep.c @@ -0,0 +1,86 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : plusieurs ouvertures, écritures concurrentes */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_sep.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + sleep(duree_sommeil); + } + + close(desc_fic); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_fichier_ecr_ouv_uni.c b/TP2/api_systeme/pf_fichier_ecr_ouv_uni.c new file mode 100644 index 0000000..737d9c4 --- /dev/null +++ b/TP2/api_systeme/pf_fichier_ecr_ouv_uni.c @@ -0,0 +1,87 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : 1 seule ouverture en écriture partagée */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_uni.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en ecriture, avec autorisations rw- -r- ---*/ + /* avec création si le fichier n'existe pas : O_CREAT */ + /* avec vidange (raz du contenu) si le fichier existe: O_TRUNC */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + sleep(duree_sommeil); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c b/TP2/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c new file mode 100644 index 0000000..e505db4 --- /dev/null +++ b/TP2/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c @@ -0,0 +1,96 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : 1 seule ouverture en écriture partagée et lseek */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_uni_lseek.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en ecriture, avec autorisations rw- -r- ---*/ + /* avec création si le fichier n'existe pas : O_CREAT */ + /* avec vidange (raz du contenu) si le fichier existe: O_TRUNC */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + // fils 2 recule la tete de 4 octets + if (fils == 2) { + lseek(desc_fic, -4, SEEK_CUR); + } + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + // fils 1 avance la tete de 4 octets + if (fils == 1) { + lseek(desc_fic, 4, SEEK_CUR); + } + sleep(duree_sommeil); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_fichier_lec_ouv_sep.c b/TP2/api_systeme/pf_fichier_lec_ouv_sep.c new file mode 100644 index 0000000..c1d2055 --- /dev/null +++ b/TP2/api_systeme/pf_fichier_lec_ouv_sep.c @@ -0,0 +1,85 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée avec ouvertures séparées */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + sleep(NB_FILS - fils); + + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4)>0) { + + printf(" Processus fils numero %d a lu %s\n", + fils, buffer); + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + + close(desc_fic); + + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_fichier_lec_ouv_uni.c b/TP2/api_systeme/pf_fichier_lec_ouv_uni.c new file mode 100644 index 0000000..9771a75 --- /dev/null +++ b/TP2/api_systeme/pf_fichier_lec_ouv_uni.c @@ -0,0 +1,82 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée entre père et fils avec ouverture unique */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + /* Initialiser buffer avec 0 */ + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les lectures des differents fils : fils 3, fils 2, fils 1 */ + sleep(NB_FILS - fils); + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4) > 0) { + printf(" Processus fils numero %d a lu %s\n", fils, buffer); + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_fichier_lec_ouv_uni_lseek.c b/TP2/api_systeme/pf_fichier_lec_ouv_uni_lseek.c new file mode 100644 index 0000000..468aadf --- /dev/null +++ b/TP2/api_systeme/pf_fichier_lec_ouv_uni_lseek.c @@ -0,0 +1,92 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée avec ouverture unique et lssek */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + /* Initialiser buffer avec 0 */ + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les lectures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + if (fils == NB_FILS) { + lseek(desc_fic, 4, SEEK_SET); + } + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4) > 0) { + + printf(" Processus fils numero %d a lu %s\n", + fils, buffer); + if (fils == 1) { + lseek(desc_fic, 4, SEEK_CUR); + } + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigchld_mask.c b/TP2/api_systeme/pf_sigchld_mask.c new file mode 100644 index 0000000..144a423 --- /dev/null +++ b/TP2/api_systeme/pf_sigchld_mask.c @@ -0,0 +1,103 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* masquage et démasquage de SIGCHLD */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ +#define DELAI 10 + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int fils_termine, wstatus; + + if (signal_num == SIGCHLD) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + } + } + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + sigset_t ens_signaux; + + sigemptyset(&ens_signaux); + + /* ajouter SIGCHLD à ens_signaux */ + sigaddset(&ens_signaux, SIGCHLD); + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil * fils); + printf("\n Processus fils numero %d : je m\'arrête.\n", fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* faire ce qu'on veut jusqu'à la terminaison de tous les fils */ + do { + /* période durant laquelle on ne veut pas être embêté par SIGCHLD */ + printf("\nProcessus de pid %d : Je masque SIGCHLD durant %d secondes\n", getpid(), DELAI); + /* masquer les signaux définis dans ens_signaux : SIGCHLD */ + sigprocmask(SIG_BLOCK, &ens_signaux, NULL); + sleep(DELAI); + + /* période durant laquelle on peut traiter le signal SIGCHLD */ + printf("\nProcessus de pid %d : Je démasque SIGCHLD\n", getpid()); + /* démasquer les signaux définis dans ens_signaux : SIGCHLD */ + sigprocmask(SIG_UNBLOCK, &ens_signaux, NULL); + sleep(2); + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigchld_wait.c b/TP2/api_systeme/pf_sigchld_wait.c new file mode 100644 index 0000000..af7cd1e --- /dev/null +++ b/TP2/api_systeme/pf_sigchld_wait.c @@ -0,0 +1,76 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* utilisation de SIGCHLD pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int wstatus, fils_termine; + + fils_termine = wait(&wstatus); + nb_fils_termines++; + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 300; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(2 + duree_sommeil * (fils -1)); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigchld_wait_sig_perdu.c b/TP2/api_systeme/pf_sigchld_wait_sig_perdu.c new file mode 100644 index 0000000..87d4f4c --- /dev/null +++ b/TP2/api_systeme/pf_sigchld_wait_sig_perdu.c @@ -0,0 +1,83 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* utilisation de SIGCHLD pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int wstatus, fils_termine; + + printf("\nJ'ai reçu le signal %d\n", signal_num); + fils_termine = wait(&wstatus); + nb_fils_termines++; + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + sleep(3); + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + //if (fils==3) duree_sommeil++; + sleep(duree_sommeil); + printf("\n Processus fils numero %d s'arrete\n", + fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + //sleep(2); /* pour les besoins de l'outil de validation automatique */ + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigchld_waitpid_while.c b/TP2/api_systeme/pf_sigchld_waitpid_while.c new file mode 100644 index 0000000..c7f9e29 --- /dev/null +++ b/TP2/api_systeme/pf_sigchld_waitpid_while.c @@ -0,0 +1,80 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* SIGCHLD et waitpid pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ +#include + +#define NB_FILS 4 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_chld(int signal_num) { + int fils_termine, wstatus; + printf("\nJ'ai reçu le signal %d\n", signal_num); + if (signal_num == SIGCHLD) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + sleep(1); + } + } + +} + +/* Programme principal : Un pere qui cree 3 fils */ + +int main() +{ + int fils, pid; + int duree_sommeil = 2; + + signal(SIGCHLD, handler_chld); + + printf("Je suis le processus principal %d, de pere %d\n", getpid(), getppid()); + nb_fils_termines = 0; + + for (fils=1; fils<=NB_FILS; fils++) { + pid = fork(); + if (pid<0) { // erreur fork + printf("Erreur fork\n"); + exit(1); + } + else if (pid==0) { //fils + printf("\n Processus fils num %d, de pid %d, de pere %d.\n", fils, getpid(), getppid()); + if (fils == 4) { + duree_sommeil = 300; + } + sleep(duree_sommeil); + printf("\n Processus fils num %d termine\n", fils); + exit(fils); /* normalement 0, mais on veut illustrer WEXITSTATUS */ + } + else {//pere + printf("\nProcessus pere de pid %d a cree un fils numero %d, de pid %d \n", getpid(), fils, pid); + } + } + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigint.c b/TP2/api_systeme/pf_sigint.c new file mode 100644 index 0000000..e4632e4 --- /dev/null +++ b/TP2/api_systeme/pf_sigint.c @@ -0,0 +1,67 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 600; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigint_ign_dfl.c b/TP2/api_systeme/pf_sigint_ign_dfl.c new file mode 100644 index 0000000..a6be450 --- /dev/null +++ b/TP2/api_systeme/pf_sigint_ign_dfl.c @@ -0,0 +1,73 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT : SIG_IGN et SIG_DFL */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 600; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + if (fils == 1) { + signal(SIGINT, SIG_IGN); + } + else if (fils == 2) { + signal(SIGINT, SIG_DFL); + } + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigint_ign_dfl_exec.c b/TP2/api_systeme/pf_sigint_ign_dfl_exec.c new file mode 100644 index 0000000..d946c10 --- /dev/null +++ b/TP2/api_systeme/pf_sigint_ign_dfl_exec.c @@ -0,0 +1,80 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT : SIG_IGN et SIG_DFL avec exec */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 300; + + char ref_exec[]="./dormir"; /* exécutable */ + char arg0_exec[]="je dors"; /* argument0 du exec : nom donnée au processus */ + char arg1_exec[]="300"; /* argument0 du exec : durée de sommeil */ + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + if (fils == 1) { + signal(SIGINT, SIG_IGN); + } + else if (fils == 2) { + signal(SIGINT, SIG_DFL); + } + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + execl(ref_exec, arg0_exec, arg1_exec, NULL); + /* on ne se retrouve ici que si exec échoue */ + printf("\n Processus fils numero %d : ERREUR EXEC\n", fils); + /* perror : affiche un message relatif à l'erreur du dernier appel systàme */ + perror(" exec "); + exit(fils); /* sortie avec le numéro di fils qui a échoué */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/pf_sigint_tstp_cont.c b/TP2/api_systeme/pf_sigint_tstp_cont.c new file mode 100644 index 0000000..850d88e --- /dev/null +++ b/TP2/api_systeme/pf_sigint_tstp_cont.c @@ -0,0 +1,70 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler); + signal(SIGTSTP, handler); + signal(SIGCONT, handler); + signal(SIGQUIT, handler); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP2/api_systeme/sigaction_source_signal.c b/TP2/api_systeme/sigaction_source_signal.c new file mode 100644 index 0000000..46eba85 --- /dev/null +++ b/TP2/api_systeme/sigaction_source_signal.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +/* traitant sigaction, avec récupération du pid de l'émetteur du signal */ +void sigaction_sig (int num_sig, siginfo_t *siginfo, void * notused) { + int emetteur; + + // récupérer le numéro du porcessus qui a envoyé le signal + emetteur = siginfo->si_pid; + + printf("Processus %d a recu le signal %d envoye par le processus %d \n", getpid(), num_sig, emetteur); +} + +/* traitant qui peut être utilisé en modifiant l'initialisation de sigaction */ +void handler_sig (int num_sig) { + printf("Processus %d a recu le signal %d\n", getpid(), num_sig); +} + +/* Programme principal + * un père crée un fils et s'endort pendant 120 secondes + * le fils se termine après 3 secondes environs ==> envoi de SIGCHLD au père + * le père traite (traitant sigaction dessus) SIGCHLD, SIGINT, SIGTSTP et SIGCONT : + * afficahge du numéro du signal reçu et du pid de l'émetterur + * A tester avec CtrlC, CtrlZ, et envoie des signaux depuis un autre terminal */ + +int main() { + struct sigaction s; + + int pid, retval, duree_sommeil = 120; + + /* Il est très important d'initialiser sa_flags, éventuellement avec 0 */ + s.sa_flags = SA_SIGINFO; // pour récupérer les infos dans siginfo + s.sa_sigaction = sigaction_sig; + + /* On utilise soit sa_sigaction ou sa_handler */ + // s.sa_handler = handler_sig; + + retval = sigaction(SIGINT, &s, NULL); // 3eme paramètre à NULL, car on ne + retval = sigaction(SIGTSTP, &s, NULL); // souhaite pas récupérer l'ancien + retval = sigaction(SIGCONT, &s, NULL); // sigaction + retval = sigaction(SIGCHLD, &s, NULL); + + if(retval < 0) { + perror("sigaction failed"); + } + + pid = fork(); + switch (pid) { + case -1 : + printf("Erreur fork\n"); exit(1); + case 0 : //fils + sleep(3); + exit(0); + + default : //pere + printf("Je suis le processus %d et j'ai cree un fils de numéro %d\n", getpid(), pid); + printf("Je m'endors pendant %d secondes et je traite les signaux SIGINT, SIGTSTP, SIGCONT et SIGCHLD\n", duree_sommeil); + + int duree=0; + do { + sleep(1); // sleep est arrêté par la réception d'un signal + // on ne peut donc pas utiliser sleep(duree_sommeil) + duree++; + } while (duree < duree_sommeil); + } + return 0; +} diff --git a/TP2/etu.c b/TP2/etu.c new file mode 100644 index 0000000..ae10cfb --- /dev/null +++ b/TP2/etu.c @@ -0,0 +1,72 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +/* Traitement du signal */ +void handler_sig(int signal_num) { + printf("Reception %d\n", signal_num); + return; +} + +// TODO: utiliser sigaction + +int main() +{ + // on affiche le pid + printf("pid=%d\n", getpid()); + + /* associer un traitant au signal USR1 */ + signal(SIGUSR1, handler_sig); + + /* associer un traitant au signal USR2 */ + signal(SIGUSR2, handler_sig); + + sigset_t ens_signaux; + + // on vide les set de signaux + sigemptyset(&ens_signaux); + + // on ajoute SIGINT à ens_signaux_int + sigaddset(&ens_signaux, SIGINT); + + // on ajoute SIGUSR1 à ens_signaux_usr1 + sigaddset(&ens_signaux, SIGUSR1); + + // on masque les signaux + sigprocmask(SIG_SETMASK, &ens_signaux, NULL); + + // on attend 10 secondes, envoyer SIGINT au clavier + printf("sleep(10)\n"); + sleep(10); + + // on s'envoie 2 signaux SIGUSR1 + kill(getpid(), SIGUSR1); + kill(getpid(), SIGUSR1); + + // on attend 5 secondes + printf("sleep(5)\n"); + sleep(5); + + // on s'envoie 2 signaux SIGUSR2 + kill(getpid(), SIGUSR2); + kill(getpid(), SIGUSR2); + + // on démasque SIGUSR1 + sigdelset(&ens_signaux, SIGUSR1); + sigprocmask(SIG_SETMASK, &ens_signaux, NULL); + + // on attend 10 secondes + printf("sleep(10)\n"); + sleep(10); + + // on démasque SIGINT + sigdelset(&ens_signaux, SIGINT); + sigprocmask(SIG_SETMASK, &ens_signaux, NULL); + + // message de terminaison + printf("Salut\n"); + + return EXIT_SUCCESS; +} diff --git a/TP2/exo1-1.c b/TP2/exo1-1.c new file mode 100644 index 0000000..b59222e --- /dev/null +++ b/TP2/exo1-1.c @@ -0,0 +1,31 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +/* Traitant du signal */ +void handler_sigint(int signal_num) { + printf("\nProcessus de pid %d : J'ai reçu le signal %d\n", getpid(),signal_num); + return; +} + +int main() { + + // on change les traitements de signal + for (int i = 0; i < _NSIG; i++) { + signal(i, handler_sigint); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + // on fait pleins de sleeps car traiter un signal le saute + for (int i = 0; i < 12; i++) { + sleep(5); + printf("I sleep\n"); + } + + return EXIT_SUCCESS; +} diff --git a/TP2/exo1-3.c b/TP2/exo1-3.c new file mode 100644 index 0000000..b8d41ce --- /dev/null +++ b/TP2/exo1-3.c @@ -0,0 +1,49 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +/* Traitant du signal */ +void handler_sigint(int signal_num) { + printf("\nProcessus de pid %d : J'ai reçu le signal %d\n", getpid(),signal_num); + return; +} + +void dormir(int nb_secondes) { + for (int i = 0; i < nb_secondes; i++) { + sleep(1); + } +} + +int main() { + int retour; + int duree_sommeil = 60; + + /* associer un traitant au signal USR2 */ + signal(12, handler_sigint); + + printf("\nPère, pid=%d.\n", getpid()); + + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + if (retour == 0) { // fils + printf("\nFils, pid=%d, ppid=%d.\n", getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + else { // père + printf("\nPère (%d), mon fils=%d.\n", getpid(), retour); + } + + dormir(duree_sommeil+2); + + return EXIT_SUCCESS; +} diff --git a/TP2/exo1-4.c b/TP2/exo1-4.c new file mode 100644 index 0000000..7a89bbb --- /dev/null +++ b/TP2/exo1-4.c @@ -0,0 +1,49 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include // pour le wait +#include /* traitement des signaux */ + +/* Traitant du signal */ +void handler_sigint(int signal_num) { + printf("\nProcessus de pid %d : J'ai reçu le signal %d\n", getpid(),signal_num); + return; +} + +int main() { + int retour, codeTerm; + + /* associer un traitant au signal USR2 */ + signal(12, handler_sigint); + + printf("\nPère, pid=%d.\n", getpid()); + + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + if (retour == 0) { // fils + printf("\nFils, pid=%d, ppid=%d.\n", getpid(), getppid()); + execl("/bin/sleep", "/bin/sleep", "10", NULL); + exit(1); // si exec fail + } + else { // père + printf("\nPère (%d), waiting mon fils (%d).\n", getpid(), retour); + + retour = wait(&codeTerm); // on attend la fin du fils + if (retour == -1){ + perror("wait "); + exit(3); + } + + printf("%d, %d, %d, %d, %d\n", WIFEXITED(codeTerm), WEXITSTATUS(codeTerm), WIFSIGNALED(codeTerm), WTERMSIG(codeTerm), codeTerm); + + } + + return EXIT_SUCCESS; +} diff --git a/TP2/exo2.c b/TP2/exo2.c new file mode 100644 index 0000000..6dfebab --- /dev/null +++ b/TP2/exo2.c @@ -0,0 +1,73 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +/* Traitement du signal */ +void handler_sigint(int signal_num) { + printf("Reception %d\n", signal_num); + return; +} + +// TODO: utiliser sigaction + +int main() +{ + // on affiche le pid + printf("pid=%d\n", getpid()); + + /* associer un traitant au signal USR1 */ + signal(SIGUSR1, handler_sigint); + + /* associer un traitant au signal USR2 */ + signal(SIGUSR2, handler_sigint); + + sigset_t ens_signaux_int; + sigset_t ens_signaux_usr1; + + // on vide les set de signaux + sigemptyset(&ens_signaux_int); + sigemptyset(&ens_signaux_usr1); + + // on ajoute SIGINT à ens_signaux_int + sigaddset(&ens_signaux_int, SIGINT); + + // on ajoute SIGUSR1 à ens_signaux_usr1 + sigaddset(&ens_signaux_usr1, SIGUSR1); + + // on masque les signaux + sigprocmask(SIG_SETMASK, &ens_signaux_int, NULL); + sigprocmask(SIG_BLOCK, &ens_signaux_usr1, NULL); + + // on attend 10 secondes, envoyer SIGINT au clavier + printf("sleep(10)\n"); + sleep(10); + + // on s'envoie 2 signaux SIGUSR1 + kill(SIGUSR1, getpid()); + kill(SIGUSR1, getpid()); + + // on attend 5 secondes + printf("sleep(5)\n"); + sleep(5); + + // on s'envoie 2 signaux SIGUSR2 + kill(SIGUSR2, getpid()); + kill(SIGUSR2, getpid()); + + // on démasque SIGUSR1 + sigprocmask(SIG_UNBLOCK, &ens_signaux_usr1, NULL); + + // on attend 10 secondes + printf("sleep(10)\n"); + sleep(10); + + // on démasque SIGINT + sigprocmask(SIG_UNBLOCK, &ens_signaux_int, NULL); + + // message de terminaison + printf("Salut\n"); + + return EXIT_SUCCESS; +} diff --git a/TP2/verif_signaux/Notice.html b/TP2/verif_signaux/Notice.html new file mode 100644 index 0000000..82c8a23 --- /dev/null +++ b/TP2/verif_signaux/Notice.html @@ -0,0 +1,37 @@ + + + + + + + + + + +

Avertissement

+

Le script de vérification verif_signaux.sh doit être considéré comme un simple outil mis à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, et non comme une application de validation automatique de votre travail. Simplement, si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation effective. Et inversement.

+

En particulier :

+
    +
  • il est inutile de modifier le script pour qu'il donne une réponse OK : la validation se fera sur nos propres outils.
  • +
  • le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers de manière intempestive, le script de vérification peut devenir invalide. Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis contre ce genre d'accidents.
  • +
  • en revanche, le script de vérification fonctionne bien avec des réponses correctes. Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être quasi-certains que cela ne découle pas d'une erreur dans le script de test.
  • +
+

Conventions de nommage

+

Pour que le script de vérification verif_signaux.sh puisse être appliqué :

+
    +
  • le fichier source du programme à vérifier doit être exactement nommé etu.c et rangé dans le répertoire etu, situé au même niveau que verif_signaux.sh
  • +
  • le répertoire etu contient par ailleurs un fichier texte réponses destiné à recueillir vos réponses aux questions posées.
  • +
  • le répertoire contenant verif_signaux.sh ne devra pas être modifié, en dehors de l'ajout du fichier source etu.c.
  • +
+

Appel et résultats du script de vérification

+

Le script verif_signaux.sh doit être lancé depuis un terminal, le répertoire courant étant le répertoire contenant verif_signaux.sh.

+
    +
  • Lorsqu'il est lancé sans option, verif_signaux.sh effectue un diagnostic sur le programme etu.c.
    +Si la vérification échoue le script affiche KO, sinon il affiche OK. Notez que la mention OK est une condition nécessaire pour que la réponse soit juste, mais que ce n'est pas une condition suffisante.
    +En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification ne devrait afficher aucun warning suite à la compilation.
    +Lorsque le script verif_signaux.sh se termine, il affiche un message OK ou KO.
    +Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut tuer le processus exécutant le script.
  • +
  • Lorsqu'il est lancé avec l'option -s (pour soumettre), le script prépare l'archive qui pourra être déposée sur Moodle. L'archive créée par l'appel de verif_signaux.sh -s se trouve au même niveau que verif_signaux.sh
  • +
+ + diff --git a/TP2/verif_signaux/Notice.md b/TP2/verif_signaux/Notice.md new file mode 100644 index 0000000..215d55a --- /dev/null +++ b/TP2/verif_signaux/Notice.md @@ -0,0 +1,54 @@ +Avertissement +------------- +Le script de vérification `verif_signaux.sh` doit être considéré comme un simple outil mis + à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, + et non comme une application de validation automatique de votre travail. Simplement, + si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation + effective. Et inversement. + +En particulier : + + - il est inutile de modifier le script pour qu'il donne une réponse `OK` : la validation + se fera sur nos propres outils. + - le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées + à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers + de manière intempestive, le script de vérification peut devenir invalide. + Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis + contre ce genre d'accidents. + - en revanche, le script de vérification fonctionne bien avec des réponses correctes. + Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être + quasi-certains que cela ne découle pas d'une erreur dans le script de test. + +Conventions de nommage +---------------------- + +Pour que le script de vérification `verif_signaux.sh` puisse être appliqué : + + - le fichier source du programme à vérifier doit être **exactement** nommé `etu.c` et + rangé dans le répertoire `etu`, situé au même niveau que `verif_signaux.sh` + - le répertoire `etu` contient par ailleurs un fichier texte `réponses` destiné à recueillir + vos réponses aux questions posées. + - le répertoire contenant `verif_signaux.sh` ne devra pas être modifié, en dehors de l'ajout du + fichier source `etu.c`. + + +Appel et résultats du script de vérification +-------------------------------------------- + +Le script `verif_signaux.sh` doit être lancé depuis un terminal, le répertoire courant +étant le répertoire contenant `verif_signaux.sh`. + +* Lorsqu'il est lancé sans option, `verif_signaux.sh` effectue un diagnostic sur le programme +`etu.c`. +Si la vérification échoue le script affiche `KO`, sinon il affiche `OK`. +Notez que la mention `OK` est une condition nécessaire pour que la réponse soit juste, +mais que ce n'est pas une condition suffisante. +En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification +ne devrait afficher aucun warning suite à la compilation. +Lorsque le script `verif_signaux.sh` se termine, il affiche un message `OK` ou `KO`. + Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut + tuer le processus exécutant le script. +* Lorsqu'il est lancé avec l'option `-s` (pour soumettre), le script prépare l'archive qui +pourra être déposée sur Moodle. L'archive créée par l'appel de `verif_signaux.sh -s` se +trouve au même niveau que `verif_signaux.sh` + diff --git a/TP2/verif_signaux/a/b/core b/TP2/verif_signaux/a/b/core new file mode 100644 index 0000000..8ffd36b --- /dev/null +++ b/TP2/verif_signaux/a/b/core @@ -0,0 +1 @@ +Reception \ No newline at end of file diff --git a/TP2/verif_signaux/a/bar b/TP2/verif_signaux/a/bar new file mode 100644 index 0000000..9d95cc1 Binary files /dev/null and b/TP2/verif_signaux/a/bar differ diff --git a/TP2/verif_signaux/a/hurz b/TP2/verif_signaux/a/hurz new file mode 100644 index 0000000..e69de29 diff --git a/TP2/verif_signaux/a/kro.c b/TP2/verif_signaux/a/kro.c new file mode 100644 index 0000000..b26a6b5 --- /dev/null +++ b/TP2/verif_signaux/a/kro.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main () { + printf ("%d\n",SIGUSR1); + printf ("%d\n",SIGUSR2); + return 0; +} diff --git a/TP2/verif_signaux/a/pfurz b/TP2/verif_signaux/a/pfurz new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/TP2/verif_signaux/a/pfurz @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/TP2/verif_signaux/a/s b/TP2/verif_signaux/a/s new file mode 100644 index 0000000..d86bac9 --- /dev/null +++ b/TP2/verif_signaux/a/s @@ -0,0 +1 @@ +OK diff --git a/TP2/verif_signaux/etu/etu.c b/TP2/verif_signaux/etu/etu.c new file mode 100644 index 0000000..be0e635 --- /dev/null +++ b/TP2/verif_signaux/etu/etu.c @@ -0,0 +1,72 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +/* Traitement du signal */ +void handler_sig(int signal_num) { + printf("Reception %d\n", signal_num); + return; +} + +// TODO: utiliser sigaction ? + +int main() +{ + // on affiche le pid + printf("DEBUG: pid=%d\n", getpid()); + + // associer un traitant au signal USR1 + signal(SIGUSR1, handler_sig); + + // associer un traitant au signal USR2 + signal(SIGUSR2, handler_sig); + + sigset_t ens_signaux; + + // on vide les set de signaux + sigemptyset(&ens_signaux); + + // on ajoute SIGINT à ens_signaux + sigaddset(&ens_signaux, SIGINT); + + // on ajoute SIGUSR1 à ens_signaux + sigaddset(&ens_signaux, SIGUSR1); + + // on masque les signaux + sigprocmask(SIG_SETMASK, &ens_signaux, NULL); + + // on attend 10 secondes, envoyer SIGINT au clavier + printf("DEBUG: sleep(10)\n"); + sleep(10); + + // on s'envoie 2 signaux SIGUSR1 + kill(getpid(), SIGUSR1); + kill(getpid(), SIGUSR1); + + // on attend 5 secondes + printf("DEBUG: sleep(5)\n"); + sleep(5); + + // on s'envoie 2 signaux SIGUSR2 + kill(getpid(), SIGUSR2); + kill(getpid(), SIGUSR2); + + // on démasque SIGUSR1 + sigdelset(&ens_signaux, SIGUSR1); + sigprocmask(SIG_SETMASK, &ens_signaux, NULL); + + // on attend 10 secondes + printf("DEBUG: sleep(10)\n"); + sleep(10); + + // on démasque SIGINT + sigdelset(&ens_signaux, SIGINT); + sigprocmask(SIG_SETMASK, &ens_signaux, NULL); + + // message de terminaison + printf("Salut\n"); + + return EXIT_SUCCESS; +} diff --git a/TP2/verif_signaux/etu/reponses b/TP2/verif_signaux/etu/reponses new file mode 100644 index 0000000..ea41156 --- /dev/null +++ b/TP2/verif_signaux/etu/reponses @@ -0,0 +1,6 @@ +1-Combien de SIGUSR1 et de SIGUSR2 seront ils affichés ? +--> On reçoit 2 signaux SIGUSR2 et 1 signal SIGUSR1 +2-Quel sera l'ordre d'affichage ? +--> 12, 12, 10 +3-Au bout de combien de temps (à 2 secondes près) s'affichera le message de terminaison ? +--> 25±2 secondes \ No newline at end of file diff --git a/TP2/verif_signaux/foo b/TP2/verif_signaux/foo new file mode 100644 index 0000000..f9e0c0c --- /dev/null +++ b/TP2/verif_signaux/foo @@ -0,0 +1,11 @@ +DEBUG: pid=28660 +DEBUG: sleep(10) +Reception 12 +DEBUG: sleep(5) +Reception 12 +Reception 12 +Reception 10 +DEBUG: sleep(10) +Reception 12 +Reception 10 +Salut diff --git a/TP2/verif_signaux/hurz b/TP2/verif_signaux/hurz new file mode 100644 index 0000000..60f5b4b --- /dev/null +++ b/TP2/verif_signaux/hurz @@ -0,0 +1,2 @@ +10 +12 diff --git a/TP2/verif_signaux/lala.o b/TP2/verif_signaux/lala.o new file mode 100644 index 0000000..e8c4d10 --- /dev/null +++ b/TP2/verif_signaux/lala.o @@ -0,0 +1,8 @@ +Notice.html +Notice.md +a +foo +lala.o +miniminishell.c +ms +verif.sh diff --git a/TP2/verif_signaux/laurent-tpSignaux.tar b/TP2/verif_signaux/laurent-tpSignaux.tar new file mode 100644 index 0000000..1242228 Binary files /dev/null and b/TP2/verif_signaux/laurent-tpSignaux.tar differ diff --git a/TP2/verif_signaux/sgnetu b/TP2/verif_signaux/sgnetu new file mode 100644 index 0000000..f1173fa Binary files /dev/null and b/TP2/verif_signaux/sgnetu differ diff --git a/TP2/verif_signaux/verif_signaux.sh b/TP2/verif_signaux/verif_signaux.sh new file mode 100644 index 0000000..541801f --- /dev/null +++ b/TP2/verif_signaux/verif_signaux.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# PM, le 6/4/21 +if [ \( "a$1" = 'a-s' \) ] ; then + echo "préparation de l'archive à soumettre" + rep=`who a i|cut -d' ' -f 1`-tpSignaux + mkdir "$rep" + if [ ! \( -f etu/reponses \) ] ; then + echo "note : fichier reponses non trouvé" + else + cp etu/reponses "$rep" + fi + if [ ! \( -f etu/etu.c \) ] ; then + echo "note : fichier source etu.c non trouvé" + else + cp etu/etu.c "$rep" + fi + cp a/s "$rep" + tar -cf "$rep".tar "$rep" + rm -r "$rep" + echo "prêt : vous pouvez déposer l'archive $rep.tar sous Moodle" + exit 0 +fi + +export PATH=.:$PATH +res=KO + +gcc -Wall etu/etu.c -o sgnetu +gcc -Wall a/kro.c -o a/bar + +a/bar > hurz +aleph=`cat hurz | head -1` +o6=`cat hurz | tail -1` +jack=`cat a/b/core` + +echo "10 secondes..." + +sgnetu > foo & + +pid=`ps| grep sgnetu | grep -v grep | cut -d ' ' -f1` + +sleep 4 + +kill -USR1 $pid +kill -USR2 $pid + +sleep 7 + +kill -USR1 $pid +kill -USR2 $pid + +r3=`cat foo | grep "$jack $aleph" | wc -l` +r4=`cat foo | grep "$jack $o6" | wc -l` + +echo "encore 10 secondes..." + +sleep 12 + +r5=`cat foo | grep Salut | wc -l` + +if [ \( $r5 -eq 1 \) -a \( $((r4/r3)) -eq $(cat a/pfurz) \) ] ; then + res=OK +fi + +echo $res > a/s +echo $res \ No newline at end of file diff --git a/TP2/verif_signaux/verif_signaux_mod.sh b/TP2/verif_signaux/verif_signaux_mod.sh new file mode 100644 index 0000000..ed19f3c --- /dev/null +++ b/TP2/verif_signaux/verif_signaux_mod.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# PM 2021-04-06 +# Laureηt 2021-04-08 # Works on my machine ™ + +# utiliser l'option "-s" pour archiver le code +if [ \( "a$1" = 'a-s' \) ] ; then + echo "préparation de l'archive à soumettre" + rep=`whoami | cut -d' ' -f 1`-tpSignaux # fix typo + mkdir "$rep" + if [ ! \( -f etu/reponses \) ] ; then + echo "note : fichier réponses non trouvé" + else + cp etu/reponses "$rep" + fi + if [ ! \( -f etu/etu.c \) ] ; then + echo "note : fichier source etu.c non trouvé" + else + cp etu/etu.c "$rep" + fi + cp a/s "$rep" + tar -cf "$rep".tar "$rep" + rm -r "$rep" + echo "prêt : vous pouvez déposer l'archive $rep.tar sous Moodle" + exit 0 +fi + +export PATH=.:$PATH +res=KO + +gcc -Wall etu/etu.c -o sgnetu +gcc -Wall a/kro.c -o a/bar + +a/bar > hurz +aleph=`cat hurz | head -1` # = 10 +o6=`cat hurz | tail -1` # = 12 +jack=`cat a/b/core` # = "Reception" + +echo "10 secondes..." + +sgnetu > foo & # on lance le script en arrière plan +# et on déverse son contenu dans le fichier foo + +pid=$! # on récupère le pid du processus mis en arrière plan +#pid=`pgrep sgnetu` # utilisez pgrep +printf "DEBUG: pid=$pid\n" + +sleep 4 + +kill -USR1 $pid +kill -USR2 $pid + +sleep 7 + +kill -USR1 $pid +kill -USR2 $pid + +r3=`cat foo | grep "$jack $aleph" -c` # compte le nombre de "Reception 10" (SIGUSR1) +printf "DEBUG: r3=$r3\n" + +r4=`cat foo | grep "$jack $o6" -c` # compte le nombre de "Reception 12" (SIGUSR2) +printf "DEBUG: r4=$r4\n" + +echo "encore 10 secondes..." + +sleep 12 + +r5=`cat foo | grep Salut -c` # compte le nombre de "Salut" +printf "DEBUG: r5=$r5\n" + +r6=$((r4/r3)) # division entière de r4 par r3 +printf "DEBUG: r4/r3=$r6\n" + +r7=`cat a/pfurz` # = 2 +printf "DEBUG: r7=$r7\n" + +printf "DEBUG: r5 = 1 && r4/r3 = r7 ?\n" +printf " ---> $r5 = 1 && $r6 = $r7\n" +if [ \( $r5 -eq 1 \) -a \( $r6 -eq $r7 \) ] ; then + res=OK # etu.c est correct (normalement) +fi + +echo $res > a/s # on sauvegarde le résultat du test +echo $res # on affiche le résultat du test diff --git a/TP3/.vscode/launch.json b/TP3/.vscode/launch.json new file mode 100644 index 0000000..f798eb3 --- /dev/null +++ b/TP3/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gcc - Build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}/${fileBasenameNoExtension}", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: gcc build active file", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/TP3/.vscode/tasks.json b/TP3/.vscode/tasks.json new file mode 100644 index 0000000..4956c3e --- /dev/null +++ b/TP3/.vscode/tasks.json @@ -0,0 +1,27 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/TP3/TPFichiers.pdf b/TP3/TPFichiers.pdf new file mode 100644 index 0000000..7a2a8ab Binary files /dev/null and b/TP3/TPFichiers.pdf differ diff --git a/TP3/afficher.c b/TP3/afficher.c new file mode 100644 index 0000000..9a32c75 --- /dev/null +++ b/TP3/afficher.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +int main() { + + extern int errno; + + char file[] = "temp"; + + // opening file + int desc_f = open(file, O_RDONLY); + if (desc_f < 0) { + perror("ERROR opening f_write.txt"); + exit(errno); + } + + // reading to file + + while (1) { + int buf; + for (int i = 0; i < 10; i++) { + int ret_read = read(desc_f, &buf, sizeof(int)); + if (ret_read < 0) { + perror("ERROR reading to f_write.txt"); + exit(errno); + } + printf("%d\n", buf); + } + sleep(1); + system("clear"); + lseek(desc_f, 0, SEEK_SET); + } + + // closing files + + int ret_close = 0; + ret_close = close(desc_f); + if (ret_close < 0) { + perror("ERROR closing f_read.txt"); + exit(errno); + } + + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/dormir.c b/TP3/api_systeme/dormir.c new file mode 100644 index 0000000..d643afd --- /dev/null +++ b/TP3/api_systeme/dormir.c @@ -0,0 +1,17 @@ +#include +#include +#include + +// dormir durant n secondes : n fournie en argument +// sinon n=5 par défault +int main(int argc, char* argv[]) +{ + int delai = 5; + if (argc > 1 ) { + delai = atoi(argv[1]); + } + printf("\n - Processus %d va dormir durant %d secondes\n", getpid(), delai); + sleep(delai); + fflush(stdout); + return 0; +} diff --git a/TP3/api_systeme/fic_centaines.txt b/TP3/api_systeme/fic_centaines.txt new file mode 100644 index 0000000..a89c82a --- /dev/null +++ b/TP3/api_systeme/fic_centaines.txt @@ -0,0 +1,11 @@ +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 diff --git a/TP3/api_systeme/pere_fils.c b/TP3/api_systeme/pere_fils.c new file mode 100644 index 0000000..4b513b9 --- /dev/null +++ b/TP3/api_systeme/pere_fils.c @@ -0,0 +1,50 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Création de fils : fork et exit */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* manipulation des chaines */ + +#define NB_FILS 3 /* nombre de fils */ + +int main(int argc, char *argv[]) +{ + int fils, retour; + int duree_sommeil = 3; + char progname[]="pere_fils.c"; + + if (argc > 1) { + write(atoi(argv[1]), progname, strlen(progname)); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil + 1); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_exec.c b/TP3/api_systeme/pere_fils_exec.c new file mode 100644 index 0000000..e7e3edc --- /dev/null +++ b/TP3/api_systeme/pere_fils_exec.c @@ -0,0 +1,74 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* execl */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, wstatus, fils_termine; + + char ref_exec[]="./dormir"; /* exécutable */ + char arg0_exec[]="dodo"; /* argument0 du exec : nom donnée au processus */ + char arg1_exec[]="10"; /* argument0 du exec : durée de sommeil */ + + printf("Je suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + + /* mettre un executable inexistant pour le fils 2 */ + if (fils == 2) { + ref_exec[3] = 'a'; + } + + execl(ref_exec, arg0_exec, arg1_exec, NULL); + + /* on ne se retrouve ici que si exec échoue */ + printf("\n Processus fils numero %d : ERREUR EXEC\n", fils); + /* perror : affiche un message relatif à l'erreur du dernier appel systàme */ + perror(" exec "); + exit(fils); /* sortie avec le numéro di fils qui a échoué */ + } + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + fflush(stdout); + } + } + sleep(3); /* pour les besoins de l'outil de validation automatique */ + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_fflush.c b/TP3/api_systeme/pere_fils_fflush.c new file mode 100644 index 0000000..6dabc85 --- /dev/null +++ b/TP3/api_systeme/pere_fils_fflush.c @@ -0,0 +1,55 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Redirection et fflush */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + /* D'après le standard ISO le comportement du printf présente 2 cas : */ + /* - sortie interactive (terminal) : flot géré par ligne et \n provoque */ + /* la vidange du tampon langage */ + /* - sortie dans un fichier : flot géré par bloc et \n est traité comme */ + /* un caractère ordinaire. fflush(stdout) force la vidange du tampon. */ + + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + /* vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_heritage.c b/TP3/api_systeme/pere_fils_heritage.c new file mode 100644 index 0000000..ac622fe --- /dev/null +++ b/TP3/api_systeme/pere_fils_heritage.c @@ -0,0 +1,51 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Héritage et dupplication des données */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 4 /* nombre de fils */ + +int main() +{ + int fils, retour; + int cagnotte, patrimoine_fils; + int duree_sommeil = 4; + cagnotte = 10000 * NB_FILS; + patrimoine_fils = cagnotte / NB_FILS; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + printf("Je dispose de %d Euros, que je partage entre mes futurs fils\n", cagnotte); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d : mon pere m'a offert %d Euros\n", + fils, patrimoine_fils); + patrimoine_fils = patrimoine_fils * (fils + 1); + sleep(duree_sommeil); + printf("\n Processus fils numero %d - j'ai augmente mon patrimoine a %d Euros\n", + fils, patrimoine_fils); + exit(EXIT_SUCCESS); /* Te:rminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil+1); + + printf("\nProcessus Principal - le patrimoine total de mes fils est de %d\n", patrimoine_fils*NB_FILS); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_orphelin.c b/TP3/api_systeme/pere_fils_orphelin.c new file mode 100644 index 0000000..9894904 --- /dev/null +++ b/TP3/api_systeme/pere_fils_orphelin.c @@ -0,0 +1,43 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fils orphelins */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + exit(EXIT_SUCCESS); /* Terminaison normale */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_sans_exit.c b/TP3/api_systeme/pere_fils_sans_exit.c new file mode 100644 index 0000000..29d6883 --- /dev/null +++ b/TP3/api_systeme/pere_fils_sans_exit.c @@ -0,0 +1,42 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Absence du exit dans le fils, et conséquences */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 3; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + /* Le fils ne s'arrete pas ici */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_wait.c b/TP3/api_systeme/pere_fils_wait.c new file mode 100644 index 0000000..d82ce9b --- /dev/null +++ b/TP3/api_systeme/pere_fils_wait.c @@ -0,0 +1,66 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* wait : le père attend la fin de ses fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, wstatus, fils_termine; + int duree_sommeil = 300; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + /* Le fils 2 s'endort pendant une durée asse longue */ + if (fils == 2) { + sleep(duree_sommeil); + } + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + sleep(3); /* pour les besoins de l'outil de validation automatique */ + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pere_fils_zombie.c b/TP3/api_systeme/pere_fils_zombie.c new file mode 100644 index 0000000..af2909f --- /dev/null +++ b/TP3/api_systeme/pere_fils_zombie.c @@ -0,0 +1,42 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fils Zombie */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil); + exit(EXIT_SUCCESS); /* Terminaison normale */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + sleep(duree_sommeil); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_alarm_waitpid.c b/TP3/api_systeme/pf_alarm_waitpid.c new file mode 100644 index 0000000..e17b34f --- /dev/null +++ b/TP3/api_systeme/pf_alarm_waitpid.c @@ -0,0 +1,89 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* SIGALRM et waitpid pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ +#define D_ALARM 10 /* durée pour alarm */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigalrm(int signal_num) { + int fils_termine, wstatus; + + if (signal_num == SIGALRM) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + } + } + /* relancer alarm a cela n'est pas fait automatiquement */ + alarm(D_ALARM); + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 3; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGALRM, handler_sigalrm); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil * fils); + printf("\n Processus fils numero %d : je m\'arrête.\n", fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + alarm(D_ALARM); + /* faire ce qu'on veut jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_calmaxtab_fichier.c b/TP3/api_systeme/pf_calmaxtab_fichier.c new file mode 100644 index 0000000..743f7d9 --- /dev/null +++ b/TP3/api_systeme/pf_calmaxtab_fichier.c @@ -0,0 +1,115 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Calcul distribué du maximum d'un tableau : communication par fichier */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ +#define NB_FLEM_FILS 100000 +#define NB_ELEM NB_FILS*NB_FLEM_FILS + +/* calcul du max d'un sous-tableau */ +int cal_max_tab(int tab[], int i1, int i2) { + int i, max; + + max = tab[i1]; + + for (i = i1 + 1; i < i2; i++) { + if (tab[i]>max) { + max = tab[i]; + } + } + return max; +} + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, max, max_lu; + + int tab[NB_ELEM]; + + char fichier[] = "fic_3f_maxtab"; + + /* initialiser le tableau */ + for (int i=0; i < NB_ELEM; i++) { + tab[i] = i+1; + } + + /* ouvrir le fichier en écriture */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* calculer le max du sous-tableau */ + max = cal_max_tab(tab, (fils-1)*NB_FLEM_FILS, fils*NB_FLEM_FILS); + /* enregistrer le max en binaire */ + write(desc_fic, &max, sizeof(int)); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* fermer le fichier ouvert en ecriture */ + close(desc_fic); + + /* ouvrir le fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + max = 0; + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + /* lire les nouvelles valeurs communiquées par les fils */ + /* et calculer le max intermédiaire */ + while (read(desc_fic, &max_lu, sizeof(int))>0) { + if (max_lu > max) { + max = max_lu; + } + } + } + close(desc_fic); + printf("\nProcessus Principal termine. Max = %d\n", max); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_fichier_ecr_ouv_sep.c b/TP3/api_systeme/pf_fichier_ecr_ouv_sep.c new file mode 100644 index 0000000..b87a048 --- /dev/null +++ b/TP3/api_systeme/pf_fichier_ecr_ouv_sep.c @@ -0,0 +1,86 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : plusieurs ouvertures, écritures concurrentes */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_sep.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + sleep(duree_sommeil); + } + + close(desc_fic); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_fichier_ecr_ouv_uni.c b/TP3/api_systeme/pf_fichier_ecr_ouv_uni.c new file mode 100644 index 0000000..737d9c4 --- /dev/null +++ b/TP3/api_systeme/pf_fichier_ecr_ouv_uni.c @@ -0,0 +1,87 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : 1 seule ouverture en écriture partagée */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_uni.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en ecriture, avec autorisations rw- -r- ---*/ + /* avec création si le fichier n'existe pas : O_CREAT */ + /* avec vidange (raz du contenu) si le fichier existe: O_TRUNC */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + sleep(duree_sommeil); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c b/TP3/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c new file mode 100644 index 0000000..e505db4 --- /dev/null +++ b/TP3/api_systeme/pf_fichier_ecr_ouv_uni_lseek.c @@ -0,0 +1,96 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* 1 fichier : 1 seule ouverture en écriture partagée et lseek */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus, ifor; + int duree_sommeil = 3; + + char fichier[] = "fic_res_ouv_uni_lseek.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en ecriture, avec autorisations rw- -r- ---*/ + /* avec création si le fichier n'existe pas : O_CREAT */ + /* avec vidange (raz du contenu) si le fichier existe: O_TRUNC */ + desc_fic = open(fichier, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les écritures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + /* effectuer 4 ecritures dans le fichier */ + for (ifor = 1; ifor <= 4; ifor++) { + // fils 2 recule la tete de 4 octets + if (fils == 2) { + lseek(desc_fic, -4, SEEK_CUR); + } + bzero(buffer, sizeof(buffer)); + sprintf(buffer, "%d-%d\n", fils,ifor); + write(desc_fic, buffer, strlen(buffer)); + printf(" Processus fils numero %d a ecrit %s\n", + fils, buffer); + // fils 1 avance la tete de 4 octets + if (fils == 1) { + lseek(desc_fic, 4, SEEK_CUR); + } + sleep(duree_sommeil); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_fichier_lec_ouv_sep.c b/TP3/api_systeme/pf_fichier_lec_ouv_sep.c new file mode 100644 index 0000000..c1d2055 --- /dev/null +++ b/TP3/api_systeme/pf_fichier_lec_ouv_sep.c @@ -0,0 +1,85 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée avec ouvertures séparées */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + bzero(buffer, sizeof(buffer)); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + sleep(NB_FILS - fils); + + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4)>0) { + + printf(" Processus fils numero %d a lu %s\n", + fils, buffer); + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + + close(desc_fic); + + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_fichier_lec_ouv_uni.c b/TP3/api_systeme/pf_fichier_lec_ouv_uni.c new file mode 100644 index 0000000..9771a75 --- /dev/null +++ b/TP3/api_systeme/pf_fichier_lec_ouv_uni.c @@ -0,0 +1,82 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée entre père et fils avec ouverture unique */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + /* Initialiser buffer avec 0 */ + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les lectures des differents fils : fils 3, fils 2, fils 1 */ + sleep(NB_FILS - fils); + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4) > 0) { + printf(" Processus fils numero %d a lu %s\n", fils, buffer); + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_fichier_lec_ouv_uni_lseek.c b/TP3/api_systeme/pf_fichier_lec_ouv_uni_lseek.c new file mode 100644 index 0000000..468aadf --- /dev/null +++ b/TP3/api_systeme/pf_fichier_lec_ouv_uni_lseek.c @@ -0,0 +1,92 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Fichiers : lecture partagée avec ouverture unique et lssek */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ + +#define NB_FILS 3 /* nombre de fils */ + +int main() +{ + int fils, retour, desc_fic, fils_termine, wstatus; + int duree_sommeil = 3; + + char fichier[] = "fic_centaines.txt"; + char buffer[8]; /* buffer de lecture */ + + /* Initialiser buffer avec 0 */ + bzero(buffer, sizeof(buffer)); + + /* ouverture du fichier en lecture */ + desc_fic = open(fichier, O_RDONLY); + /* traiter systématiquement les retours d'erreur des appels */ + if (desc_fic < 0) { + printf("Erreur ouverture %s\n", fichier); + exit(1); + } + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + /* decaler les lectures des differents fils : fils 3, fils 2, fils 1, ... */ + sleep(NB_FILS - fils); + + if (fils == NB_FILS) { + lseek(desc_fic, 4, SEEK_SET); + } + /* lire le fichier par blocs de 4 octets */ + while (read(desc_fic, buffer, 4) > 0) { + + printf(" Processus fils numero %d a lu %s\n", + fils, buffer); + if (fils == 1) { + lseek(desc_fic, 4, SEEK_CUR); + } + sleep(duree_sommeil); + bzero(buffer, sizeof(buffer)); + } + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* attendre la fin des fils */ + for (fils = 1; fils <= NB_FILS; fils++) { + /* attendre la fin d'un fils */ + fils_termine = wait(&wstatus); + + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + } + close(desc_fic); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigchld_mask.c b/TP3/api_systeme/pf_sigchld_mask.c new file mode 100644 index 0000000..144a423 --- /dev/null +++ b/TP3/api_systeme/pf_sigchld_mask.c @@ -0,0 +1,103 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* masquage et démasquage de SIGCHLD */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ +#define DELAI 10 + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int fils_termine, wstatus; + + if (signal_num == SIGCHLD) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + } + } + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + sigset_t ens_signaux; + + sigemptyset(&ens_signaux); + + /* ajouter SIGCHLD à ens_signaux */ + sigaddset(&ens_signaux, SIGCHLD); + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(duree_sommeil * fils); + printf("\n Processus fils numero %d : je m\'arrête.\n", fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* faire ce qu'on veut jusqu'à la terminaison de tous les fils */ + do { + /* période durant laquelle on ne veut pas être embêté par SIGCHLD */ + printf("\nProcessus de pid %d : Je masque SIGCHLD durant %d secondes\n", getpid(), DELAI); + /* masquer les signaux définis dans ens_signaux : SIGCHLD */ + sigprocmask(SIG_BLOCK, &ens_signaux, NULL); + sleep(DELAI); + + /* période durant laquelle on peut traiter le signal SIGCHLD */ + printf("\nProcessus de pid %d : Je démasque SIGCHLD\n", getpid()); + /* démasquer les signaux définis dans ens_signaux : SIGCHLD */ + sigprocmask(SIG_UNBLOCK, &ens_signaux, NULL); + sleep(2); + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigchld_wait.c b/TP3/api_systeme/pf_sigchld_wait.c new file mode 100644 index 0000000..af7cd1e --- /dev/null +++ b/TP3/api_systeme/pf_sigchld_wait.c @@ -0,0 +1,76 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* utilisation de SIGCHLD pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int wstatus, fils_termine; + + fils_termine = wait(&wstatus); + nb_fils_termines++; + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 300; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + sleep(2 + duree_sommeil * (fils -1)); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigchld_wait_sig_perdu.c b/TP3/api_systeme/pf_sigchld_wait_sig_perdu.c new file mode 100644 index 0000000..87d4f4c --- /dev/null +++ b/TP3/api_systeme/pf_sigchld_wait_sig_perdu.c @@ -0,0 +1,83 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* utilisation de SIGCHLD pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_sigchld(int signal_num) { + int wstatus, fils_termine; + + printf("\nJ'ai reçu le signal %d\n", signal_num); + fils_termine = wait(&wstatus); + nb_fils_termines++; + if WIFEXITED(wstatus) { /* fils terminé avec exit */ + printf("\nMon fils de pid %d a termine avec exit %d\n", + fils_termine, WEXITSTATUS(wstatus)); + } + else if WIFSIGNALED(wstatus) { /* fils tué par un signal */ + printf("\nMon fils de pid %d a ete tue par le signal %d\n", + fils_termine, WTERMSIG(wstatus)); + } + sleep(3); + return; +} + +int main() +{ + int fils, retour; + int duree_sommeil = 2; + + nb_fils_termines = 0; + /* associer traitant sigchld à SIGCHLD */ + signal(SIGCHLD, handler_sigchld); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + /* Vidange du tampon de sortie pour que le fils le récupère vide */ + fflush(stdout); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + //if (fils==3) duree_sommeil++; + sleep(duree_sommeil); + printf("\n Processus fils numero %d s'arrete\n", + fils); + exit(fils); /* normalement exit(0), mais on veut illustrer WEXITSTATUS */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + + //sleep(2); /* pour les besoins de l'outil de validation automatique */ + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigchld_waitpid_while.c b/TP3/api_systeme/pf_sigchld_waitpid_while.c new file mode 100644 index 0000000..c7f9e29 --- /dev/null +++ b/TP3/api_systeme/pf_sigchld_waitpid_while.c @@ -0,0 +1,80 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* SIGCHLD et waitpid pour prendre connaissance de la fin des fils */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les signaux */ +#include + +#define NB_FILS 4 /* nombre de fils */ + +int nb_fils_termines; /* variable globale car modifiée par le traitant */ + +/* Traitant du signal SIGCHLD */ +void handler_chld(int signal_num) { + int fils_termine, wstatus; + printf("\nJ'ai reçu le signal %d\n", signal_num); + if (signal_num == SIGCHLD) { + while ((fils_termine = (int) waitpid(-1, &wstatus, WNOHANG | WUNTRACED | WCONTINUED)) > 0) { + if WIFEXITED(wstatus) { + printf("\nMon fils de pid %d s'est arrete avec exit %d\n", fils_termine, WEXITSTATUS(wstatus)); + nb_fils_termines++; + } + else if WIFSIGNALED(wstatus) { + printf("\nMon fils de pid %d a recu le signal %d\n", fils_termine, WTERMSIG(wstatus)); + nb_fils_termines++; + } + else if (WIFCONTINUED(wstatus)) { + printf("\nMon fils de pid %d a ete relance \n", fils_termine); + } + else if (WIFSTOPPED(wstatus)) { + printf("\nMon fils de pid %d a ete suspendu \n", fils_termine); + } + sleep(1); + } + } + +} + +/* Programme principal : Un pere qui cree 3 fils */ + +int main() +{ + int fils, pid; + int duree_sommeil = 2; + + signal(SIGCHLD, handler_chld); + + printf("Je suis le processus principal %d, de pere %d\n", getpid(), getppid()); + nb_fils_termines = 0; + + for (fils=1; fils<=NB_FILS; fils++) { + pid = fork(); + if (pid<0) { // erreur fork + printf("Erreur fork\n"); + exit(1); + } + else if (pid==0) { //fils + printf("\n Processus fils num %d, de pid %d, de pere %d.\n", fils, getpid(), getppid()); + if (fils == 4) { + duree_sommeil = 300; + } + sleep(duree_sommeil); + printf("\n Processus fils num %d termine\n", fils); + exit(fils); /* normalement 0, mais on veut illustrer WEXITSTATUS */ + } + else {//pere + printf("\nProcessus pere de pid %d a cree un fils numero %d, de pid %d \n", getpid(), fils, pid); + } + } + + /* faire ce qu'on jusqu'à la terminaison de tous les fils */ + do { + /* faire ce qu'on veut */ + + } while (nb_fils_termines < NB_FILS); + printf("\nProcessus Principal termine\n"); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigint.c b/TP3/api_systeme/pf_sigint.c new file mode 100644 index 0000000..e4632e4 --- /dev/null +++ b/TP3/api_systeme/pf_sigint.c @@ -0,0 +1,67 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 600; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigint_ign_dfl.c b/TP3/api_systeme/pf_sigint_ign_dfl.c new file mode 100644 index 0000000..a6be450 --- /dev/null +++ b/TP3/api_systeme/pf_sigint_ign_dfl.c @@ -0,0 +1,73 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT : SIG_IGN et SIG_DFL */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 600; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + if (fils == 1) { + signal(SIGINT, SIG_IGN); + } + else if (fils == 2) { + signal(SIGINT, SIG_DFL); + } + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigint_ign_dfl_exec.c b/TP3/api_systeme/pf_sigint_ign_dfl_exec.c new file mode 100644 index 0000000..d946c10 --- /dev/null +++ b/TP3/api_systeme/pf_sigint_ign_dfl_exec.c @@ -0,0 +1,80 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT : SIG_IGN et SIG_DFL avec exec */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler_sigint(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 300; + + char ref_exec[]="./dormir"; /* exécutable */ + char arg0_exec[]="je dors"; /* argument0 du exec : nom donnée au processus */ + char arg1_exec[]="300"; /* argument0 du exec : durée de sommeil */ + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler_sigint); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + if (fils == 1) { + signal(SIGINT, SIG_IGN); + } + else if (fils == 2) { + signal(SIGINT, SIG_DFL); + } + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + execl(ref_exec, arg0_exec, arg1_exec, NULL); + /* on ne se retrouve ici que si exec échoue */ + printf("\n Processus fils numero %d : ERREUR EXEC\n", fils); + /* perror : affiche un message relatif à l'erreur du dernier appel systàme */ + perror(" exec "); + exit(fils); /* sortie avec le numéro di fils qui a échoué */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/pf_sigint_tstp_cont.c b/TP3/api_systeme/pf_sigint_tstp_cont.c new file mode 100644 index 0000000..850d88e --- /dev/null +++ b/TP3/api_systeme/pf_sigint_tstp_cont.c @@ -0,0 +1,70 @@ +/* Exemple d'illustration des primitives Unix : Un père et ses fils */ +/* Traitement du signal SIGINT */ + +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* traitement des signaux */ + +#define NB_FILS 3 /* nombre de fils */ + +/* Traitant du signal SIGINT */ +void handler(int signal_num) { + printf("\n Processus de pid %d : J'ai reçu le signal %d\n", + getpid(),signal_num); + return; +} + +/* dormir pendant nb_secondes secondes */ +/* à utiliser à la palce de sleep(duree), car sleep s'arrête */ +/* dès qu'un signal non ignoré est reçu */ +void dormir(int nb_secondes) +{ + int duree = 0; + while (duree < nb_secondes) { + sleep(1); + duree++; + } +} + +int main() +{ + int fils, retour; + int duree_sommeil = 120; + + /* associer un traitant au signal SIGINT */ + signal(SIGINT, handler); + signal(SIGTSTP, handler); + signal(SIGCONT, handler); + signal(SIGQUIT, handler); + + printf("\nJe suis le processus principal de pid %d\n", getpid()); + + for (fils = 1; fils <= NB_FILS; fils++) { + retour = fork(); + + /* Bonne pratique : tester systématiquement le retour des appels système */ + if (retour < 0) { /* échec du fork */ + printf("Erreur fork\n"); + /* Convention : s'arrêter avec une valeur > 0 en cas d'erreur */ + exit(1); + } + + /* fils */ + if (retour == 0) { + printf("\n Processus fils numero %d, de pid %d, de pere %d.\n", + fils, getpid(), getppid()); + dormir(duree_sommeil); + /* Important : terminer un processus par exit */ + exit(EXIT_SUCCESS); /* Terminaison normale (0 = sans erreur) */ + } + + /* pere */ + else { + printf("\nProcessus de pid %d a cree un fils numero %d, de pid %d \n", + getpid(), fils, retour); + } + } + dormir(duree_sommeil+2); + return EXIT_SUCCESS; +} diff --git a/TP3/api_systeme/sigaction_source_signal.c b/TP3/api_systeme/sigaction_source_signal.c new file mode 100644 index 0000000..46eba85 --- /dev/null +++ b/TP3/api_systeme/sigaction_source_signal.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +/* traitant sigaction, avec récupération du pid de l'émetteur du signal */ +void sigaction_sig (int num_sig, siginfo_t *siginfo, void * notused) { + int emetteur; + + // récupérer le numéro du porcessus qui a envoyé le signal + emetteur = siginfo->si_pid; + + printf("Processus %d a recu le signal %d envoye par le processus %d \n", getpid(), num_sig, emetteur); +} + +/* traitant qui peut être utilisé en modifiant l'initialisation de sigaction */ +void handler_sig (int num_sig) { + printf("Processus %d a recu le signal %d\n", getpid(), num_sig); +} + +/* Programme principal + * un père crée un fils et s'endort pendant 120 secondes + * le fils se termine après 3 secondes environs ==> envoi de SIGCHLD au père + * le père traite (traitant sigaction dessus) SIGCHLD, SIGINT, SIGTSTP et SIGCONT : + * afficahge du numéro du signal reçu et du pid de l'émetterur + * A tester avec CtrlC, CtrlZ, et envoie des signaux depuis un autre terminal */ + +int main() { + struct sigaction s; + + int pid, retval, duree_sommeil = 120; + + /* Il est très important d'initialiser sa_flags, éventuellement avec 0 */ + s.sa_flags = SA_SIGINFO; // pour récupérer les infos dans siginfo + s.sa_sigaction = sigaction_sig; + + /* On utilise soit sa_sigaction ou sa_handler */ + // s.sa_handler = handler_sig; + + retval = sigaction(SIGINT, &s, NULL); // 3eme paramètre à NULL, car on ne + retval = sigaction(SIGTSTP, &s, NULL); // souhaite pas récupérer l'ancien + retval = sigaction(SIGCONT, &s, NULL); // sigaction + retval = sigaction(SIGCHLD, &s, NULL); + + if(retval < 0) { + perror("sigaction failed"); + } + + pid = fork(); + switch (pid) { + case -1 : + printf("Erreur fork\n"); exit(1); + case 0 : //fils + sleep(3); + exit(0); + + default : //pere + printf("Je suis le processus %d et j'ai cree un fils de numéro %d\n", getpid(), pid); + printf("Je m'endors pendant %d secondes et je traite les signaux SIGINT, SIGTSTP, SIGCONT et SIGCHLD\n", duree_sommeil); + + int duree=0; + do { + sleep(1); // sleep est arrêté par la réception d'un signal + // on ne peut donc pas utiliser sleep(duree_sommeil) + duree++; + } while (duree < duree_sommeil); + } + return 0; +} diff --git a/TP3/copier.c b/TP3/copier.c new file mode 100644 index 0000000..8e4cce0 --- /dev/null +++ b/TP3/copier.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +#define BUFFSIZE 8 + +int main() { + + extern int errno; + + char file_read[] = "f_read.txt"; + char file_write[] = "f_write.txt"; + + char buffer[BUFFSIZE]; + bzero(buffer, sizeof(buffer)); + + // opening files + + int desc_fr = open(file_read, O_RDONLY); + if (desc_fr < 0) { + perror("ERROR opening f_read.txt"); + exit(errno); + } + + int desc_fw = open(file_write, O_WRONLY | O_CREAT | O_TRUNC, 0640); + if (desc_fw < 0) { + perror("ERROR opening f_write.txt"); + exit(errno); + } + + // reading and writing to buffer + + int ret_write = 0; + int ret_read = BUFFSIZE; + while (ret_read == BUFFSIZE) { + ret_read = read(desc_fr, buffer, BUFFSIZE); + if (ret_read < 0) { + perror("ERROR reading f_read.txt"); + exit(errno); + } + + printf("[%d] %.*s\n", ret_read, ret_read, buffer); + + ret_write = write(desc_fw, buffer, ret_read); + if (ret_write < 0) { + perror("ERROR writing to f_write.txt"); + exit(errno); + } + + bzero(buffer, sizeof(buffer)); + } + + // closing files + + int ret_close = 0; + ret_close = close(desc_fr); + if (ret_close < 0) { + perror("ERROR closing f_read.txt"); + exit(errno); + } + close(desc_fw); + if (ret_close < 0) { + perror("ERROR closing f_write.txt"); + exit(errno); + } + + return EXIT_SUCCESS; +} diff --git a/TP3/f_read.txt b/TP3/f_read.txt new file mode 100644 index 0000000..3f2642c --- /dev/null +++ b/TP3/f_read.txt @@ -0,0 +1 @@ +bonjour ceci est un message !! \ No newline at end of file diff --git a/TP3/f_write.txt b/TP3/f_write.txt new file mode 100644 index 0000000..e69de29 diff --git a/TP3/scruter.c b/TP3/scruter.c new file mode 100644 index 0000000..5b81fc6 --- /dev/null +++ b/TP3/scruter.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +int main() { + + extern int errno; + + char file[] = "temp"; + + // opening file + int desc_f = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0640); + if (desc_f < 0) { + perror("ERROR opening f_write.txt"); + exit(errno); + } + + // writing to file + + int ret_write = 0; + for (int i = 1; i <= 30; i++) { + + ret_write = write(desc_f, &i, sizeof(int)); + if (ret_write < 0) { + perror("ERROR writing to f_write.txt"); + exit(errno); + } + + sleep(1); + if (i % 10 == 0) { + lseek(desc_f, 0, SEEK_SET); + } + } + + // closing files + + int ret_close = 0; + ret_close = close(desc_f); + if (ret_close < 0) { + perror("ERROR closing f_read.txt"); + exit(errno); + } + + return EXIT_SUCCESS; +} diff --git a/TP3/verif_fichiers/Notice.md b/TP3/verif_fichiers/Notice.md new file mode 100644 index 0000000..fb60917 --- /dev/null +++ b/TP3/verif_fichiers/Notice.md @@ -0,0 +1,57 @@ +Avertissement +------------- +Le script de vérification `verif_fichiers.sh` doit être considéré comme un simple outil mis + à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, + et non comme une application de validation automatique de votre travail. Simplement, + si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation + effective. Et inversement. + +En particulier : + + - il est inutile de modifier le script pour qu'il donne une réponse `OK` : la validation + se fera sur nos propres outils. + - le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées + à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers + de manière intempestive, le script de vérification peut devenir invalide. + Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis + contre ce genre d'accidents. + - en revanche, le script de vérification fonctionne bien avec des réponses correctes. + Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être + quasi-certains que cela ne découle pas d'une erreur dans le script de test. + +Conventions de nommage +---------------------- + +Pour que le script de vérification `verif_fichiers.sh` puisse être appliqué : + + - les fichier source des programmes à vérifier doivent être **exactement** nommés `copier.c` + et `scruter.c`, et ils doivent être rangés dans le répertoire `etu`, situé au + même niveau que `verif_fichiers.sh` + - le répertoire contenant `verif_fichiers.sh` ne devra pas être modifié, en dehors de + l'ajout des fichiers sources `copier.c` et `scruter.c`. + + +Appel et résultats du script de vérification +-------------------------------------------- + +Le script `verif_fichiers.sh` doit être lancé depuis un terminal, le répertoire courant +étant le répertoire contenant `verif_fichiers.sh`. + +* Lorsqu'il est lancé sans option, `verif_fichiers.sh` effectue un diagnostic sur les +programmes `copier.c` puis `scruter.c`. +Si la vérification échoue pour l'un des programmes, le script affiche `KO`, sinon il affiche `OK`. +Notez que la mention `OK` est une condition nécessaire pour que la réponse soit juste, +mais que ce n'est pas une condition suffisante. +En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification +ne devrait afficher aucun warning suite à la compilation. +Lorsque le script `verif_fichiers.sh` se termine, il affiche un message `OK` ou `KO`. + Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut + tuer le processus exécutant le script. +Pour le programme `scruter.c` il se peut que la vérification affiche `??`. Cela signifie +que la vérification n'a pas pu se faire, mais pas forcément que le programme est erroné. +(Ce n'est cependant pas un très bon signe.) +* Lorsqu'il est lancé avec l'option `-s` (pour soumettre), le script prépare l'archive qui +pourra être déposée sur Moodle. L'archive créée par l'appel de `verif_fichiers.sh -s` se +trouve au même niveau que `verif_fichiers.sh` +Notez qu'il n'est pas nécessaire d'avoir obtenu des `OK` pour soumettre votre travail. Mais c'est +clairement préférable. \ No newline at end of file diff --git a/TP3/verif_fichiers/a/b/core b/TP3/verif_fichiers/a/b/core new file mode 100644 index 0000000..8ffd36b --- /dev/null +++ b/TP3/verif_fichiers/a/b/core @@ -0,0 +1 @@ +Reception \ No newline at end of file diff --git a/TP3/verif_fichiers/a/bar b/TP3/verif_fichiers/a/bar new file mode 100644 index 0000000..ace9d03 --- /dev/null +++ b/TP3/verif_fichiers/a/bar @@ -0,0 +1 @@ +255 diff --git a/TP3/verif_fichiers/a/hurz b/TP3/verif_fichiers/a/hurz new file mode 100644 index 0000000..e69de29 diff --git a/TP3/verif_fichiers/a/kro.c b/TP3/verif_fichiers/a/kro.c new file mode 100644 index 0000000..6cfb10d --- /dev/null +++ b/TP3/verif_fichiers/a/kro.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include //open +#include //open +#include //open + +int main () { + int i,fd,j=0; + fd = open("temp", O_RDONLY, NULL); + while (read(fd,&i,sizeof(i))> 0) j+=i; + printf("%d\n",j); + return 0; +} \ No newline at end of file diff --git a/TP3/verif_fichiers/a/pfurz b/TP3/verif_fichiers/a/pfurz new file mode 100644 index 0000000..aa4c6d9 Binary files /dev/null and b/TP3/verif_fichiers/a/pfurz differ diff --git a/TP3/verif_fichiers/a/s b/TP3/verif_fichiers/a/s new file mode 100644 index 0000000..d65874e --- /dev/null +++ b/TP3/verif_fichiers/a/s @@ -0,0 +1 @@ +OKOK diff --git a/TP3/verif_fichiers/etu/copier.c b/TP3/verif_fichiers/etu/copier.c new file mode 100644 index 0000000..c0f4977 --- /dev/null +++ b/TP3/verif_fichiers/etu/copier.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include + +#define BUFFSIZE 4096 + +int main(int argc, char* argv[]) { + + extern int errno; + + char* file_read = argv[1]; + char* file_write = argv[2]; + + char buffer[BUFFSIZE]; + bzero(buffer, sizeof(buffer)); + + // opening files + + int desc_fr = open(file_read, O_RDONLY); + if (desc_fr < 0) { + fprintf(stderr, "ERROR: opening %s : %s\n", file_read, strerror(errno)); + exit(errno); + } + + int desc_fw = open(file_write, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (desc_fw < 0) { + fprintf(stderr, "ERROR: opening %s : %s\n", file_write, strerror(errno)); + exit(errno); + } + + // reading and writing to buffer + + int ret_write = 0; + int ret_read = BUFFSIZE; + while (ret_read == BUFFSIZE) { + ret_read = read(desc_fr, buffer, BUFFSIZE); + if (ret_read < 0) { + fprintf(stderr, "ERROR: reading %s : %s\n", file_read, strerror(errno)); + exit(errno); + } + + printf("[%d] %.*s\n", ret_read, ret_read, buffer); // debug + + ret_write = write(desc_fw, buffer, ret_read); + if (ret_write < 0) { + fprintf(stderr, "ERROR: writing to %s : %s\n", file_write, strerror(errno)); + exit(errno); + } + + bzero(buffer, sizeof(buffer)); + } + + // closing files + + int ret_close = 0; + ret_close = close(desc_fr); + if (ret_close < 0) { + fprintf(stderr, "ERROR: closing %s : %s\n", file_read, strerror(errno)); + exit(errno); + } + close(desc_fw); + if (ret_close < 0) { + fprintf(stderr, "ERROR: closing %s : %s\n", file_write, strerror(errno)); + exit(errno); + } + + return EXIT_SUCCESS; +} + + +// perror \ No newline at end of file diff --git a/TP3/verif_fichiers/etu/scruter.c b/TP3/verif_fichiers/etu/scruter.c new file mode 100644 index 0000000..4a8fd36 --- /dev/null +++ b/TP3/verif_fichiers/etu/scruter.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include + +int main() { + + extern int errno; + + char file[] = "temp"; + + // opening file + int desc_f = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (desc_f < 0) { + fprintf(stderr, "ERROR: opening %s : %s\n", file, strerror(errno)); + exit(errno); + } + + // writing to file + + int ret_write = 0; + for (int i = 1; i <= 30; i++) { + + ret_write = write(desc_f, &i, sizeof(int)); + if (ret_write < 0) { + fprintf(stderr, "ERROR: opening %s : %s\n", file, strerror(errno)); + exit(errno); + } + + printf("%02d ", i); // debug + fflush(stdout); // debug + + sleep(1); + + if (i % 10 == 0) { + lseek(desc_f, 0, SEEK_SET); + printf("\r"); + } + } + printf("\n"); + + // closing files + + int ret_close = 0; + ret_close = close(desc_f); + if (ret_close < 0) { + fprintf(stderr, "ERROR: closing %s : %s\n", file, strerror(errno)); + exit(errno); + } + + return EXIT_SUCCESS; +} diff --git a/TP3/verif_fichiers/verif_fichiers.sh b/TP3/verif_fichiers/verif_fichiers.sh new file mode 100644 index 0000000..122ff77 --- /dev/null +++ b/TP3/verif_fichiers/verif_fichiers.sh @@ -0,0 +1,115 @@ +#!/bin/sh +# PM, le 13/4/21 +# Laurent 2021-04-14 + +if [ \( "a$1" = 'a-s' \) ] ; then + echo "préparation de l'archive à soumettre" + rep=`whoami|cut -d' ' -f 1`-tpFichiers + mkdir "$rep" + if [ ! \( -f etu/copier.c \) ] ; then + echo "note : fichier source copier.c (q10,11,12) non trouvé" + else + cp etu/copier.c "$rep" + fi + if [ ! \( -f etu/scruter.c \) ] ; then + echo "note : fichier source scruter.c non trouvé" + else + cp etu/scruter.c "$rep" + fi + cp a/s "$rep" + tar -cf "$rep".tar "$rep" + rm -r "$rep" + echo "prêt : vous pouvez déposer l'archive $rep.tar sous Moodle" + exit 0 +fi + +export PATH=.:$PATH +res=KO +nbOK=0 + +# compilation des scripts + +gcc -Wall etu/scruter.c -o scruter +gcc -Wall etu/copier.c -o copier +gcc -Wall a/kro.c -o cpt + +printf " =============== COPIER TEST ===============\n" + +#copier +copier a/pfurz ww +if [ $? -eq 0 ] ; then + nbOK=$((nbOK+1)) + printf "DEBUG: nbOK n°1 GOOD\n" +else + printf "DEBUG: nbOK n°1 FAILED, `errno $?`\n" +fi + +diff a/pfurz ww +if [ $? -eq 0 ] ; then + nbOK=$((nbOK+1)) + printf "DEBUG: nbOK n°2 GOOD\n" +else + printf "DEBUG: nbOK n°2 FAILED, `errno $?`\n" +fi + +# ce test là doit échouer, car a/b/core n'est pas écrivable (pas les droits) +copier a/pfurz a/b/core +if [ $? -ne 0 ] ; then + nbOK=$((nbOK+1)) + printf "DEBUG: nbOK n°3 GOOD\n" +else + printf "DEBUG: nbOK n°3 FAILED, `errno $?`\n" +fi + +# ce test doit aussi échouer, car plop n'existe pas +copier plop a/pfurz +if [ $? -ne 0 ] ; then + nbOK=$((nbOK+1)) + printf "DEBUG: nbOK n°4 GOOD\n" +else + printf "DEBUG: nbOK n°4 FAILED, `errno $?`\n" +fi + +# fermez bien vos fichiers +if [ $(cat etu/copier.c | grep close | wc -l) -gt 0 ] ; then + nbOK=$((nbOK+1)) + printf "DEBUG: nbOK n°5 GOOD\n" +else + printf "DEBUG: nbOK n°5 FAILED\n" +fi + +# pensez à utiliser perror +if [ $(cat etu/copier.c | grep perror | wc -l) -gt 0 ] ; then + nbOK=$((nbOK+1)) + printf "DEBUG: nbOK n°6 GOOD\n" +else + printf "DEBUG: nbOK n°6 FAILED\n" +fi + +if [ $nbOK -eq 6 ] ; then + res=OK +fi + +echo "copier : $res ($nbOK/6)" + +printf " =============== SCRUTER TEST ===============\n" + + +# scruter +scruter #> /dev/null +if [ -f "temp" ] ; then + cpt > foo + diff foo a/bar + if [ $? -eq 0 ] ; then + res2=OK + else + res2=KO + fi +else + res2="??" +fi +rm cpt +rm ww +echo "scruter : $res2" + +echo $res$res2 > a/s # sauvegarde des réponses dans un fichier, pour l'archivage diff --git a/TP_Shell/shell-filtrage.pdf b/TP_Shell/shell-filtrage.pdf new file mode 100644 index 0000000..c8a7265 Binary files /dev/null and b/TP_Shell/shell-filtrage.pdf differ diff --git a/TP_Shell/shell-script.pdf b/TP_Shell/shell-script.pdf new file mode 100644 index 0000000..e8fde68 Binary files /dev/null and b/TP_Shell/shell-script.pdf differ diff --git a/TP_Shell/shell_filtrage.zsh b/TP_Shell/shell_filtrage.zsh new file mode 100644 index 0000000..1c802db --- /dev/null +++ b/TP_Shell/shell_filtrage.zsh @@ -0,0 +1,30 @@ +# 1 : Afficher le nom de tous les fichiers dans la sous-arborescence du répertoire courant possédant le suffixe .o. +find . -name "*.o" + +# 2 : Compter le nombre de fichiers avec l'extension .o présents dans la sous-arborescence du répertoire courant. +find . -name "*.o" | wc -l + +# 3 : Supprimer tous les fichiers core non vides présents dans la sous-arborescence du répertoire courant. +find . -name "core" -size +0 -exec rm {} \; + +# 4 : Calculer la somme du nombre de caractères présents dans tous les fichiers ordinaires de l'arborescence issue du répertoire courant. +find . -type f -exec cat {} \; | wc -m + +# 5 : Compter le nombre de lignes où apparaît une chaîne donnée dans tous les fichiers du répertoire courant. +find . -type f -exec cat {} \; | grep "chaine de caractère" | wc -l + +# 6 : Lister les caractéristiques du troisième objet (objet = fichier ou répertoire) du répertoire courant dans l’ordre chronologique de modification. +ls -laht | head -n 4 | tail -n 1 +ls -laht | sed -n 4p + +# 7 : Compter le nombre de voyelles dans un fichier donné. +cat fichier.txt | tr -cd aeiouy | wc -m + +# 8 : Compter le nombre d’occurrences d’une chaîne (sans espace) dans un fichier. On ne compte qu’une occurrence du mot recherché par mot du fichier (ba dans “baba babababa ba” apparaît trois fois), et il peut se trouver plusieurs occurrences du mot recherché sur une même ligne. Le délimiteur entre les mots du fichier est l’espace. +cat fichier.txt | tr -s "motif" "*" | tr -cd "*" | wc -m + +# 9 : Lister pour tous les répertoires contenus dans le répertoire courant les informations suivantes : nom du propriétaire, nom du répertoire, date de dernière modification. (je donne quelques info en plus ici) +ls -lahd -- */ .*/ + +# 10 : Calculer la longueur de la plus longue ligne d’un fichier donné. +wc -L fichier.txt \ No newline at end of file diff --git a/TP_Shell/shell_script.zsh b/TP_Shell/shell_script.zsh new file mode 100644 index 0000000..ff35052 --- /dev/null +++ b/TP_Shell/shell_script.zsh @@ -0,0 +1,117 @@ +# 1 +function rmcore { + find $1 -name "core" -size +0 -exec rm {} \; + return 0 +} + +# 2 +function satisfait { + ans="\0" + until [ ${ans:0:1} = "o" ] || [ ${ans:0:1} = "n" ] + do + echo -n "Etes-vous satisfait ? (o/n) " + read ans + done + return 0 +} + +# 3 +# Via la commande "last | head" un utilisateur peut savoir précisement la date à laquelle il s'est deconnecté. +# Ensuite en executant: "find ~" il peut ainsi regarder quels fichiers on été modifiés. + +function lastmodif { + find ~ -printf "%AFT%Ar %TFT%Tr %p \n" | sort + tput setaf 1 && echo "last access last modified" + echo -n "last logout : " + tput setaf 1 && last `whoami` --time-format=iso | head -n 2 | tail -n 1 | awk '{print $5}' | cut -c -19 && + return 0 +} + +# 4 plutôt lent +function arbre { + if [ $1 = "-d" ] + then + list=`find $2 -type d -printf "%d %f\n"` + else + list=`find $1 -printf "%d %f\n"` + fi + + while IFS= read -r line; do + nb=`echo $line | awk '{print $1}'` + printf '\t%.0s ' {0..$nb} + echo $line | awk '{print $2}' + done <<< "$list" + return 0 +} + +# 5 +function profondeur { + find $1 -printf "%d %p\n" | sort -n | tail -n 1 + return 0 +} + +# 6 +# on peut créer un alias qui supprime automatiquement les options -T et -e et qui remplace automatiquement -t par -x + +# 7 +function inv { + for (( i=$#1-1; i>=0; i-- )) + do + echo -n ${1:$i:1} + done + return 0 +} + +# 8 +alias lsd="ls -lahd -- */ .*/" + +# 9 # TODO: mode d'emploi + multi mois +function arbre { + if [ $1 = "-d" ] + then + find $2 -type d -printf "%Tb %p\n" | grep $3 | awk '{print $2}' + else + find . -printf "%Tb %p\n" | grep $1 | awk '{print $2}' + fi + return 0 +} + +# 10 +function tuer { + list=`ps -eo pid,comm | grep $1` + + if [ `echo $list | awk '{ print $2 }' | sort | uniq | wc -l` -gt 1 ] + then + return -1 + else + echo $list | awk '{ print $1 }' | xargs kill + fi + return 0 +} + +# 11 +function compter { + cat $1 | grep -o $2 | wc -l + return 0 +} + +# 12 +function voyelles { + echo $1 | egrep -Eo "*[aeiouy]" | sort | uniq | tr -d "\n" + return 0 +} + +# 13 +... | awk '{ print length " " $0 }' | sort -n | tail -n 1 | awk '{$1=""}1' + +# 14 +function multipath { + echo $PATH | tr ':' '\n' | xargs -I{} find {} -type l -printf "%l\n" | sort | uniq -d + return 0 +} + +# 15 +function doublons { + cat $1 | tr -d "\n" | grep -E '(\b.+) \1\b' + return 0 +} \ No newline at end of file diff --git a/TP_Shell/verif/F1 b/TP_Shell/verif/F1 new file mode 100644 index 0000000..55cc616 --- /dev/null +++ b/TP_Shell/verif/F1 @@ -0,0 +1 @@ +find . -name "*.o" -type f diff --git a/TP_Shell/verif/F11 b/TP_Shell/verif/F11 new file mode 100644 index 0000000..e1ee272 --- /dev/null +++ b/TP_Shell/verif/F11 @@ -0,0 +1 @@ +cat $1 | wc -L diff --git a/TP_Shell/verif/F2 b/TP_Shell/verif/F2 new file mode 100644 index 0000000..ae2494a --- /dev/null +++ b/TP_Shell/verif/F2 @@ -0,0 +1 @@ +find . -name "*.o" -type f | wc -l diff --git a/TP_Shell/verif/F3 b/TP_Shell/verif/F3 new file mode 100644 index 0000000..0670ab9 --- /dev/null +++ b/TP_Shell/verif/F3 @@ -0,0 +1 @@ +find . -name "core" -size +0 -exec rm {} \; diff --git a/TP_Shell/verif/F8 b/TP_Shell/verif/F8 new file mode 100644 index 0000000..7635633 --- /dev/null +++ b/TP_Shell/verif/F8 @@ -0,0 +1 @@ +cat $1 | tr -cd aeiouyAEIOUY | wc -m \ No newline at end of file diff --git a/TP_Shell/verif/Notice.html b/TP_Shell/verif/Notice.html new file mode 100644 index 0000000..b26cffd --- /dev/null +++ b/TP_Shell/verif/Notice.html @@ -0,0 +1,40 @@ + + + + + + + + + + +

Avertissement

+

Le script de vérification verif.sh doit être considéré comme un simple outil mis à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, et non comme une application de validation automatique de votre travail. Simplement, si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation effective. Et inversement.

+

En particulier :

+
    +
  • il est inutile de modifier le script pour qu'il donne des réponses OK: la validation se fera sur nos propres outils.
  • +
  • le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées à l'exécution de vos programmes. Par exemple si vos commandes détruisent des fichiers de manière intempestive, le script de vérification peut devenir invalide. Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis contre ce genre d'accidents.
  • +
  • en revanche, le script de vérification fonctionne bien avec des réponses correctes. Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être quasi-certains que cela découle d'une erreur dans l'exercice qui est en cours de test autour de cette ligne, et non pas dans le script de test.
  • +
+

Conventions de nommage

+

Pour que le script de vérification verif.sh puisse être appliqué :

+
    +
  • pour chaque question, la réponse devra être fournie dans un fichier distinct
  • +
  • le nom du fichier réponse sera exactement composé du numéro de la question, précédé d'un 'F' si la question est un exercice sur les filtres, et d'un 'S' si la question est un exercice sur les scripts.
    +Par exemple, 'F8' serait le nom du fichier contenant la réponse à l'exercice 8 du TP filtres.
  • +
  • les fichiers contenant les réponses devront être placés dans le même répertoire que verif.sh, au même niveau que verif.sh.
  • +
  • les fichiers contenant les réponses devront être exécutables (appliquer chmodau besoin)
  • +
  • le répertoire contenant verif.sh ne devra pas être modifié, en dehors de l'ajout des fichiers de réponse.
  • +
+

Conventions de lancement

+

Pour les exercices du TP filtres, les énoncés font souvent mention d'un "fichier donné". Pour le script de vérification, cela est compris comme un fichier donné en paramètre, et le script de vérification s'attend à ce que la réponse désigne ce fichier comme $1. Par exemple, pour l'énoncé
+"Afficher les 10 premières lignes d'un fichier donné"
+la réponse attendue serait
+head $1

+

Appel et résultats du script de vérification

+

Le script verif.sh doit être lancé depuis un terminal, le répertoire courant étant le répertoire contenant verif.sh.

+

Le script verif.sh vérifie les réponses dans l'ordre lexicographique des noms de fichier. Si une réponse est manquante ou en échec le script affiche KO pour cette réponse, sinon il affiche OK.
+Notez que la mention OK est une condition nécessaire pour que la réponse soit juste, mais que ce n'est pas une condition suffisante.

+

Lorsque le script verif.sh se termine, il affiche un message fini. Il est possible qu'une réponse provoque le blocage du script. Dans ce cas, il faut tuer le processus exécutant le script, et corriger (ou supprimer/renommer) la réponse ayant provoqué le blocage (qui devrait être la réponse suivant la dernière réponse pour laquelle KO ou OK a été affiché)

+ + diff --git a/TP_Shell/verif/Notice.md b/TP_Shell/verif/Notice.md new file mode 100644 index 0000000..a584212 --- /dev/null +++ b/TP_Shell/verif/Notice.md @@ -0,0 +1,67 @@ +Avertissement +------------- +Le script de vérification `verif.sh` doit être considéré comme un simple outil mis à votre +disposition, pour vous fournir une indication quant à la viabilité de vos réponses, et non +comme une application de validation automatique de votre travail. Simplement, si vous passez +la vérification, vous pouvez avoir bon espoir quant à l'évaluation effective. Et inversement. + +En particulier : + + - il est inutile de modifier le script pour qu'il donne des réponses `OK`: la validation + se fera sur nos propres outils. + - le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées + à l'exécution de vos programmes. Par exemple si vos commandes détruisent des fichiers + de manière intempestive, le script de vérification peut devenir invalide. + Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis + contre ce genre d'accidents. + - en revanche, le script de vérification fonctionne bien avec des réponses correctes. + Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être + quasi-certains que cela découle d'une erreur dans l'exercice qui est en cours de test + autour de cette ligne, et non pas dans le script de test. + +Conventions de nommage +---------------------- + +Pour que le script de vérification `verif.sh` puisse être appliqué : + + - pour chaque question, la réponse devra être fournie dans un fichier distinct + - le nom du fichier réponse sera **exactement** composé du numéro de la question, + précédé d'un 'F' si la question est un exercice sur les filtres, + et d'un 'S' si la question est un exercice sur les scripts. + Par exemple, 'F8' serait le nom du fichier contenant la réponse à l'exercice 8 du TP filtres. + - les fichiers contenant les réponses devront être placés dans le même répertoire que + `verif.sh`, au même niveau que `verif.sh`. + - les fichiers contenant les réponses devront être exécutables (appliquer `chmod`au besoin) + - le répertoire contenant `verif.sh` ne devra pas être modifié, en dehors de l'ajout des + fichiers de réponse. + +Conventions de lancement +------------------------ + +Pour les exercices du TP filtres, les énoncés font souvent mention d'un "fichier donné". +Pour le script de vérification, cela est compris comme un fichier donné *en paramètre*, +et le script de vérification s'attend à ce que la réponse désigne ce fichier comme `$1`. +Par exemple, pour l'énoncé +"Afficher les 10 premières lignes d'un fichier donné" +la réponse attendue serait +`head $1` + +Appel et résultats du script de vérification +-------------------------------------------- + +Le script `verif.sh` doit être lancé depuis un terminal, le répertoire courant étant le +répertoire contenant `verif.sh`. + +Le script `verif.sh` vérifie les réponses dans l'ordre lexicographique des noms de fichier. +Si une réponse est manquante ou en échec le script affiche `KO` pour cette réponse, sinon +il affiche `OK`. +Notez que la mention `OK` est une condition nécessaire pour que la réponse soit juste, +mais que ce n'est pas une condition suffisante. + +Lorsque le script `verif.sh` se termine, il affiche un message `fini`. Il est possible +qu'une réponse provoque le blocage du script. Dans ce cas, il faut tuer le processus +exécutant le script, et corriger (ou supprimer/renommer) la réponse ayant provoqué + le blocage (qui devrait être la réponse suivant la dernière réponse pour laquelle `KO` + ou `OK` a été affiché) + + \ No newline at end of file diff --git a/TP_Shell/verif/S2 b/TP_Shell/verif/S2 new file mode 100644 index 0000000..3678e26 --- /dev/null +++ b/TP_Shell/verif/S2 @@ -0,0 +1,7 @@ +ans="\0" +until [ ${ans:0:1} = "o" ] || [ ${ans:0:1} = "n" ] +do + echo -n "Etes-vous satisfait ? (o/n) " + read ans + echo +done diff --git a/TP_Shell/verif/S4 b/TP_Shell/verif/S4 new file mode 100644 index 0000000..573678d --- /dev/null +++ b/TP_Shell/verif/S4 @@ -0,0 +1,12 @@ +if [ $1 = "-d" ] +then + list=`find $2 -type d -printf "%d %f\n"` +else + list=`find $1 -printf "%d %f\n"` +fi + +while IFS= read -r line; do + nb=`echo $line | awk '{print $1}'` + printf '\t%.0s ' {0..$nb} + echo $line | awk '{print $2}' +done <<< "$list" \ No newline at end of file diff --git a/TP_Shell/verif/S6 b/TP_Shell/verif/S6 new file mode 100644 index 0000000..8b2721f --- /dev/null +++ b/TP_Shell/verif/S6 @@ -0,0 +1,10 @@ +for var in "$@" +do + if [ $var = "-t" ] + then + echo -n "-x " + elif [ ! $var = "-T" ] && [ ! $var = "-e" ] + then + echo -n "$var " + fi +done diff --git a/TP_Shell/verif/S7 b/TP_Shell/verif/S7 new file mode 100644 index 0000000..d68acff --- /dev/null +++ b/TP_Shell/verif/S7 @@ -0,0 +1,4 @@ +for (( i=$#1-1; i>=0; i-- )) +do + echo -n ${1:$i:1} +done \ No newline at end of file diff --git a/TP_Shell/verif/a/b/core b/TP_Shell/verif/a/b/core new file mode 100644 index 0000000..e69de29 diff --git a/TP_Shell/verif/a/bar b/TP_Shell/verif/a/bar new file mode 100644 index 0000000..0009c35 --- /dev/null +++ b/TP_Shell/verif/a/bar @@ -0,0 +1 @@ +find . -name c${1}re | wc -l \ No newline at end of file diff --git a/TP_Shell/verif/a/hurz b/TP_Shell/verif/a/hurz new file mode 100644 index 0000000..84ec034 --- /dev/null +++ b/TP_Shell/verif/a/hurz @@ -0,0 +1 @@ +nnnnnnnnnnnnnnnnnnn \ No newline at end of file diff --git a/TP_Shell/verif/a/kro.o b/TP_Shell/verif/a/kro.o new file mode 100644 index 0000000..e69de29 diff --git a/TP_Shell/verif/a/pfurz b/TP_Shell/verif/a/pfurz new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/TP_Shell/verif/a/pfurz @@ -0,0 +1 @@ +2 diff --git a/TP_Shell/verif/a/s b/TP_Shell/verif/a/s new file mode 100644 index 0000000..4cd1015 --- /dev/null +++ b/TP_Shell/verif/a/s @@ -0,0 +1,11 @@ +y +bof +i + +o +h +n +x +non +oui +Z diff --git a/TP_Shell/verif/foo b/TP_Shell/verif/foo new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/TP_Shell/verif/foo @@ -0,0 +1 @@ +1 diff --git a/TP_Shell/verif/lala.o b/TP_Shell/verif/lala.o new file mode 100644 index 0000000..224fd23 --- /dev/null +++ b/TP_Shell/verif/lala.o @@ -0,0 +1 @@ +lala diff --git a/TP_Shell/verif/verif.sh b/TP_Shell/verif/verif.sh new file mode 100644 index 0000000..b17a15a --- /dev/null +++ b/TP_Shell/verif/verif.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# PM, le 21/3/21 + +export PATH=.:$PATH + + +res=KO +if [ \( -f "F1" \) -a \( "`F1 | grep a | tr '[:print:]\n' 'n'`" = "`cat a/hurz`" \) ] ; then + res=OK +fi +echo "F1 : "$res + + +res=KO +if [ \( -f "F2" \) -a \( "`F2`" -eq "`cat a/pfurz`" \) ] ; then + res=OK +fi +echo "F2 : "$res + +res=KO +if [ \( -f "F3" \) -a \( -f "a/hurz" \) -a \( -f "a/pfurz" \) ] ; then + cp a/hurz a/core + cp a/pfurz core + touch a/b/core + F3 + if [ "`a/bar o`" -eq "`cat foo`" ] ; then + res=OK + fi +fi +echo "F3 : "$res + +res=KO +if [ \( -f "F8" \) -a \( "`F8 Notice.md`" -eq 1010 \) ] ; then + res=OK +fi +echo "F8 : "$res + +res=KO +if [ \( -f "F11" \) -a \( "`F11 Notice.md`" -le 100 \) -a \( "`F11 Notice.md`" -gt 80 \) ] ; then + res=OK +fi +echo "F11 : "$res + +res=KO +if [ \( -f "S2" \) -a \( \( "`S2 < a/s | wc -l `" -eq 5 \) -o \( "`S2 < a/s | wc -l `" -eq 6 \) \) ] ; then + res=OK +fi +echo "S2 : "$res + +res=KO +if [ -f "S4" -a \( "`S4 a | wc -l `" -eq 9 \) ] ; then + res=OK +fi +echo "S4 : "$res +echo "Note : pour ce test (S4), OK et KO ne sont qu'indicatifs" + +res=KO +if [ -f "S6" ] ; then + S6 echo -v -o toto -T 14 -S -I -e -t > test + if [ "`cat test`" = '-v -o toto -S -I -x' ] ; then + res=OK + fi + cat test + rm test +fi +echo "S6 : "$res + +res=KO +if [ \( -f "S7" \) -a \( "`S7 esope`" = epose \) ] ; then + res=OK +fi +echo "S7 : "$res + +echo "fini" diff --git a/TP_select/filtrage-squelette.c b/TP_select/filtrage-squelette.c new file mode 100644 index 0000000..d5a2435 --- /dev/null +++ b/TP_select/filtrage-squelette.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 512 + +void traiter(char tampon[], char cde, int nb) +{ + int i; + switch (cde) + { + case 'X': + break; + case 'Q': + exit(0); + break; + case 'R': + write(1, tampon, nb); + break; + case 'M': + for (i = 0; i < nb; i++) + { + tampon[i] = toupper(tampon[i]); + } + write(1, tampon, nb); + break; + case 'm': + for (i = 0; i < nb; i++) + { + tampon[i] = tolower(tampon[i]); + } + write(1, tampon, nb); + break; + default: + printf("????\n"); + } +} + +int main(int argc, char *argv[]) +{ + int p[2]; + pid_t pid; + int d, nlus; + char buf[BUFSIZE]; + char commande = 'R'; /* mode normal */ + if (argc != 2) + { + printf("utilisation : %s \n", argv[0]); + exit(1); + } + + if (pipe(p) == -1) + { + perror("pipe"); + exit(2); + } + + pid = fork(); + if (pid == -1) + { + perror("fork"); + exit(3); + } + if (pid == 0) + { /* fils */ + d = open(argv[1], O_RDONLY); + if (d == -1) + { + fprintf(stderr, "Impossible d'ouvrir le fichier "); + perror(argv[1]); + exit(4); + } + + close(p[0]); /* pour finir malgre tout, avec sigpipe */ + while (true) + { + while ((nlus = read(d, buf, BUFSIZE)) > 0) + { + /* read peut lire moins que le nombre d'octets demandes, en + * particulier lorsque la fin du fichier est atteinte. */ + write(p[1], buf, nlus); + sleep(5); + } + sleep(5); + printf("on recommence...\n"); + lseek(d, (off_t)0, SEEK_SET); + } + } + else + { /* pere */ + close(p[1]); + system("stty -icanon min 1"); // saisie entrees clavier sans tampon + + /* a completer */ + + while (true) + { + + /* debut code a completer et adapter */ + + read(0, &commande, sizeof(char)); + printf("-->%c\n", commande); + + bzero(buf, BUFSIZE); // nettoyage + if ((nlus = read(p[0], buf, BUFSIZE)) > 0) + { + traiter(buf, commande, nlus); + } + + /* fin code a completer et adapter */ + + sleep(1); + } + } + return 0; +} \ No newline at end of file diff --git a/TP_select/select-fcntl.pdf b/TP_select/select-fcntl.pdf new file mode 100644 index 0000000..817b700 Binary files /dev/null and b/TP_select/select-fcntl.pdf differ diff --git a/TP_tubes/TPredirections-tubes.pdf b/TP_tubes/TPredirections-tubes.pdf new file mode 100644 index 0000000..3a9e618 Binary files /dev/null and b/TP_tubes/TPredirections-tubes.pdf differ diff --git a/TP_tubes/verif_tubes/Notice.html b/TP_tubes/verif_tubes/Notice.html new file mode 100644 index 0000000..81cb607 --- /dev/null +++ b/TP_tubes/verif_tubes/Notice.html @@ -0,0 +1,43 @@ + + + + + + + + + + +

Avertissement

+

Le script de vérification verif_tubes.sh doit être considéré comme un simple outil mis à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, et non comme une application de validation automatique de votre travail. Simplement, si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation effective. Et inversement.

+

En particulier :

+
    +
  • il est inutile de modifier le script pour qu'il donne une réponse OK : la validation se fera sur nos propres outils.
  • +
  • le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers de manière intempestive, le script de vérification peut devenir invalide. Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis contre ce genre d'accidents.
  • +
  • en revanche, le script de vérification fonctionne bien avec des réponses correctes. Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être quasi-certains que cela ne découle pas d'une erreur dans le script de test.
  • +
+

Conventions de nommage

+

Pour que le script de vérification verif_tubes.sh puisse être appliqué :

+
    +
  • les fichier source du programme à vérifier doit être exactement nommé wgw.c, et il doit être rangé dans le répertoire etu, situé au même niveau que verif_tubes.sh
  • +
  • le répertoire contenant verif_tubes.sh ne devra pas être modifié, en dehors de l'ajout du fichier source wgw.c.
  • +
+

Appel et résultats du script de vérification

+

Le script verif_tubes.sh doit être lancé depuis un terminal, le répertoire courant étant le répertoire contenant verif_tubes.sh.

+
    +
  • Lorsqu'il est lancé sans option, verif_tubes.sh effectue un diagnostic sur le programme wgw.c.

    +
      +
    • Si la vérification échoue, le script affiche KO, sinon il affiche OK.
    • +
    • Lorsqu'il affiche KO, il affiche aussi une courte indication sur le(s) point(s) pouvant poser problème. La lecture du script peut au besoin vous éclairer sur la cause de l'indication.
    • +
    • Notez que la mention OK est une condition nécessaire pour que la réponse soit juste, mais que ce n'est pas une condition suffisante.
      +En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification ne devrait afficher aucun warning suite à la compilation.
      +
    • +
    • Lorsque le script verif_tubes.sh se termine, il affiche un message OK ou KO.
      +Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut tuer le processus exécutant le script.
      +
    • +
  • +
  • Lorsqu'il est lancé avec l'option -s ('s' pour "soumettre"), le script prépare l'archive qui pourra être déposée sur Moodle. L'archive créée par l'appel de verif_tubes.sh -s se trouve au même niveau que verif_tubes.sh
    +Notez qu'il n'est pas nécessaire d'avoir obtenu un OK pour soumettre votre travail. Mais c'est clairement préférable.

  • +
+ + diff --git a/TP_tubes/verif_tubes/Notice.md b/TP_tubes/verif_tubes/Notice.md new file mode 100644 index 0000000..0fdeb4f --- /dev/null +++ b/TP_tubes/verif_tubes/Notice.md @@ -0,0 +1,57 @@ +Avertissement +------------- +Le script de vérification `verif_tubes.sh` doit être considéré comme un simple outil mis + à votre disposition, pour vous fournir une indication quant à la viabilité de vos réponses, + et non comme une application de validation automatique de votre travail. Simplement, + si vous passez la vérification, vous pouvez avoir bon espoir quant à l'évaluation + effective. Et inversement. + +En particulier : + + - il est inutile de modifier le script pour qu'il donne une réponse `OK` : la validation + se fera sur nos propres outils. + - le script n'est pas protégé contre les erreurs résultant de (mauvaises) actions liées + à l'exécution de vos programmes. Par exemple si votre programme détruit des fichiers + de manière intempestive, le script de vérification peut devenir invalide. + Il est donc prudent de prévoir une sauvegarde de l'original, si vous voulez être prémunis + contre ce genre d'accidents. + - en revanche, le script de vérification fonctionne bien avec des réponses correctes. + Par conséquent, si une erreur est signalée sur une ligne du script, vous pouvez être + quasi-certains que cela ne découle pas d'une erreur dans le script de test. + +Conventions de nommage +---------------------- + +Pour que le script de vérification `verif_tubes.sh` puisse être appliqué : + + - les fichier source du programme à vérifier doit être **exactement** nommé `wgw.c`, et + il doit être rangé dans le répertoire `etu`, situé au même niveau que `verif_tubes.sh` + - le répertoire contenant `verif_tubes.sh` ne devra pas être modifié, en dehors de + l'ajout du fichier source `wgw.c`. + + +Appel et résultats du script de vérification +-------------------------------------------- + +Le script `verif_tubes.sh` doit être lancé depuis un terminal, le répertoire courant +étant le répertoire contenant `verif_tubes.sh`. + + * Lorsqu'il est lancé sans option, `verif_tubes.sh` effectue un diagnostic sur le +programme `wgw.c`. + + - Si la vérification échoue, le script affiche `KO`, sinon il affiche `OK`. + - Lorsqu'il affiche `KO`, il affiche aussi une courte indication sur le(s) point(s) + pouvant poser problème. La lecture du script peut au besoin vous éclairer sur la cause + de l'indication. + - Notez que la mention `OK` est une condition nécessaire pour que la réponse soit juste, +mais que ce n'est pas une condition suffisante. +En particulier, vous êtes laissés juges de leur pertinence, mais a priori la vérification +ne devrait afficher aucun warning suite à la compilation. + - Lorsque le script `verif_tubes.sh` se termine, il affiche un message `OK` ou `KO`. + Il est possible que la réponse fournie provoque le blocage du script. Dans ce cas, il faut + tuer le processus exécutant le script. + * Lorsqu'il est lancé avec l'option `-s` ('s' pour "soumettre"), le script prépare l'archive qui +pourra être déposée sur Moodle. L'archive créée par l'appel de `verif_tubes.sh -s` se +trouve au même niveau que `verif_tubes.sh` +Notez qu'il n'est pas nécessaire d'avoir obtenu un `OK` pour soumettre votre travail. Mais c'est +clairement préférable. \ No newline at end of file diff --git a/TP_tubes/verif_tubes/a/b/core b/TP_tubes/verif_tubes/a/b/core new file mode 100644 index 0000000..e69de29 diff --git a/TP_tubes/verif_tubes/a/s b/TP_tubes/verif_tubes/a/s new file mode 100644 index 0000000..d86bac9 --- /dev/null +++ b/TP_tubes/verif_tubes/a/s @@ -0,0 +1 @@ +OK diff --git a/TP_tubes/verif_tubes/etu/wgw.c b/TP_tubes/verif_tubes/etu/wgw.c new file mode 100644 index 0000000..0bc5795 --- /dev/null +++ b/TP_tubes/verif_tubes/etu/wgw.c @@ -0,0 +1,94 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ +#include + +int main(int argc, char *argv[]) +{ + extern int errno; + int retour; + int pipes[2][2]; + + if (pipe(pipes[0]) < 0) + { // pipe failed + fprintf(stderr, "ERROR: pipe error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + if (pipe(pipes[1]) < 0) + { // pipe failed + fprintf(stderr, "ERROR: pipe error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if ((retour = fork()) < 0) + { // fork failed + fprintf(stderr, "ERROR: fork error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + else if (retour == 0) + { ////////// pipes[0][0] --> grep --> pipes[1][1] ////////// + if (dup2(pipes[0][0], 0) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if (dup2(pipes[1][1], 1) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + close(pipes[0][1]); + close(pipes[1][0]); + + execlp("grep", "grep", argv[1], NULL); + fprintf(stderr, "ERROR: execlp error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if ((retour = fork()) < 0) + { // fork failed + fprintf(stderr, "ERROR: fork error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + else if (retour == 0) + { ////////// pipes[1][0] --> wc --> stdout ////////// + if (dup2(pipes[1][0], 0) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + close(pipes[0][0]); + close(pipes[0][1]); + close(pipes[1][1]); + + execlp("wc", "wc", "-l", NULL); + fprintf(stderr, "ERROR: execlp error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + ////////// stdin --> who --> pipes[0][0] ////////// + if (dup2(pipes[0][1], 1) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + close(pipes[0][0]); + close(pipes[1][0]); + close(pipes[1][1]); + + execlp("who", "who", NULL); + fprintf(stderr, "ERROR: execlp error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + + // on atteint jamais cet endroit + return EXIT_FAILURE; +} + +// perror \ No newline at end of file diff --git a/TP_tubes/verif_tubes/foo b/TP_tubes/verif_tubes/foo new file mode 100644 index 0000000..ace9d03 --- /dev/null +++ b/TP_tubes/verif_tubes/foo @@ -0,0 +1 @@ +255 diff --git a/TP_tubes/verif_tubes/hurz b/TP_tubes/verif_tubes/hurz new file mode 100644 index 0000000..c97c85b --- /dev/null +++ b/TP_tubes/verif_tubes/hurz @@ -0,0 +1,2 @@ +30 +31 diff --git a/TP_tubes/verif_tubes/lala.o b/TP_tubes/verif_tubes/lala.o new file mode 100644 index 0000000..e8c4d10 --- /dev/null +++ b/TP_tubes/verif_tubes/lala.o @@ -0,0 +1,8 @@ +Notice.html +Notice.md +a +foo +lala.o +miniminishell.c +ms +verif.sh diff --git a/TP_tubes/verif_tubes/pfurz b/TP_tubes/verif_tubes/pfurz new file mode 100644 index 0000000..d8263ee --- /dev/null +++ b/TP_tubes/verif_tubes/pfurz @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/TP_tubes/verif_tubes/verif_tubes.sh b/TP_tubes/verif_tubes/verif_tubes.sh new file mode 100644 index 0000000..ab626c5 --- /dev/null +++ b/TP_tubes/verif_tubes/verif_tubes.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# PM, 1/5/21 : version initiale + +if [ \( "a$1" = 'a-s' \) ] ; then + echo "préparation de l'archive à soumettre" + rep=`whoami|cut -d' ' -f 1`-tpTubes + mkdir "$rep" + if [ ! \( -f etu/wgw.c \) ] ; then + echo "note : fichier source wgw.c non trouvé" + else + cp etu/wgw.c "$rep" + fi + if [ -f a/s ] ; then + cp a/s "$rep" + fi + tar -cf "$rep".tar "$rep" + rm -r "$rep" + echo "prêt : vous pouvez déposer l'archive $rep.tar sous Moodle" + exit 0 +fi + +export PATH=.:$PATH +res=KO +nbOK=0 + +gcc -Wall etu/wgw.c -o wgw + +who | grep `whoami` | wc -l > ressh +wgw `whoami`> reswgw & + +sleep 2 + +diff reswgw ressh > /dev/null +if [ $? -eq 0 ] ; then + nbOK=$((nbOK+1)) +else + echo "résultat ?" +fi + +if [ $(pgrep wgw | wc -l) -eq 0 ] ; then + nbOK=$((nbOK+1)) +else + echo "terminaison ?" +fi + +if [ $(cat etu/wgw.c | grep perror | wc -l) -gt 0 ] ; then + nbOK=$((nbOK+1)) +else + echo "test des retours appels système ?" +fi + +if [ $nbOK -eq 3 ] ; then + res=OK +fi + +rm res* +rm wgw +echo "bilan : $res ($nbOK/3)" + +echo $res > a/s \ No newline at end of file diff --git a/TP_tubes/wgw.c b/TP_tubes/wgw.c new file mode 100644 index 0000000..c449071 --- /dev/null +++ b/TP_tubes/wgw.c @@ -0,0 +1,92 @@ +#include /* entrées sorties */ +#include /* pimitives de base : fork, ...*/ +#include /* exit */ +#include /* wait */ +#include /* opérations sur les chaines */ +#include /* opérations sur les fichiers */ +#include + +int main(int argc, char *argv[]) +{ + extern int errno; + int retour; + int pipes[2][2]; + + if (pipe(pipes[0]) < 0) + { // pipe failed + fprintf(stderr, "ERROR: pipe error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + if (pipe(pipes[1]) < 0) + { // pipe failed + fprintf(stderr, "ERROR: pipe error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if ((retour = fork()) < 0) + { // fork failed + fprintf(stderr, "ERROR: fork error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + else if (retour == 0) + { ////////// pipes[0][0] --> grep --> pipes[1][1] ////////// + if (dup2(pipes[0][0], 0) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if (dup2(pipes[1][1], 1) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + close(pipes[0][1]); + close(pipes[1][0]); + + execlp("grep", "grep", argv[1], NULL); + fprintf(stderr, "ERROR: execlp error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if ((retour = fork()) < 0) + { // fork failed + fprintf(stderr, "ERROR: fork error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + else if (retour == 0) + { ////////// pipes[1][0] --> wc --> stdout ////////// + if (dup2(pipes[1][0], 0) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + close(pipes[0][0]); + close(pipes[0][1]); + close(pipes[1][1]); + + execlp("wc", "wc", "-l", NULL); + fprintf(stderr, "ERROR: execlp error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + ////////// stdin --> who --> pipes[0][0] ////////// + if (dup2(pipes[0][1], 1) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + close(pipes[0][0]); + close(pipes[1][0]); + close(pipes[1][1]); + + execlp("who", "who", NULL); + fprintf(stderr, "ERROR: execlp error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + + // on atteint jamais cet endroit + return EXIT_FAILURE; +}