Ressources

Description officielle

Maîtriser et appliquer les concepts fondamentaux des systèmes d’exploitation. Comprendre les mécanismes et les politiques mises-en-oeuvre par les systèmes d’exploitations. Maîtriser la programmation système UNIX/Linux en C.

Rôles, types et structure générale des systèmes d’exploitation. Mécanismes noyaux : appels systèmes, interruptions, modes d’exécution processeur. Gestion des processus : états des processus, création et terminaison (fork et exec). Multitâche : changement de contexte, fils (threads), ordonnancement des tâches. Gestion des fichiers : systèmes de fichiers, inodes, descripteurs de fichiers, fichiers spéciaux. Communication inter-processus : échanges de messages, signaux, tubes, mémoire partagée. Concurrence : synchronisation, sections critiques, interblocages. Gestion de la mémoire : adressage, allocation, protection, pagination, mémoire virtuelle. Entrées-sorties : pilotes, pseudo-périphériques. Les considérations de sécurité seront intégrées au développement de la matière.

Évaluations et échéancier des rendus

Les dates de remise sont des dates “au plus tard”, et s’entendent sur le fuseau horaire de Montréal, à 23:55 le jour de la date de remise. Tout rendu hors délai recevra la note de zéro (0), mais rien ne vous empêche de livrer avant l’échéance. Les règles concernant le plagiat seront appliquées sans aucune tolérance.

Desc % Présentation Du À
💾 TP0 wall-e 10% Enregistrement 🎥 Dimanche 15 mai Lundi 30 mai à 23h55
💾 TP1 echelon 10% Enregistrement 🎥 Lundi 30 mai Dimanche 19 juin à 23h55
💾 TP2 tubeo 20% Enregistrement 🎥 Lundi 11 juillet Dimanche 7 août à 23h55

La note finale (en lettre, A+, A, etc.) pour le trimestre sera attribuée en fonction de l’atteinte des objectifs spécifiques à travers les évaluations. La distribution des résultats dans le groupe pourrait aussi être utilisée. Aucune autre opportunité (travail supplémentaire, etc.) d’augmenter le nombre de points ne sera accordée.

Semainier des séances

Les diapositives téléchargeables (pdf) datent de la sessions d’été 2021 mais le contenu est à jour et sera utilisé tel quel pour la session d’automne 2021.

# Semaine Diapositives Laboratoires
1 2 au 6 mai 100 Introduction - pdf 🖼
110 Définition et rôles - pdf 🖼
Enregistrement 🎥
120 Appels système - pdf 🖼 - progs 💾
130 Mécanismes matériels - pdf 🖼 - progs 💾
Enregistrement 🎥
Pas de laboratoire
2 9 au 13 mai 200 Processus - pdf 🖼
210 Threads - pdf 🖼
220 Mémoire des processus - pdf 🖼 - progs 💾
Enregistrement 🎥
230 Vie et état - pdf 🖼
Lab1 ⌨️
Solutions du lab1
3 16 au 20 mai 240 Création et terminaison - pdf 🖼 - progs 💾
241 fork et création de processus - pdf 🖼 - progs 💾
Enregistrement 🎥
242 exec et recouvrement de processus - pdf 🖼 - progs 💾
243 exit et terminaison de processus - pdf 🖼 - progs 💾
Enregistrement 🎥 (Deuxième partie du cours seulement)
Lab2 ⌨️
Solutions du lab2
4 23 au 27 mai 250 Ordonnancement des processus - pdf 🖼 - progs 💾
Enregistrement 🎥
Lab3 ⌨️
Solutions du lab3
5 30 mai au 3 juin 300 Système de gestion de fichiers - pdf 🖼
310 Manipulation de fichiers - pdf 🖼
Quiz 1
Lab4 ⌨️
Solutions du lab4
6 6 au 10 juin 320 Droits et utilisateurs - pdf 🖼
330 Répertoires - pdf 🖼 - progs 💾
Enregistrement 🎥
Lab5 ⌨️
Solutions du lab5
7 13 au 17 juin 340 Traitement des fichiers ouverts - pdf 🖼 - progs 💾
350 Implémentation des systèmes de fichiers - pdf 🖼
Enregistrement 🎥
Correction intra 🎥
Lab6 ⌨️
Solutions du lab6
8 🌼 20 au 24 juin Examen intra
À la place du cours - Mardi 21 juin 2022
Lab7 ⌨️
Solutions du lab7
9 27 juin au 1 juillet 400 Communication interprocessus - pdf 🖼
410 Signaux - pdf 🖼 - progs 💾
420 Tubes - pdf 🖼 - progs 💾
Enregistrement 🎥
Lab9 ⌨️
Solutions du lab9
10 4 au 8 juillet 430 Sockets - pdf 🖼 - progs 💾
500 Synchronisation - pdf 🖼 - progs 💾
Enregistrement 🎥
Jeudi 7 juillet: date limite d'abandon sans mention d'échec.
Lab10 ⌨️
Solutions du lab10
11 11 au 15 juillet 510 Section critique - pdf 🖼 - progs 💾
520 Outils de synchronisation - pdf 🖼 - progs 💾
530 Interblocage - pdf 🖼 - progs 💾
Enregistrement 🎥
Lab11 ⌨️
Solutions du lab11
12 18 au 22 juillet 600 Gestion de la mémoire - pdf 🖼 - progs 💾
610 Pagination - pdf 🖼
620 Mémoire virtuelle - pdf 🖼
Enregistrement 🎥
Quiz 2
Lab12 ⌨️
Solutions du lab12
13 25 au 29 juillet 621 Mémoire virtuelle avancée - pdf 🖼
622 mmap et cie. - pdf 🖼 - progs 💾
623 Consommation mémoire - pdf 🖼 - progs 💾
630 Allocation - pdf 🖼
Lab13 ⌨️
Solutions du lab13
14 1 au 5 août Rattrapage première semaine Lab14 ⌨️
15 ☀ 8 au 12 août Examen final
À la place du cours - Mardi 9 août 2022
Pas de laboratoire

