- [Système d'Exploitation : Cours 2 : Intro Historique](#système-dexploitation--cours-2--intro-historique)
  - [Mémoire](#mémoire)
    - [Hiérachie des mémoires](#hiérachie-des-mémoires)
  - [Système d'exploitation](#système-dexploitation)
  - [Multiprogrammation](#multiprogrammation)
    - [Notion de processus](#notion-de-processus)
    - [Notion de Thread](#notion-de-thread)
    - [Gestion de processus](#gestion-de-processus)
    - [Etats des processus](#etats-des-processus)
  - [Gestion de fichiers](#gestion-de-fichiers)
    - [Structure des répertoires](#structure-des-répertoires)
  - [Histoires des Systèmes d'Exploitation](#histoires-des-systèmes-dexploitation)
    - [Gen 1 : Tubes à vide (1945-1965)](#gen-1--tubes-à-vide-1945-1965)
    - [Gen 2 : Transistor et bandes magnétiques (1955 - 1965)](#gen-2--transistor-et-bandes-magnétiques-1955---1965)
    - [Gen 3 : Circuits intégrés (1965 - 1980)](#gen-3--circuits-intégrés-1965---1980)
    - [Gen 4 : PC (1980 - today)](#gen-4--pc-1980---today)
  - [Types d'OS](#types-dos)
- [Système d'Exploitation : Cours 3 : Processus & Threads](#système-dexploitation--cours-3--processus--threads)
  - [Processus](#processus)
  - [Multi programmation](#multi-programmation)
  - [Types de processus](#types-de-processus)
  - [Etats d'un processus](#etats-dun-processus)
    - [Principaux états](#principaux-états)
    - [Transitions d'états](#transitions-détats)
  - [Les Interruptions](#les-interruptions)
  - [Gestion de processus](#gestion-de-processus-1)
    - [PCB](#pcb)
    - [Création de processus](#création-de-processus)
    - [Dupliquer](#dupliquer)
    - [Remplacer](#remplacer)
    - [Identité](#identité)
    - [Terminer un processus](#terminer-un-processus)
    - [Attendre la fin d'un processus](#attendre-la-fin-dun-processus)
  - [Thread](#thread)
    - [Créer un thread](#créer-un-thread)
    - [Terminaison d'un thread](#terminaison-dun-thread)
    - [Attente de la terminaison d'un thread](#attente-de-la-terminaison-dun-thread)
- [Système d'Exploitation : Cours 4 : Synchronisation](#système-dexploitation--cours-4--synchronisation)
  - [Interactions entre les programmes](#interactions-entre-les-programmes)
  - [Synchronisation](#synchronisation)
  - [Communication](#communication)
  - [Section critique](#section-critique)
  - [Sériabilité et atomicité](#sériabilité-et-atomicité)
  - [Gérer les risques d'incohérence](#gérer-les-risques-dincohérence)
    - [Guérir](#guérir)
    - [Solution à l'exclusion mutuelle](#solution-à-lexclusion-mutuelle)
  - [Sémaphores](#sémaphores)
    - [Sémaphore d'exclusion mutuelle (MUTEX)](#sémaphore-dexclusion-mutuelle-mutex)
    - [Sémaphores privés](#sémaphores-privés)
    - [Interblocage](#interblocage)
    - [Ordonnancement des ressources](#ordonnancement-des-ressources)
    - [Sémaphores généraux](#sémaphores-généraux)
  - [Producteur/Consommateur](#producteurconsommateur)
  - [Les sémaphores en C](#les-sémaphores-en-c)
    - [Inclure l'entête `semaphore.h`](#inclure-lentête-semaphoreh)
    - [Déclarer un sémaphore :](#déclarer-un-sémaphore-)
    - [Initialiser un sémaphore :](#initialiser-un-sémaphore-)
    - [Opération P sur un sémaphore :](#opération-p-sur-un-sémaphore-)
- [Système d'Exploitation : Cours 5 : IPC](#système-dexploitation--cours-5--ipc)
  - [Différents types de communication](#différents-types-de-communication)
  - [Tubes](#tubes)
    - [Tubes anonymes](#tubes-anonymes)
      - [Principe & API](#principe--api)
      - [Implémentation en C](#implémentation-en-c)
    - [Les tubes nommés](#les-tubes-nommés)
      - [Pincipes](#pincipes)
      - [Implémentation en C](#implémentation-en-c-1)
- [Système d'Exploitation : Cours 6 : Mémoires partagées](#système-dexploitation--cours-6--mémoires-partagées)
  - [Les processus et la mémoire](#les-processus-et-la-mémoire)
    - [Mono Programmation](#mono-programmation)
    - [Multi Programmation](#multi-programmation-1)
      - [Partitions fixes](#partitions-fixes)
      - [Partitions variables](#partitions-variables)
        - [Comment connaitre la taille d'un processus](#comment-connaitre-la-taille-dun-processus)
        - [Comment représenter les zones libres ?](#comment-représenter-les-zones-libres-)
        - [Comment sélectionner la zone à allouer ?](#comment-sélectionner-la-zone-à-allouer-)
        - [Que faire lors de la libération d'une zone occupée ?](#que-faire-lors-de-la-libération-dune-zone-occupée-)
      - [Mémoire virtuelle](#mémoire-virtuelle)
      - [Principe de pagination](#principe-de-pagination)
      - [MMU : Memory Management Unit](#mmu--memory-management-unit)
      - [Pagination](#pagination)
      - [Segmentation](#segmentation)

# Système d'Exploitation : Cours 2 : Intro Historique

## Mémoire

Organisée en 2<sup>N</sup> mots de M bits.

* Un mot est séléctionné par son adresse
* La mémoire stocke des programmes et des données

### Hiérachie des mémoires

- CPU : 
  - Registres
  - Caches mémoire
- Ordinateur : 
  - Cache secondaire
  - RAM
  - Disque Dur

## Système d'exploitation 

Ensembles des programmes gérant les organes physiques d'un ordinateur : 

- Coordonne les différents éléments de la machine et coordonne les échanges entre eux.
- Exécute les commandes de l'utilisateur ou des applications
- Sécurise son intégrité

Couche logicielle pour utiliser de manière optimale les ressources de l'ordinateur.

- Interface simple
- Gestion et partage des ressources

Un OS peut être : 

- Multi-tâches : plusieurs programmes en parallèle.
- Multi utilisateurs

|         |Mono utilisateurs  |Multi utilisateurs  |
|---------|---------|---------|
|Mono tâche     |    MS-DOS     |         |
|Multi-taches     |     Windows 95-98    |    Windows NT, UNIX     |

## Multiprogrammation

### Notion de processus

- Unité de traitement d'un programme par l'ordinateur
  - Ensemble d'instruction
  - Espace d'adressage (ou mémoire)
- PCB (Process Control Block)
  - Structure contenant les informations nécessaires à la gestion du processus (Etat, conteur ordinal, registres ...)

### Notion de Thread

- Processus léger => un processus = plusieurs threads
  - Ensemble d'instructions propres
  - Partages de données entre les threads
- Fin d'un processus => fin de tous les threads

### Gestion de processus

- Scheduler : gestionnaire de processus
- Affecte une zone mémoire aux programmes
- Contrôle les demandes de mémoire
- Permet l'échange de données entre applications
- Ordonnancement avec quota de temps

### Etats des processus

- Création
- Runnable
- Stopped
- Sleeping
- Running
- Zombie
- Terminated

## Gestion de fichiers

Trois classes d'utilisateurs : 
- Propriétaire
- Groupe
- Autre

Trois attributs pour chaque classe  :
- Lecture : r
- Ecriture : w
- Excécution : x

### Structure des répertoires

- Unique arborescence (racine : "/")
- On peut monter une partition depuis un disque, une clé USB => création d'un nouveau répertoire dans l'arborescence.

## Histoires des Systèmes d'Exploitation

### Gen 1 : Tubes à vide (1945-1965)

- Machine énormes, peu fiables, lentes
- Pas d'OS, pas de langage de haut niveau
- Une équipé créait et utilisait la machine
- 1950 : cartes perforées

### Gen 2 : Transistor et bandes magnétiques (1955 - 1965)

- Traitement par lot
- Fortran et assembleur

### Gen 3 : Circuits intégrés (1965 - 1980)

- Moins chers
- Mémoire partitionnée
- Multi programmation
- Système d'exploitation contraignant

### Gen 4 : PC (1980 - today)

- MS DOS, Windows, Windows NT
- UNIX, Linux
- IHM Graphiques

## Types d'OS

- Mainframe : gros système d'entreprise
- Serveur : assure des services à des utilisateurs via le réseau
- Système Multi processeur : station à plusieurs processeurs
- Système personnel : Windows, Mac, Linux, adapté au besoin des utilisateurs.
- Système temps réel : Pilotages de machines industrielles et de robots.
- Système embarqué : IoT

# Système d'Exploitation : Cours 3 : Processus & Threads


## Processus

- Concept central pour tout OS. C'est une séquence d'actions produite par l'exécution d'une suite d'instructions.
- Un processus est une instance d'un programme en cours d'exécution.
  - Tâches en cours
  - Environnement propre, son contexte d'exécution.
  - Espace mémoire propre, son espace d'adressage, contient code et données du programme.

**Programme :** concept statique ; code et données, pas d'actions.

**Processus :** concept dynamique, exécution du programme (instance, plusieurs processus d'un même programme possibles) avec un état courant.

## Multi programmation

- Système temps partagé : l'UC passe d'un processus à l'autre rapidement.
  - Plusieurs fils d'exécution séquentiels
- Virtualisation d'une UC
  - N UC virtuelles mais une UC physique
  - N compteurs ordinaux logiques mais un compteur physique
  - Différent d'un vrai parallélisme matériel (multi processeur)

## Types de processus

- Processus utilisateur
  - Exécution des applications
  - Utilisateur particulier : root
  - Certaines instructions interdites ou limitées
- Processus système : exécution en mode kernel.

> Mode noyau != mode super user

## Etats d'un processus

- Contexte ou vecteur d'état
  - Information de l'exécution du processus
  - Point interruptible : instant pendant lequel le contexte contient des informations stables.

### Principaux états

- Bloqué
  - Attente de ressources nécessaires
- Activable
  - Ressources disponibles
  - En attente de l'UC
- Actif
  - Ressources disponibles
  - S'exécute sur l'UC

### Transitions d'états

- Activable &rarr; Actif
  - Modification du vecteur d'état par le scheduler
  - Commutation de contexte
- Active &rarr; Activable
  - Interruption prioritaire (ex : fin quantum de temps)
  - Communcation de contexte
- Actif &rarr; Bloqué
  - Processus lui même
  - Blocage matériel : demande de ressource non dispo
  - Blocage logiciel : prévu par le programmeur
  - Commutation de contexte
- Bloqué &rarr; Activable
  - Sur l'arrivée d'un evénement
  - Signalé par une interruption
  - Commutation de contexte pas automatique

## Les Interruptions

- Arrivée d'un évènement &rarr; arrivée d'une interruption
- Prise en compte de l'évèneent &rarr; traitement de l'interruption
- Rôle très important : unique moyen pour le SE de prendre la main sur le CPU.

## Gestion de processus

### PCB

- Ensemble de PCB (Process Control Block)
  - Structure de donnée propre au SE
  - Info accessible uniquement par le noyau (appel système)
  - Contient : 
    - Identité : PID, PPID, droits
    - Exécution : Etat, contexte, priorité
    - Ressources : mémoire, temps, fichiers
  
### Création de processus

- Un processus peut en créer un autre
- Windows : pas de hiérarchie 
- UNIX : Parents, enfants, groupe, identifié par une numéro (PID,PPID)
- Arbre de processus 

### Dupliquer

```c
int pid = fork();
```

Duplication du processus appelé.
Renvoie `0` si c'est le fils, renvoie le PID du fils si c'est le père.

### Remplacer

Les appels système de la famille `exec` permettent de remplacer entièrement le processus courant par celui d'une autre application.

L'appel système de base est `execve()`.
Des variantes sont implémentée : 
- `execl()` : l &rarr; Liste d'arguments
- `exelv()` : v &rarr; tableau à la manière de `argv`. 
- Termine par e &rarr; transmet l'environnement (`tab envp[]`)
- Termine par p &rarr; recherche l'application à lancer à partir du PATH, pour les autres, il faut le chemin d'accès.

### Identité

Dans un terimnal : 

```
echo $$
```

ou 

```
ps
```

En C : 
```c
pid_t getpid()
```

### Terminer un processus

```c
void exit(int status)
```

Le status est une variable entière qui donne des information sur le succès ou l'échec de l'exécution du processus : `0` normal, sinon anormal.
Macros : `EXIT_SUCCESS` et `EXIT_FAILURE`
Cette valeur doit être récupérée par le parent. Pas de libération de ressource tant que ce n'est pas fait : état zombie.

### Attendre la fin d'un processus

```c
pid_t wait(int* status)
```
Attends la fin d'un processus fils. Si pas de fils, retourne -1.
Si plusieurs fils : impossible d'en séléctionner un en particulier.
`status` permet de récupérer la valeur retournée par le fils.

```c
pid_t waitpid(pid_t pid, int* stat_infos, int options)
```
Attendre la fin d'un processus particulier.

## Thread

- Processus &rarr; couteux en temps
- Contexte lourd
- Un thread est un processus léger
- Espace mémoire partagé
  - Partage des données facile
  - Attention à la synchronisation

### Créer un thread

```c
int pthread_create(pthread_t* idptr, pthread_attr_t attr, void*(*fonc)(void*), void* arg)
```
- `idptr` &rarr; pointeur pour récupérer l'identité du thread
- `attr` &rarr; attribut du thread : `pthread_attr_default` ou `0`
- `fonc` &rarr; pointeur sur la fonction exécutée par le thread
- `arg` &rarr; pointeur sur les arguments passés au thread

Contrairement au processus, le code n'est pas dupliqué

### Terminaison d'un thread

 ```c
 int pthread_exit(void* status)
 ```

 stauts &rarr; pointeur sur le résultat retourné par le thread

 ### Attente de la terminaison d'un thread

  ```c
 int pthread_join(pthread_t id, void* status)
 ```

- `id` &rarr; identité du thread attendu
- `status` &rarr; pointeur sur le résultat retourné par le thread attendu

# Système d'Exploitation : Cours 4 : Synchronisation


## Interactions entre les programmes 

- Les problèmes dans les systèmes multi tâches sont dus aux interactions entre les tâches parallèles
- Partage de ressource &rarr; même résulat que si on est en séquentiel (pas d'incohérence due à la parallélisation)
- Communiquer, coopérer &rarr; définir un protocole pour communiquer entre programmes

## Synchronisation

- Résoudre les problèmes de cohérence sur la mémoire partagée
- Spécifier les dépendances entres les étapes de traitements (si une action doit être effectuée avant une autre)
- Régler les problèmes de concurrence sur l'accès à une ressource partagée (logicielle ou matérielle)

## Communication

- Mémoire partagée
- Tubes FIFO
- Boites au lettres asynchrones
- Buffers circulaires

> Une instruction C peut être assemblée en plusieurs instruction au niveau du code assembleur ! &rarr; Une instruction C n'est pas forcément atomique

## Section critique

Portion de code dans lequel une tâche utilise des ressources partagée mais qui ne pas être utilisées par celles-ci durant l'exécution de cette portion de code.

> Les sections critiques diminuent le taux de parallélisme, il faut les réduire au maximum afin de garantir la cohérence des données sans dégrader les performances gagnées grâce à la parallélisation.

## Sériabilité et atomicité

**Seriabilité :** exécution de deux taches peut se faire dans n'importe quel ordre sans incidence. Leur parallélisation est indépendante de l'ordonnancement.

**Atomicité :** deux tâches ne peuvent être mises en parallèle. On ne peut pas mettre en pause l'une pour démarrer l'autre. Chacune dur un temps nul pour l'autre. L'atomicité évite les interactions entre les tâches mais ne résout pas le problème d'interaction entre elles. 

> Les périodes d'atomicité diminuent le taux de parallélisme, il faut les réduire au maximum afin de garantir la cohérence des données sans dégrader les performances gagnées grâce à la parallélisation.

## Gérer les risques d'incohérence

Les tâches qui entrent en conflit sur des données (lecture / écriture concurrente) doivent être atomiques.
- Synchronisation pessimiste : prévention (section critique) &rarr; empêcher un soucis de survenir
- Synchronisation optimiste : guérison (estampilles) &rarr; détecter le problèmes et corriger les données pour garantir leur cohérence.

&rarr; Dépend de la possibilité d'avoir les tâches actives ensemble.

### Guérir

- Copier la date (l'estampille)
- Copier les données
- Calculer les nouvelles valeurs
  *Début de l'atomicité*
- Copier la date actuelle (est ce que quelqu'un a changé l'estampille)
- Si elle est inchangée, modifier les donnée et augmenter la date
  *Fin de l'atomicité*
Sinon recommencer

### Solution à l'exclusion mutuelle

- Indépendant de la vitesse d'exécution des tâches
- Pas plus de deux processus *en même temps* dans une section critique
- Un tâches hors de sa section critique qui ne cherche pas à y rentrer ne doit pas empêchant une autre d'entrer en section critique
- Deux tâches ne doivent pas s'empêcher mutuellement et indéfiniment d'entrer en section critique &rarr; problème d'interblocage (deadlock)
- Un processus doit toujours entrer en section critique au bout d'un temps fini &rarr; problème de famine (livelock)

## Sémaphores

Un sémaphore est un objet sur lequel seulement deux opérations atomique sont possibles.

- P(sem) : décrémentation de la valeur du sémaphore. Appel bloquant si la valeur est inférieure à 0 (barrière)
- V(sem) : incrémentation de la valeur du sémaphore. Permet de débloquer une tâche bloquée par un appel à P

> Vient du hollandais Passeren (prendre), Vrygeven (libérer)

### Sémaphore d'exclusion mutuelle (MUTEX)

Sémaphore binaire initialisé à 1 qui sert à protéger une section critique. Cela permet d'assurer l'accès cohérent à un ensemble de variable auquel on fait correspondre une MUTEX.

### Sémaphores privés

A utiliser quand une tâche ne peut utiliser qu'une seule des primitives P ou V.
Le processus qui fait P attend un signal des tâches qui font V.
Si le processus est en avance il est bloqué, si le signal est émis en avance il est mémorisé.

### Interblocage

Il faut faire attention à l'interblocage de tâches.
Exemple avec deux tâches et deux sémaphores :
- A : P(S1)
- B : P(S2)
- A : P(S2) &rarr; appel à P bloquant
- B : P(S2) &rarr; appel à P bloquant

La situation est bloquée.

> On peut s'inter bloquer même avec un seul sémaphore

Remèdes : 
- Annuler un appel à P
- Remonter la tâches dans le code
- Pouvoir restaurer les données de la tâches
- Annuler toutes les opérations qu'elle a faite
- En pratique : détecter et détruire les tâches concernées...
- Même soucis qu'avec les estampilles...

Prévention :
- Problèmes compliqué mais dans des cas particuliers il y a des solutions simples
- Annonce des besoin : une tache demande une seule fois toutes ses ressources

### Ordonnancement des ressources

La tâche peut faire des demandes successives pourvu qu'elle porte sur des ressources comparables et qu'elles soient faites en suivant une *relation d'ordre*.

### Sémaphores généraux

- Utilisés comme compteur de ressources : pas limité à 0 ou 1 contrairement aux MUTEX
- Valeurs du sémaphore : valeure initiale correspond au nombre de ressource maximum, la valeur courante, le nombre de ressources disponibles.
- L'opération P permet d'acquérir une ressource, appel bloquant si aucune ressource n'est disponible
- L'opération V permet de libérer une ressource

## Producteur/Consommateur

Un système possède N emplacement pour stocker de l'info :
- Les tâches *productrices* produisent de l'information vers ces emplacements
- Les tâches *consommatrices* utilisent l'information et libèrent l'emplacement correspondant.

Un sémaphore est nécessaire pour synchroniser les deux types de processus : 
- Bloquer les producteurs s'il n'y a plus de places
- Bloquer un consommateur s'il n'y a plus d'information disponible.

## Les sémaphores en C

### Inclure l'entête `semaphore.h`

```c
#include <semaphore.h> 
```

### Déclarer un sémaphore :

```c
sem_t semaphore;
```

### Initialiser un sémaphore : 
```c
int sem_init(sem_t *semaphore, int pshared, unsigned int value)
```

- `semaphore` &rarr; adresse sur sémaphore à initialiser
- `pshared` &rarr; indique si le sémaphore est partagé entre des threads, si il est égale à 0 le sémaphore sera partagé et doit avoir une adresse visible de tous ces threads (globale ou varibale allouée dynamiquement)
- `value` &rarr; value à initialiser

### Opération P sur un sémaphore : 

```c
int sem_wait(sem_t * semaphore)
```


<br><br>
Opération V sur un sémaphore

```c
int sem_post(sem_t * semaphore);
```

# Système d'Exploitation : Cours 5 : IPC


## Différents types de communication

- Machines distantes reliées par un réseau
  -  Socket
- Sur la même machine : 
  - Tubes et tubes nommés
  - Files de messages
  - Sémaphores
  - Mémoires partagée

## Tubes

### Tubes anonymes

#### Principe & API

Communication unidirectionnelle entre processus.
Appel système : 
```c
int pipe(int *fileDesc);
```
- `fileDesc` &rarr; descripteur de fichier
- `fileDesc[0]` &rarr; descripteur de lecture
- `fileDesc[1]` &rarr; descripteur d'écriture

Caractéristiques : 
- Capacité limitée
- Fichier : possède un numéro d'inode mais pas de nom dans le système
- Disparait avec le processus
- Les processus qui utilisent un tube doivent avoir un lien de parenté

Concept : 

Processus père (writes fd) &rarr; Kernel (Pipe) &rarr; Processus fils (read fd)

Il est possible de mettre à la chaine entre plein de processus.
Pour une communication bidirectionnelle, il faut un tube supplémentaire.

#### Implémentation en C

```c
// Déclaration
int tube1[2] = {-1,-1};
int tube2[2] = {-1,-1};
// Ouverture
pipe(tube1);
pipe(tube2);
...
// Chaque processus ferme les descripteurs inutilisés
close(tube1[0]);
close(tube2[1]);

// Ecrire dans le tube
write(tueb1[1], &outboundMessage, sizeof(char));

// Lire dans le tube
read(tube[2], &inboundMessage, sizeof(char));

// Fermer les descripteurs à la fin du processus
close(tube1[1]);
close(tube2[0]);

```

### Les tubes nommés

#### Pincipes

Différence avec les tubes anonymes :
- Possède un nom dans le système de fichiers
- Pas de lien de parenté obligatoire entre les différents processus
- Persistant tant qu'il n'est pas détruit (même après disparition du processus qui l'a créé)
- Donnée en FIFO (taille limitée + on se déplace pas à l'intérieur)

<br>
<br>
<br>
<br>
<br>

<br>
<br>
<br>
<br>
<br>

#### Implémentation en C

```c
int tube;
mode_t droits_tubes = S_IRWXU | S_IRWXG; // Droits en lecture, écriture et exécution pour User et Group

// Création du tube
mkfifo("TUBE", droits_tube);
...

/* Ouverture du tube (fichier) en écriture seule
* Appel bloquant jusqu'à ouverture du tube par le lecteur
*/
tube = open("TUBE", O_WRONLY);

// Lecture dans le tube
read(tube, &lettre, sizeof(unsigned char));

// Ecriture dans le tube
write(tube, &lettre, sizeof(unsigned char));
```

On voit bien la création d'un fichier dans le repertoir courant de l'exécutable qui porte le nom du tube.
Il faut gérer la suppression du tube sinon il reste dans le système de fichier.

# Système d'Exploitation : Cours 6 : Mémoires partagées 


## Les processus et la mémoire

- Sur un PC, plusieurs processus s'exécutent à un instant T, avec chacun un espace mémoire (espace d'adressage) qui lui est propre.
- Un processus ne peut pas modifier la mémoire d'un autre (protection mémoire)
- Certaines instructions (branchements) nécessitent de connaître les adresses à la compilation
- Un processus doit pouvoir être exécuté sur plusieurs ordinateurs ayant des capacités mémoire différente &rarr; il faut une abstraction de la mémoire matérielle.
  
&rarr; Solution : mécanisme de mémoire virtuelle

### Mono Programmation

En mono programmation (un seul processus à la fois sur le CPU), la mémoire est découpée en 2 parties (partitions) : 
- Une partie réservée au SE (de taille fixe)
- Une partie réservée au programme

&rarr; Les adresses mémoires sont des adresses physiques
&rarr; Chaque case mémoire est affectée à une adresse
&rarr; L'adresse est obtenue depuis l'instruction processus en binaire, elle est contenue sur *n* bits (&rarr; processus *n* bits) et permet d'adresser *2<sup>n</sup>*

Donc en mono programmation, pas de problème de relocation de la mémoire (l'adresse de début du programme est toujours la même). Le problème de la mémoire est donc simplifié. Un *"Registre limite"* est implémenté pour connaître l'adresse du début du programme en mémoire.
&rarr; L'accès est interdit si cette adresse est inférieure au registre limite.

### Multi Programmation

#### Partitions fixes

Les premiers systèmes d'exploitation étaient à **partitions fixes** :
- La mémoire est divisée en partitions de taille fixe lors de la génération du système.
- Un programme obtient une partition entière à lui tout seul.
- On pouvait avoir autant de programme en simultané que de partitions sur le système
Implémentation : un registre de base et un registre de limite &rarr; vérification des accès mémoire dans un intervalle. Une clé de protection est attributée à chaque processus qui correspond à la partition qui lui est attribué. 

Gestion de la relocation avec une adresse de base ; le système d'exploitation corrige les adresses du programme en fonction de l'adresse de base.
Deux méthodes : 
- Correction au lancement du programme par le système d'exploitation ou automatiquement par le processus grâce au registre de base
- Position indépendant du code, effectuée par les compilateurs et les linkers

Cette méthode pose un problème de fragmentation de la mémoire :
- Fragmentation interne : la taille réelle du programme est inférieure à la taille de la partition ; la mémoire restante sur la partition est gachée le temps de l'exécution du programme.
- Fragmentation externe : Une partition libre entre deux partitions occupées

Il faut donc que le processus puisse : 
- Demander une partition d'une taille précise qui lui est adapté
- Allouer dynamiquement plus de mémoire au cours de son exécution.

#### Partitions variables

On fait une partition d'une certaine taille demandée par le programme. Cela résout le problème de la fragmentation interne mais pas celui de la fragmentation externe. Il y a toujours des trous entre les partitions, et donc faire de la relocation.

Les problématiques sont les suivantes : 
- Comment connaître la taille d'un processus ?
- Comment représenter la zone libre ?
- Comment séléctionner la zone à allouer ?
- Que faire lors de la libération d'une zone occupée ?

##### Comment connaitre la taille d'un processus

Le volume d'espace mémoire varie d'un processus à l'autre mais aussi durant l'exécution du processus (au fur et à mesure qu'il alloue dynamiquement des variables).

Les zones principales sont : 
- Text : code exécutable &rarr; taille fixe
- Data : variables statiques et globales initialisées &rarr; taille fixe
- Heap : tas, variables dynamiques &rarr; taille variable
- Stack : pile variables automatiques &rarr; taille variable

On fixe donc arbitrairement la taille pour la pile et le tas.
Si plus assez de ressource, deux possibilité : 
- Plus de mémoire : terminaison du processus
- Relocation dans une nouvelle zone plus grande

Problème lié à la relocation : les données stockées dans le tas sont référencées par leur adresse mémoire &rarr; pb de translation d'adresse. La relocation ne doit pas modifier leur emplacement.
Moins de soucis pour la pile, on y accède par le pointeur de pile (stack pointer).

Solution : la pile croit vers le haut et le tas croit vers le bas de l'espace mémoire. On fait une relocation quand les deux se rencontrent.

##### Comment représenter les zones libres ?

Le système d'exploitation maintient une table des partitions pour savoir les quelles son utilisées ou non. La gestion des blocs libres est plus ou moins complexe (table de bits ou liste chainée).

##### Comment sélectionner la zone à allouer ?

Différents algorithmes plus ou moins performants : 
- First-fit : première zone libre
- Best-fit : plus petite zone libre
- Worst-fit : plus grande zone libre

##### Que faire lors de la libération d'une zone occupée ?

Dépend de l'algorithme de gestion : par exemple fusionner des zones adjacentes. Cela dépend des performances.

#### Mémoire virtuelle

But principal : exécuter les processus sans qu'ils soient logés en RAM dans la totalité.

- Le processus possède toute la mémoire virtuelle (elle peut être supérieure à la taille de la RAM)
- Disponibilité d'une zone de va et vient (swap) sur le disque dur en remplacement de la mémoire physique manquante.

#### Principe de pagination

Découper la mémoire en blocs de taille constante (cadres de pages) et de découper ces blocs en paquets de taille constante (pages). Les pages sont affectées dans les cadres de page.

La mémoire doit être de taille *2<sup>m+n</sup>* sinon certaines zones sont non adressables (donc non utilisables) : 
- Nombre de cadres : *2<sup>n</sup>*
- Taille des cadres (en pages) : *2<sup>m</sup>*

> Par exemple sur un architecture 32bits on a une page de 4Kio &rarr; *2<sup>20</sup>* pages de *2<sup>12</sup>* (4Kio)

#### MMU : Memory Management Unit

La conversion mémoire physique (utilisé par la machine) / mémoire virtuelle (vues par les processus et allouées par le système) est assurée par un composant matériel basé sur le mécanisme de protection mémoire du processeur Intel 386/386.
La mémoire est protégé, c'est-à-dire que l'espace mémoire d'un processus n'est jamais écrasé par un autre. Cela permet d'avoir un système d'exploitation stable.
Si un programme essaye de sortir de son espace mémoire, la MMU détecte l'erreur et stop le programme. (Erreur de violation de segment : SIGSEGV).
La majorité des processeurs possèdent une MMU, mais elle rend ce dernier, plus cher, plus gourmand et complexe.

#### Pagination

Le système d'exploitation charge la table de pages du processus dans la MMU et n'a pas de calculs à faire pour lui-même.
La hiérarchisation des pages à 2 ou 3 niveaux permet de : 
- Charger uniquement les tables utiles
- Réduire la fragmentation due au pages
- Réduire l'espace mémoire utilisé par le système d'adressage
Mais pose des problèmes de sélections et de défauts de pages.

Limite des pages :
- Découpage des processus &rarr; fragmentation interne
- Chargement d'une page &rarr; données pas forcément utiles chargées
- Découper en prenant en compte la structure du processus &rarr; mémoire segmentée

#### Segmentation

Découpage du code exécutable en blocs de code / données indépendantes : programme principal, fonction, bibliothèque, pile, tas. 
Ce découpage est dépendant du langage, on a donc une table des segments ou table des descripteurs où chaque segment est référencé par un numéro.
Les segments sont gérés par la MMU.
Calculs d'adresse : 
- Numéro de segment (sélécteur) &rarr; adresse de base
- Base + décalage &rarr; adresse physique

Erreur de segmentation si inférieur à la limite : 
- Base &rarr; adresse physique de départ
- Limite &rarr; taille du segment 