Anciens examens

Liens

  • The Linux Kernel documentation. Documentation officielle du noyau Linux
  • LWN. Site d’information spécialisé sur le noyau linux et son ecosystème (Linux Weekly News)
  • POSIX.1-2017. Norme POSIX (Open Group et IEEE).
  • The Unix Tree. Code source original de nombreuses versions historiques de Unix.

Médiagraphie

Les ressources suivantes sont recommandées.

  • SILBERSCHATZ, A., GAVIN, P.B., GAGNE, G. – Operating Systems Concepts, 10TH EDITION, WILEY, 2018.
  • TANENBAUM, Andrew S. – Modern Operating Systems – PRENTICE HALL, 4RD ED., 2014.
  • TANENBAUM, Andrew S. – Système d’exploitation – PERSON EDUCATION, 3RD ED. (en français)

Des ressources complémentaires sont disponibles

  • NUTT, G. – Operating system concepts – ADDISON WESLEY.
  • STALLING, W. – Operating systems Internals and Design Principles – PRENTICE HALL.
  • BIC, L.F. et SHAW, A.C. – Operating systems principles – PRENTICE HALL.
  • KERNIGHAN, B.W., RITCHIE, D.M. – The C programming language – PRENTICE HALL.
  • BLAESS, C. – Développement système sous Linux – EYROLLES
  • RIFFLET, J.M. – La programmation sous Unix – SCIENCE INTERNATIONAL, PARIS.
  • KERRISK M. – The Linux Programming Interface – NO STARCH PRESS.
  • GRAY, J.S. – Inteprocess communications in Linux – THE NOOKS AND GRANMIS.
  • ROBBINGS, K.A. et ROBBINGS, S. – Unix Systems Programming – PRENTICE HALL.

Bibliothèques C Le programme “./prime” #include <stdlib.h> #include <stdio.h> #include <math.h> #include <stdbool.h> #include <errno.h> #include <string.h> int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "Vous devez fournir la borne supérieure\n"); return -1; } char* endptr; long int argument = strtol(argv[1], &endptr, 0); //strtol pour convertir de String vers Integer if (*argv[1] == '\0' || *endptr != '\0' || argument <= 0) { fprintf(stderr, "La borne fournie doit être un entier supérieur à 0\n"); return -1; } long int racine_i, j, i ; size_t cap = 8; long int* primes = malloc(cap * sizeof(long int)); // Tableau de nombres premiers trouvés (à allouer dans le tas et réallouer) if (primes == NULL) { perror("Allocation"); return 1; } size_t nb = 0 , k; bool prime ; for (i=2; i<=argument; i++) { prime = true ; racine_i = (long int)sqrt((double)i) ; for (k=0; k<nb; k++) { j = primes[k] ; if ( j > racine_i ) { break ; // on trouvera plus de diviseur, inutile de continuer de chercher } if (i%j == 0) { prime = false ; // c'est divisible, donc pas premier break ; } } if (prime) { // on enregistre et on passe au nombre suivant primes[nb] = i ; nb++ ; if(nb > cap){ cap *= 2; primes = realloc( primes, sizeof(long int) * cap); if(primes == NULL){ fprintf(stderr, "La valeur de errno: %d\nInterprétation: %s",errno, strerror(errno)) ; return 1; } } } } printf("Nombre de nombres premiers trouvés : %ld\n", nb) ; free(primes); //Affichage des nombres premiers trouvés /*printf("Affichage des nombres premiers trouvés : \n") ; for(int long h = 0 ; h!

Tailles des binaires Code source des programmes de test Programme p0.c int main(int argv, char *argc[]){ return 42; } Programme p1.c #include <stdlib.h> #include <stdio.h> #include <unistd.h> int main(int argv, char *argc[]){ return 42; } Programme p2.c char tableau[8000]; int main(int argv, char *argc[]){ return 42; } Programme p3.c char tableau[8000]="hello"; int main(int argv, char *argc[]){ return 42; } Comparaison entre les différents programmes Entre p0 et p1 : La taille du fichier p0 est égale à la taille du fichier p1 car lorsqu’on inclue des “Headers”, ceux-ci ne contiennent que des éléments tels que des prototypes de fonctions, des définitions de structures, … .

Mise en bouche #include<stdlib.h> #include<stdio.h> #include<unistd.h> int main(){ pid_t pid_fils; printf("Mon PID est <%d>\n", getpid()); pid_fils = fork(); if(pid_fils > 0){ printf("Je suis le père et mon PID est <%d>\n", getpid()); } else if(pid_fils == 0){ printf("Je suis le fils et mon PID est <%d>\n", getpid()); } else{ perror("Echec du fork"); } } Multiple fils Programme p1.c #include<stdlib.h> #include<stdio.h> #include<unistd.h> #include<sys/types.h> int main() { pid_t pfils; for(int i=0 ; i!= 10 ; i++ ){ pfils = fork(); if (pfils == -1) { perror("Echec du fork"); } else if(pfils == 0) { printf("Je suis le numéro %d, mon PID est %d et mon père est %d !

Ordonnancement Afin de donner une valeur de gentillesse au programme prime_th on utilise la commande suivante nice -n 10 prime_th 10000000 10 &, n’hésitez pas à donner au programme des valeurs grandes pour vous laisser le temps de voir votre processus avec ps -l Pour lancer les 3 commandes en même temps avec l’affichage du temps d’exécution(réel, mode utilisateur, mode noyau), ainsi que le nombre d’interuption volontaire et involontaire, on utilisera la commande suivante: /usr/bin/time --format 'n19: %e %U %S %w %c' nice -n 19 .

Bonjour le monde

Cimetière d'exercices de laboratoires

Chronomètre Développer un programme chrono qui permet d’obtenir le temps réel d’exécution d’une commande passé en argument (similaire à time). Pour ce faire, utiliser la fonction gettimeofday. Reprendre le programme chrono, et rajouter les informations sur le temps passé en mode utilisateur et noyau de la commande passé en argument. Pour ce faire, utiliser la commande wait3. Note: Pour vérifier les temps d’exécution obtenue à l’aide de votre programme, vour pouvez utiliser la commande time chrono [la commande à exécuter].

Laboratoire 1

L’objectif de ce laboratoire est de vous rafraichir (ou de vous mettre à niveau) par rapport aux prérequis du cours INF1070 et INF3135. Avoir son Linux Plusieurs solutions sont possibles : Avoir une distribution native. Pour assister aux séances zoom, vous pouvez alors utiliser leur client web ou leur client Linux natif. Avoir une machine virtuelle (par exemple virtualbox). Utiliser le serveur java de labunix via SSH. Unix et ligne de commande Calculer le nombre de fichiers texte existants dans le répertoire courant, et mettre le résultat dans un fichier « f1 » Aide: man ls, man wc, man bash Afficher la cinquième ligne du fichier « /etc/hosts » Aide: man head, man tail Créer un lien symbolique vers /bin/sh qui s’appelle toto dans le répertoire courant Aide: man ln Quelles sont les permissions qui seront données avec la commande : chmod 777 chmod 640 chmod 005 Listez tous les fichiers et répertoires du répertoire /etc qui commencent par la lettre « c ».

Laboratoire 10 - Signaux et tubes

Remarque: n’oubliez pas, lors de l’utilisation d’appels système, de traiter les cas d’erreur. Modification du gestionnaire d’un signal On veut gérer le signal d’interruption de processus (signal SIGINT). Attention, il faut que l’arrêt du processus reste possible, par un autre moyen. Pour ce faire, créez un programme p0 permettant d’essayer les diverses possibilités de gestion d’un signal et constatez qu’il est possible de: gérer directement le signal, en affichant le texte Réception du signal SIGINT dans le gestionnaire montrant que le signal a bien été capturé et que l’on maîtrise la situation, ignorer l’occurrence du signal, traiter une fois le signal, puis de revenir au traitement du signal par défaut par défaut, traiter deux fois le signal, puis de revenir au traitement du signal par défaut par défaut.

Laboratoire 10 - Signaux et tubes

Remarque: n’oubliez pas, lors de l’utilisation d’appels systèmes, de traiter les cas d’erreur. Modification du gestionnaire d’un signal On veut gérer le signal d’interruption de processus (signal SIGINT) de plusieurs facons: Gestion directe du signal avec un affichage: #include<stdlib.h> #include<stdio.h> #include<unistd.h> #include<signal.h> void gere(int sig) { printf("Réception du signal SIGINT\n"); exit(1); } int main(void) { struct sigaction action; sigemptyset(&action.sa_mask); action.sa_flags = 0; action.sa_handler = gere; sigaction(SIGINT, &action, NULL); pause(); return 0 ; } En ignorant l’occurence du signal: #include<signal.