Skip to content
Snippets Groups Projects
Commit 4cf076a7 authored by Guillaume Chanel's avatar Guillaume Chanel
Browse files

Add Florent's content without reformating

parent 640682a0
No related branches found
No related tags found
No related merge requests found
Showing
with 1862 additions and 0 deletions
---
author: Florent Gluck - Florent.Gluck@hesge.ch
title: Systèmes de fichiers - Introduction
date: \vspace{.5cm} \footnotesize \today
institute: \vspace{0.5cm} \tiny \textsuperscript{*}Remerciements à Mickaël Hoerdt
pandoc-latex-fontsize:
- classes: [tiny]
size: tiny
- classes: [verysmall]
size: scriptsize
- classes: [small]
size: footnotesize
- classes: [huge, important]
size: huge
---
[//]: # ----------------------------------------------------------------
## Historique
\small
:::::: {.columns}
::: {.column width="55%"}
- Les systèmes de fichiers ont été conçu pour accéder, avec une interface simple, à des périphériques de stockage de masse (persistents)
- Premiers périphériques de stockage de masse étaient basé sur des disques magnétiques appelés *Hard Disk Drive*
- La plus petite unité de lecture/écriture adressable est le secteur
- Adressable par le triplet CHS :\
{ Cylinder, Head, Sector }
:::
::: {.column width="45%"}
![](images/hdd.png){ width=70% }
\tiny
a. Plateaux
a. Bras mobile
a. Têtes de lecture/écriture reliées par le bras mobile
a. Cylindre = coupe transversale des plateaux
a. Pistes = groupe de secteurs contigüs
a. Secteur angulaire
:::
::::::
[//]: # ----------------------------------------------------------------
## Historique : premier disque dur
\footnotesize
Premier disque dur conçu en 1956 pour le super-computer IBM 305 Ramac
- Capacité : 4.8MB
- \scriptsize 50 plateaux de 60cm (24"), contenant chacun 100 pistes/faces, contenant chacune 5 secteurs de 100 octets
- Débit : 8.8KB/sec.
- Vitesse : 1200 tours/min.
- 2 têtes lecture/écriture, 1 sec. pour passer d'un plateau à l'autre
- Prix du système complet : $33'200/mois
\centering
![](images/IBM-305-RAMAC.jpg){ width=50% }
[//]: # ----------------------------------------------------------------
## Aujourd'hui
\small
- Les **disques durs mécanique (HDD)** utilisent les mêmes principes (cylindres, pistes, têtes, des secteurs), mais :
- \footnotesize performances et capacités ont augmenté exponentiellement
- adressage physique CHS remplacé par adressage logique : LBA (*Logical Block Addressing*)
- taille physique d'un secteur est souvent 4KB avec émulation à 512 bytes par le firmware
- Les **disques durs à base de flash[^1] (SSD)** ne comportent pas de partie mécanique, mais présentent aussi des secteurs de 512 bytes adressés logiquement en LBA (émulation réalisée par le firmware)
- \footnotesize la plupart des périphiques de stockage à base de flash sont similaires (clés USB, cartes SD, etc.)
[^1]: \tiny Flash de type NAND: [\textcolor{myblue}{https://www.arrow.com/en/research-and-events/articles/nand-memory-explained-understanding-pros-and-cons-of-nand}](https://www.arrow.com/en/research-and-events/articles/nand-memory-explained-understanding-pros-and-cons-of-nand)
[//]: # ----------------------------------------------------------------
## Structure d'un disque
\small
- Un disque est divisé en unités de taille identique appelées **secteurs**
- La taille typique d'un secteur est 512 bytes, mais il existe des secteurs plus grands (2KB, 4KB, etc.)
- Un secteur est la plus petite unité physique pouvant être lue ou écrite
- La lecture ou l'écriture d'un secteur est une opération **atomique**
\vspace{.2cm}
\centering
![](images/sectors.png){ width=80% }
[//]: # ----------------------------------------------------------------
## UNIX et blocs
- Dans un OS de type UNIX, on parle de blocs plutôt que de secteurs
- **But : s'abstraire du type de périphérique**
- Tout périphérique dont on peut lire/écrire les données par unités de 512, 1024, etc. bytes est géré par le module noyau de
gestion de lecture/écriture par blocs
- Permet d'être indépendant du type de périphérique $\rightarrow$ généricité
[//]: # ----------------------------------------------------------------
## Secteurs, blocs et clusters
\small
- L'unité d'allocation de base des systèmes de fichiers n'est pas le secteur, mais une unité plus grande (ou égale) appelée **bloc**[^2]
- **Un bloc est une collection contiguë de secteurs**
- Un système de fichiers (FS) divise l'espace disque en blocs de taille égale
- Généralement, un bloc fait entre 1KB et 8KB
- La commande `stat fichier` affiche la taille d'un bloc du FS où se trouve `fichier` (champ *IO Block*)
\vspace{.1cm}
\centering
![](images/block_and_cluster.png){ width=80% }
\vspace{.3cm}
[^2]: \footnotesize Microsoft appelle un bloc un *cluster*
[//]: # ----------------------------------------------------------------
## Interface périphérique bloc
Si on fait abstraction de la gestion du cache, l'interface d'accès à un périphérique de type bloc est très simple :
- Après initialisation de la taille d'un bloc, chaque bloc est adressable logiquement via son numéro par une fonction d'écriture et une fonction de lecture :
- `init_block_dev(dev, size)`
- `read_blocks(dev, block_nb, buf, count)`
- `write_blocks(dev, block_nb, buf, count)`
[//]: # ----------------------------------------------------------------
## Adressage
- Les blocs d'un périphérique de taille $N$ blocs de $n$ bytes chacun, sont adressables de $0$ à $N-1$ (comme un tableau en C)
- La lecture/écriture se fait uniquement par bloc, donc par unité de $n$ bytes
- La lecture/écriture du bloc $0$ traite les bytes de l'offset $0$ à l'offset $n-1$ du périphérique
- La lecture/écriture du bloc $b$ traite les bytes de l'offset $n*b$ à l'offset $n*(b+1)-1$
\vspace{.3cm}
\centering
![](images/addressing.png){ width=70% }
[//]: # ----------------------------------------------------------------
## Adressage : exemple
::: incremental
Exemple : périphérique de 10MB ($1024*1024*10$ bytes), taille de bloc de 1024 bytes
- Quelle est l'intervalle des offsets des bytes du bloc numéro 17 ?
- \textcolor{myorange}{$[1024*17,1024*(17+1)-1] = [17408,18431]$}
- Dans quel bloc se trouve le byte localisé à l'offset 7000 du périphérique ?
- \textcolor{myorange}{$7000/1024 = 6.8359375 = 6$}
- À quel offset du bloc est localisé le byte se trouvant à l'offset 7000 du périphérique ?
- \textcolor{myorange}{$7000\ \%\ 1024 = 856$}
:::
\vspace{.3cm}
\centering
![](images/addressing_example.png){ width=70% }
[//]: # ----------------------------------------------------------------
## Abstraction (1/2)
- Avec cet adressage logique, on peut facilement émuler un périphérique bloc à partir d'un fichier image
- On peut y accéder via les appels systèmes usuels `read` et `write`
- Ces appels système peuvent simplement être mappés sur les fonctions décrites précédemment :
- \small `init_block_dev(dev, size)` $\longrightarrow$ `fd = open(file)`
- `read_blocks(dev, block_nb, buf, count)` $\longrightarrow$ `read(fd)`
- `write_blocks(dev, block_nb, buf, count)` $\longrightarrow$ `write(fd)`
[//]: # ----------------------------------------------------------------
## Abstraction (2/2)
- Le fichier image peut-être distant, si on implémente l'abstraction au dessus des sockets et d'un protocole qui
reste très simple :
- \small `init_block_dev(dev, size)` $\longrightarrow$ `s = socket()`
- `read_blocks(block_nb, buf, count)` $\longrightarrow$ `read(s)`
- `write_blocks(block_nb, buf, count)` $\longrightarrow$ `write(s)`
[//]: # ----------------------------------------------------------------
## Conclusion
::: incremental
- On peut lire/écrire des blocs adressés logiquement, mais on est encore loin d'un FS
- Comment à partir de ces opérations simples, peut-on construire un FS ?
- Pour cela, il est nécessaire de comprendre l'allocation des blocs de données ainsi que l'organisation sur disque d'un FS
:::
[//]: # ----------------------------------------------------------------
## Ressources
\small
- Operating Systems: Three Easy Pieces, Remzi H. and Andrea C. Arpaci-Dusseau. Arpaci-Dusseau Books\
\footnotesize [\textcolor{myblue}{http://pages.cs.wisc.edu/~remzi/OSTEP/}](http://pages.cs.wisc.edu/~remzi/OSTEP/)
- livre disponible à la bibliothèque
---
author: Florent Gluck - Florent.Gluck@hesge.ch
title: Systèmes de fichiers - Stratégies d'allocation
date: \vspace{.5cm} \footnotesize \today
pandoc-latex-fontsize:
- classes: [tiny]
size: tiny
- classes: [verysmall]
size: scriptsize
- classes: [small]
size: footnotesize
- classes: [huge, important]
size: huge
---
## TODO
- Update FAT diagram:
- indicate a file's metadata with: first block, file size (along the type), type, etc.
- Update inode diagram:
- indicate a file's inode with: file size (along the type), permission, type, etc. and block pointers
- specify an inode has a fixed size
- update diagram to show the data blocks to "scale", especially vs an inode
- ext4: indicate that very small files' content is stored in the inode and don't use a data block
- would be good to the number of single ptr, indirect ptr, etc. for ext2, ext3 and ext4
[//]: # ----------------------------------------------------------------
## Système de fichiers
- Un système de fichiers (FS) est un ensemble de fichiers
- Les fichiers stockent des données
- Les fichiers et les répertoires sont tous deux des fichiers, mais de types différents
- Du point de vue du FS :
- un fichier ordinaire contient... les données du fichier
- un répertoires contient des entrées de répertoire (cf. suite du cours)
- Fichiers et répertoires sont représentés de la même manière, mais leurs contenus sont différents
[//]: # ----------------------------------------------------------------
## Fichier
Un fichier est composé de deux parties :
- **Métadonnées**
- type, permissions, (nom), propriétaire, pointeurs vers les données, etc.
- **Données (contenu)**
- fichier "ordinaire" : blocs contenant le contenu du fichier
- répertoire : blocs contenant les références vers les fichiers présents dans le répertoire
[//]: # ----------------------------------------------------------------
## Défi
- Comment organiser un FS hiérarchique en utilisant des blocs comme unité de base ?
- Comment rendre le FS performant ?
- en termes d'espace (pas d'espace perdu)
- en terme de lecture et d'écriture de fichiers
[//]: # ----------------------------------------------------------------
## Stratégies d'allocation des blocs de données
- La création d'un fichier ou d'un répertoire nécessite **d'allouer des blocs**
- La stratégie d'allocation des blocs de données (contenu) doit :
- être efficace en termes d'espace
- garantir un accès rapide aux fichiers
[//]: # ----------------------------------------------------------------
## Métriques d'allocation de blocs
Métriques principales:
- Les fichiers peuvent-ils grandir ?
- Performance des accès séquentiels
- Performance des accès aléatoires
- Facilité d'implémentation
- Fragmentation
- Efficacité du stockage/*overhead*
[//]: # ----------------------------------------------------------------
## Fragmentation interne
:::::: {.columns}
::: {.column width="50%"}
- L'espace alloué peut être plus grand que l'espace demandé
- **L'espace alloué non utilisé est gaspillé !**
:::
::: {.column width="50%"}
\centering
![](images/internal_fragmentation.png){ width=50% }
:::
::::::
[//]: # ----------------------------------------------------------------
## Fragmentation externe
:::::: {.columns}
::: {.column width="50%"}
- Bien qu'il y ait suffisamment d'espace libre au total, il n'y a pas assez d'espace libre contigu pour satisfaire la demande d'allocation
- **Impossible de satisfaire la demande d'allocation !**
:::
::: {.column width="50%"}
\centering
![](images/external_fragmentation.png){ width=80% }
:::
::::::
[//]: # ----------------------------------------------------------------
## Principales stratégies d'allocation de blocs
- Le choix de la stratégie d'allocation dépend :
- de la technologie de stockage (SSD, HDD, etc.)
- de la stratégie d'accès et le type d'utilisation
- lecture seule, gros fichiers, petits fichiers, fichiers grandissant beaucoup, etc.
- Stratégies d'allocation principales
1. contiguë
1. liste chaînée
1. indexée
[//]: # ----------------------------------------------------------------
## 1 | Allocation contiguë
- Chaque fichier utilise un ensemble de blocs contigus
- Un fichier stocke :
- l'index du premier bloc du fichier
- la taille du fichier
[//]: # ----------------------------------------------------------------
## 1 | Allocation contiguë : exemple
\centering
![](images/contiguous_alloc.png){ width=70% }
[//]: # ----------------------------------------------------------------
## 1 | Allocation contiguë : synthèse
- \textbf{\textcolor{mygreen}{Avantages}}
- très facile à implémenter
- accès séquentiel rapide
- accès aléatoire rapide
- faible *overhead* stockage (structure de données très simple)
- \textbf{\textcolor{myred}{Inconvénients}}
- les fichiers ne peuvent pas (ou peu) grandir
- fragmentation externe importante
- fragmentation interne lorsque taille fichier < taille bloc
[//]: # ----------------------------------------------------------------
## 2 | Allocation par liste chaînée
- Un fichier stocke :
- un pointeur sur le premier bloc
- la taille du fichier (ou un pointeur sur le dernier bloc)
- Les blocs sont stockés dans une liste chaînée
- chaque bloc possède un pointeur sur le bloc suivant
\vspace{.5cm}
![](images/linked_list.png){ width=70% }
\vspace{.3cm}
[//]: # ----------------------------------------------------------------
## 2 | Allocation par liste chaînée : exemple
\centering
![](images/linked_list_alloc.png){ width=70% }
[//]: # ----------------------------------------------------------------
## 2 | Allocation par liste chaînée : synthèse
- \textbf{\textcolor{mygreen}{Avantages}}
- les fichiers peuvent facilement grandir, sans limite
- facile à implémenter, mais le stockage des pointeurs est délicat
- pas de fragmentation externe
- \textbf{\textcolor{myred}{Inconvénients}}
- accès séquentiel lent
- accès aléatoire lent : adresse difficile à calculer
- fragmentation interne lorsque taille fichier < taille bloc
[//]: # ----------------------------------------------------------------
## 2b | Allocation par FAT
:::::: {.columns}
::: {.column width="63%"}
\small
- Variante de l'allocation par liste chaînée
- Les pointeurs de blocs sont stockés dans une table dédiée située au début du FS
- taille de la table d'allocation des fichiers (FAT)
- \footnotesize une entrée FAT par bloc de données
- \footnotesize liste chaînée d'entrées FAT par fichier
- \footnotesize valeur spéciale indique la fin de la liste (EOC = *End of Chain*)
- Système fichiers de MS-DOS et Winows 95, utilisé dans cartes SD et clés USB
- Nombreuses variantes : FAT16, FAT32, exFAT, etc.
:::
::: {.column width="37%"}
\centering
\vspace{.5cm}
\small
Structure sur disque du FS FAT
\vspace{.5cm}
![](images/FAT_disk_layout.png){ width=100% }
:::
::::::
[//]: # ----------------------------------------------------------------
## 2b | Contenu de la FAT : exemple
\centering
![](images/FAT_alloc.png){ width=100% }
[//]: # ----------------------------------------------------------------
## 2b | FS de type FAT : exemple
\small
Soit le FS de type FAT suivant :
- Le FS comporte 1'000 blocs de données
- Taille des blocs de données : 4 KB
- Chaque entrée dans la FAT est codée sur 16 bits
- une valeur est réservée pour représenter la EOC (*End Of Chain*)
::: incremental
**Questions**
1. Quelle est la taille de la FAT en bytes pour ce FS\ ?
- \footnotesize \textcolor{mygreen}{$1000*(16 bits)$ = 2000 bytes}
1. Quelle est la taille de fichier maximum supportée pour ce FS (en bytes, KB et MB)\ ?
- \footnotesize \textcolor{mygreen}{$1000*4096$ = 4096000 bytes, 4000 KB, 3.9 MB}
1. Combien de blocs de données cette FAT pourrait-elle gérer au maximum théoriquement\ ?
- \footnotesize \textcolor{mygreen}{$(2^{16})-1$ = 65535}
:::
[//]: # ----------------------------------------------------------------
## 2b | Allocation par FAT : synthèse
- \textbf{\textcolor{mygreen}{Avantages}}
- relativement facile à implémenter
- les fichiers peuvent facilement grandir (tant qu'il y a de l'espace dans la FAT)
- accès aléatoire rapide
- pas de fragmentation externe
- \textbf{\textcolor{myred}{Inconvénients}}
- accès séquentiel lent si les blocs ne sont pas contigus (HDD uniquement)
- *overhead* important pour le stockage de la FAT (disque et RAM), en particulier avec un grand nombre de clusters
- la FAT doit être chargée en RAM (sinon performances catastrophiques)
- fragmentation interne lorsque taille fichier < taille bloc
[//]: # ----------------------------------------------------------------
## 3 | Allocation indexée
- Chaque fichier est associé à un **inode** de taille fixe
- L'inode contient
- les métadonnées du fichier
- la liste des pointeurs vers les blocs de données
\vspace{.3cm}
\centering
![](images/indexed_alloc.png){ width=50% }
[//]: # ----------------------------------------------------------------
## 3b | Allocation indexée multi-niveau
\small
- L'inode stocke pointeurs directs, indirects, doublement indirects, etc.
- Utilisé par tous les FS dans les systèmes UNIX : minix-fs, ext2, ext3, etc.
\centering
![](images/multi_indexed_alloc.png){ width=90% }
[//]: # ----------------------------------------------------------------
## 3b | Allocation indexée multi-niveau : exemple
\small
Soit le FS de type indexé multi-niveau suivant :
- Un inode fait 64 bytes
- Un inode contient 8 pointeurs directs, 2 pointeurs indirects et 1 pointeur doublement indirect
- Un pointeur de bloc est stocké sur 16 bits
- Taille des blocs de données : 1 KB (1024 bytes)
::: incremental
**Questions**
1. Combien peut-on stocker de pointeurs par bloc\ ?
- \footnotesize \textcolor{mygreen}{$1024/2$ = 512}
1. Quelle est la taille de fichier maximum supportée pour ce FS (en bytes, KB et MB)\ ?
- \footnotesize \textcolor{mygreen}{$8*1024 + (512*1024)*2 + (512^2)*1024$ = 269492224 bytes, 263176 KB, 257 MB }
:::
<!--
1. Combien peut-on stocker d'inodes par bloc\ ?
- \footnotesize \textcolor{mygreen}{$1024/64$ = 16}
-->
[//]: # ----------------------------------------------------------------
## 3b | Allocation indexée : synthèse
- \textbf{\textcolor{mygreen}{Avantages}}
- relativement facile à implémenter
- les fichiers peuvent facilement grandir (tant qu'il y a des pointeurs libres)
- accès aléatoire rapide
- pas de fragmentation externe
- \textbf{\textcolor{myred}{Inconvénients}}
- *overhead* de stockage pour les pointeurs
- l'accès rapide nécessite l'allocation de blocs contigus (HDD uniquement)
- sinon, accès potentiellement lent
- fragmentation interne lorsque taille fichier < taille bloc
[//]: # ----------------------------------------------------------------
## 3c | Allocation par extent
- Principe similaire à l'allocation indexée
- **Différence** : un pointeur référence un **\textit{extent}** plutôt qu'un bloc
- *Extent* = ensemble de blocs contigüs
- représenté par le tuple : `{ FirstBlockAddress, Length }`
- Exemple : 64 bits par *extent* :
- 48 bits pour l'indice du 1er bloc
- 16 bits pour la longueur (= nombre de blocs)
- **Avantages** : moins de blocs à stocker si la plupart des allocations sont contiguës
- Utilisé par les FS "modernes" : ext4, btrfs, ntfs, xfs, etc.
[//]: # ----------------------------------------------------------------
## 3c | Allocation par extent : synthèse
- \textbf{\textcolor{mygreen}{Avantages}}
- les fichiers peuvent grandir (tant qu'il y a des extents libres)
- accès séquentiel rapide
- accès aléatoire rapide
- faible *overhead* stockage (structure de données simple)
- \textbf{\textcolor{myred}{Inconvénients}}
- fragmentation externe potentielle
- \ plus complexe que l'allocation indexée
- fragmentation interne lorsque taille fichier < taille bloc
[//]: # ----------------------------------------------------------------
## Ressources
\small
- Operating Systems: Three Easy Pieces, Remzi H. and Andrea C. Arpaci-Dusseau. Arpaci-Dusseau Books\
\footnotesize [\textcolor{myblue}{http://pages.cs.wisc.edu/~remzi/OSTEP/}](http://pages.cs.wisc.edu/~remzi/OSTEP/)
- livre disponible à la bibliothèque
---
author: Florent Gluck - Florent.Gluck@hesge.ch
title: Systèmes de fichiers - Structure sur disque
date: \vspace{.5cm} \footnotesize \today
institute: \vspace{0.5cm} \tiny \textsuperscript{*}Remerciements à Mickaël Hoerdt
pandoc-latex-fontsize:
- classes: [tiny]
size: tiny
- classes: [verysmall]
size: scriptsize
- classes: [small]
size: footnotesize
- classes: [huge, important]
size: huge
---
[//]: # ----------------------------------------------------------------
## Concepts clés d'un système de fichiers stocké
1. Quelles sont les structures de données stockées sur le disque qui organisent les méta-données et le contenu des fichiers ?
1. Comment est-ce que ces structures de données sont-elles reliées les unes aux autres ?
1. Quelles sont les interfaces d'accès au système de fichiers (FS) ?
- comment est-ce que le système associe p.ex. `open()`, `read()` et `write()` aux points 1 et 2 ?
[//]: # ----------------------------------------------------------------
## Exemple de structure simple d'un FS
\small
Soit un FS constitué de 64 blocs
\vspace{.2cm}
\centering
![](images/simple_fs1.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Exemple de structure simple d'un FS
\small
Le bloc 0 est réservé : contient potentiellement le secteur de boot et la table de partitions
\vspace{.2cm}
\centering
![](images/simple_fs2.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Blocs de données
\small
Pour stocker des données il est préférable que la majorité des blocs soient réservés pour cela (blocs de données)
\vspace{.2cm}
\centering
![](images/simple_fs3.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Allocation des blocs de données
\footnotesize
- Un tableau de bits indique quels blocs de données sont disponibles/utilisés
- Appelé **bitmap de blocs**
- Contient autant de bits qu'il y a de blocs de données
\centering
![](images/simple_fs4.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Exemple de bitmap pour les blocs de données
\small
- Soit 3 blocs de données utilisés : 2, 3 et 6
- Bitmap contient : 0,0,1,1,0,0,1,0,0,...
\centering
![](images/simple_fs5.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Allocation des blocs de données
- Un bitmap pour allouer les blocs n'est qu'un exemple de structure d'allocation
- D'autres structures sont possibles : listes, arbres, etc.
- On peut donc allouer/libérer des blocs de données, mais on veut aussi associer des blocs à un/des fichiers
[//]: # ----------------------------------------------------------------
## Association blocs de données $\leftrightarrow$ fichiers
\small
- C'est la fonction principale des **inodes**
- Les inodes contiennent également les méta-données des fichiers
\centering
![](images/simple_fs6.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Inodes
- La taille d'un inode est fixe pour un FS donné
- Le inodes sont stockés de manière **contigüe** au début du FS
- appelé la **table d'inodes**
- Selon le FS, la taille varie (typiquement divise la taille d'un secteur, 512 bytes)
- La taille d'un inode est définie à la création du FS
- Un petit FS (= faible nombre de blocs) aura typiquement une taille d'inode inférieure à un grand FS
- Soit des blocs de 4 KB et une taille d'inode de 128 bytes
- combien d'inodes par bloc ?
[//]: # ----------------------------------------------------------------
## Table d'inodes
\small
Exemple d'une table d'inodes utilisant 2 blocs
- Taille de bloc : 2 KB
- Taille d'inode : 128 bytes
**\textcolor{myred}{Les inodes sont indexés à 1}**
\vspace{.3cm}
\centering
![](images/inodes_table.png){ width=75% }
[//]: # ----------------------------------------------------------------
## Relation fichier $\leftrightarrow$ inode
- Chaque fichier est associé **exactement** à 1 inode
- Chaque n° d'inode est **unique** à un FS donné
- Des FS différents peuvent utiliser les mêmes n° d'inodes
- Le n° d'inode d'un fichier supprimé est réutilisé par le FS
[//]: # ----------------------------------------------------------------
## Historique du nom "inode"
"In truth, I don't know either. It was just a term that we started to use. ‘Index’ is my best guess, because of the
slightly unusual file system structure that stored the access information of files as a flat array on the disk..."
\vspace{.5cm}
Dennis Ritchie[^1]
[^1]: \footnotesize Un des deux principaux créateurs d'UNIX, l'autre étant Ken Thompson
[//]: # ----------------------------------------------------------------
## Structure d'un inode
\small
Structure typique, mais qui peut varier en fonction du FS :
\scriptsize
**Champ** **Description**
-------------- -----------------------------
`type` \textcolor{myblue}{Fichier}, \textcolor{myorange}{répertoire}, device, lien, etc.
`uid` UID du propriétaire
`gid` GID du propriétaire
`rwx` Permissions (droits d'accès)
`size` Taille en bytes
`time` Date du dernier accès
`n_links` Nombre de liens/chemins d'accès vers l'inode
`direct[N]` Pointeurs directs vers les blocs du contenu du
fichier, **dans l'ordre**
`indir[M]` Pointeurs indirects vers les blocs du contenu
du fichier, **dans l'ordre**
`dbl_indir[P]` Pointeurs doublement indirects vers les blocs
du contenu du fichier, **dans l'ordre**
\vspace{-.3cm}
Une valeur de 0 dans les n° indique une entrée non-utilisée
[//]: # ----------------------------------------------------------------
## Allocation des blocs de données dans un inode
\small
Exemple avec : 10 pointeurs directs, 1 pointeur indirect, 1 pointeur doublement indirect et 1 pointeur triplement indirect
\vspace{.3cm}
\centering
![](images/multi_indexed_alloc.png){ width=90% }
[//]: # ----------------------------------------------------------------
## Contenu des fichiers
- Un fichier de **type \textcolor{myblue}{fichier}** est un fichier habituel dont les données (contenu) peuvent être :
- du texte si c'est un fichier texte
- des données d'image si c'est un fichier png
- des données audio si c'est un fichier flac
- etc.
- Un fichier de **type \textcolor{myorange}{répertoire}** (*directory*) est un fichier qui contient des entrées de répertoires (*directory entries*)
[//]: # ----------------------------------------------------------------
## Entrée de répertoire
- Une entrée de répertoire associe simplement un nom à un inode
- Structure d'une entrée de répertoire (`dir_entry`) :
**Champ** **Description**
-------------- -----------------------------
`inode` numéro d'inode du fichier
`name` nom associé à cet inode (fichier)
\vspace{.3cm}
**\textcolor{myred}{Un fichier n'est donc pas caractérisé par son nom, mais par son inode !}**
[//]: # ----------------------------------------------------------------
## Contenu d'un répertoire
\small
- Le contenu d'un fichier de type **\textcolor{myorange}{répertoire}** contient des entrées de répertoires
- Par convention, dans la plupart des FS, l'inode n° 1 est le répertoire racine du FS : `/`
\vspace{.2cm}
\centering
![](images/dir_content.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Liens symboliques
\small
- En Anglais : *soft links* ou *symbolic links*
- Un fichier de type **lien symbolique** a comme contenu (1 seul bloc de donnée) une chaîne de caractères représentant le chemin de destination du lien
- Lors de l'analyse d'un chemin d'accès, si le système rencontre un lien symbolique, alors son contenu est concaténé avec le chemin déjà parcouru
- `ln -s` permet de créer un lien symbolique
- Exemple : créé le lien symbolique `pipo.c` vers `code/src/prog.c` :
```{.shell .verysmall}
ln -s code/src/prog.c pipo.c
```
[//]: # ----------------------------------------------------------------
## Liens symboliques : considérations importantes
- Un lien symbolique peut pointer vers un fichier ou un répertoire
- Un lien symbolique peut traverser les FS
- il est possible de créer un lien symbolique X sur le FS1 qui pointe vers le fichier Y sur le FS2
- Si la destination d'un lien symbolique est déplacée ou supprimée, le lien symbolique devient alors invalide\ !
[//]: # ----------------------------------------------------------------
## Liens durs
- En Anglais : *hard links*
- Un **lien dur** est simplement une nouvelle entrée de répertoire (`dir_entry`) pointant vers un inode donné
- En d'autres termes, il s'agit simplement d'un nom supplémentaire pointant vers le même inode
- `ln` permet de créer un lien dur
- Exemple : créé le lien dur `pipo.c` vers `code/src/prog.c` :
```{.shell .verysmall}
ln code/src/prog.c pipo.c
```
[//]: # ----------------------------------------------------------------
## Liens durs : considérations importantes
- Un lien dur ne peut pas pointer vers un répertoire
- Un lien dur ne peut pas traverser les FS car un numéro d'inode est seulement unique à un FS\ !
- La valeur `Links` affichée par la commande `stat` indique le nombre de `dir_entry` pointant sur le fichier (inode)
- \textcolor{myred}{Un fichier (inode) n'est \textbf{réellement supprimé} que lorsque le dernier \texttt{dir\_entry} (lien dur) pointant dessus est supprimée !}
- aussi, si un descripteur de fichier ouvert référence ce fichier (inode), alors le fichier ne sera supprimé que lorsque le dernier descripteur sera fermé
- Les liens durs (ou `dir_entry`) sont donc simplement des références vers un inode (fichier)
[//]: # ----------------------------------------------------------------
## Allocation des inodes
\small
- Similairement à l'allocation des blocs de données, on utilise un bitmap
- D'autres structures sont possibles : listes, arbres, etc.
\centering
![](images/simple_fs7.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Superblock
\small
Le superblock stocke des informations globales sur le FS :
- Signature du FS, nombre d'inodes total, nombre de blocs total, taille du bitmap des inodes, etc.
\centering
![](images/simple_fs8.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Combien d'inodes ?
Le nombre d'inodes détermine le nombre maximum de fichiers pouvant être créés sur un FS
\vspace{.5cm}
**\textcolor{myred}{Combien d'inodes faut-il réserver pour un FS d'une taille donnée ?}**
[//]: # ----------------------------------------------------------------
## Combien d'inodes : mkfs.minix
- `mkfs.minix` se base sur la taille du disque (`DS`) ; ci-dessous `fs_blocks` = nombre total de blocs dans le FS
- Si `DS` > 2 GB alors `inodes = fs_blocks/16`
- Si `DS` > 500 MB alors `inodes = fs_blocks/8`
- Sinon : `inodes = fs_blocks/3`
- Ensuite, arrondi au prochain multiple de la taille d'un inode (32 bytes)
- Exemple :
- soit un disque de 64 MB et des blocs de 1 KB\
$\rightarrow$ `inodes = (64*1024/3 + 32) & 0xFFFFFFE0 = 21856`
[//]: # ----------------------------------------------------------------
## Combien d'inodes : mke2fs (ext2/3/4)
- `mke2fs` se base sur un paramètre nommée \textcolor{myblue}{\texttt{bytes-per-inode}}
- Indique de créér un inode pour chaque \textcolor{myblue}{\texttt{bytes-per-inode}} bytes d'espace disque
- Exemple :
- soit un disque de 64 MB et \textcolor{myblue}{\texttt{bytes-per-inode}} = 4096\
$\rightarrow$ `inodes = 64*1024*1024/4096 = 16384`
[//]: # ----------------------------------------------------------------
## Ressources
\small
- Operating Systems: Three Easy Pieces, Remzi H. and Andrea C. Arpaci-Dusseau. Arpaci-Dusseau Books\
\footnotesize [\textcolor{myblue}{http://pages.cs.wisc.edu/~remzi/OSTEP/}](http://pages.cs.wisc.edu/~remzi/OSTEP/)
- livre disponible à la bibliothèque
\small
- `mkfs.minix` source code\
\footnotesize [\textcolor{myblue}{https://github.com/util-linux/util-linux/blob/master/disk-utils/mkfs.minix.c}](https://github.com/util-linux/util-linux/blob/master/disk-utils/mkfs.minix.c)
\small
- The Second Extended File System - Internal Layout\
\footnotesize [\textcolor{myblue}{https://www.nongnu.org/ext2-doc/ext2.html}](https://www.nongnu.org/ext2-doc/ext2.html)
\small
- Ext4 (and Ext2/Ext3) Wiki\
\footnotesize [\textcolor{myblue}{https://ext4.wiki.kernel.org/index.php/Main\_Page}](https://ext4.wiki.kernel.org/index.php/Main_Page)
---
author: Florent Gluck - Florent.Gluck@hesge.ch
title: Systèmes de fichiers - MINIX-fs
date: \vspace{.5cm} \footnotesize \today
institute: \vspace{0.5cm} \tiny \textsuperscript{*}Remerciements à Mickaël Hoerdt
pandoc-latex-fontsize:
- classes: [tiny]
size: tiny
- classes: [verysmall]
size: scriptsize
- classes: [small]
size: footnotesize
- classes: [huge, important]
size: huge
---
## TODO
- Ajouter slide expliquant comment débogger une image:
- en la montant puis en la parcourant
- "ls -i file" affiche le n° d'inode de "file
- "stat file" affiche n° inode, link count, etc.
- "tree --inodes -p -s -a" affiche arborescence avec n°inodes, permissions+type, tailles
- "-a" affiche également les fichiers cachés
[//]: # ----------------------------------------------------------------
## Introduction à MINIX-fs
- MINIX-fs est le système de fichiers (FS) natif du système d'exploitation MINIX écrit par Andrew S. Tanenbaum en 1987
- Le but de MINIX-fs était :
- de répliquer la structure du FS de UNIX, mais sans les fonctionnalités avancées et complexes de ce dernier
- de fournir une aide à l'enseignement des systèmes de fichiers et des OS
[//]: # ----------------------------------------------------------------
## Linux et MINIX-fs
- Les premières versions du noyau Linux (1992) utilisaient MINIX-fs comme FS
- 1992 : Rémy Card implémente ext (Extended Filesystem) pour remplacer MINIX-fs
- ext est basé sur une structure similaire à MINIX-fs
- 1993 : Rémy Card publie ext2
- 2001 : Theodore Ts'o et d'autres publient ext3
- 2006 : la version instable de ext4 est publiée
- 2008 : la version stable de ext4 est publiée
[//]: # ----------------------------------------------------------------
## Versions de MINIX-fs
- Il existe 3 versions de MINIX-fs : v1, v2 et v3
- Nous présentons ici la v1 car c'est la plus simple
- Il existe deux variantes de MINIX-fs v1 :
- variante avec noms de fichiers de 14 caractères max (superblock magic value `0x137F`)
- variante avec noms de fichiers de 30 caractères max (superblock magic value `0x138F`)
[//]: # ----------------------------------------------------------------
## Comparaison MINIX-fs et ext2/3/4
Valeurs max pour les caractéristiques principales des FS :
\footnotesize
**Name** **FS** **File** **Block** **Extent** **File length**
------------- --------------- -------------------- --------------- ---------- ---------------
MINIX-fs v1.0 256 MB 256 MB 1 KB (fixed) n/a 14/30
ext 2 GB 2 GB ? n/a 255
ext2 32 TB 2 TB 8 KB n/a 255
ext3 32 TB 2 TB 8 KB n/a 255
ext4 1 EB 16 TB 4 KB 128 MB 255
\small
Remarque : ext3 est simplement ext2 avec l'ajout d'un journal
[//]: # ----------------------------------------------------------------
## Structure générale
\small
Structure générale sur disque de MINIX-fs v1.0
\vspace{.5cm}
\centering
![](images/minix_gen_struct.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Structure des inodes
\small
Structure d'un inode dans MINIX-fs v1.0 :
\vspace{.2cm}
```{.c .verysmall}
struct minix_inode {
u16 i_mode; // file type and permissions for file
u16 i_uid; // user id
u32 i_size; // file size in bytes
u32 i_time; // inode time
u8 i_gid; // group id
u8 i_nlinks; // number of dir entry pointing to
// this inode
u16 i_zone[7]; // direct pointers
u16 i_indir_zone; // indirect pointer
u16 i_dbl_indir_zone; // double indirect pointer
};
```
- **Important** : structure sur disque stockée selon l'ordre *little-endian*
- Taille d'un inode en bytes ?
[//]: # ----------------------------------------------------------------
## Structure du mode du fichier
Format du champs `i_mode` (16 bits) de l'inode :
\footnotesize
**Bits** **Description**
---------------- -------------------------- ---------------------------
`12-15` Type de fichier : `0x1` : named pipe (FIFO)
`0x2` : char device
`0x4` : directory
`0x6` : block device
`0x8` : regular file
`0xA` : symbolic link
`11` SUID bit
`10` SGID bit
`9` Sticky bit
`6-8` user permissions (rwx)
`3-5` group permissions (rwx)
`0-2` others permissions (rwx)
[//]: # ----------------------------------------------------------------
## Structure des entrées de répertoires
Structure d'une entrée de répertoire dans MINIX-fs v1.0 :
\vspace{.2cm}
```{.c .verysmall}
// Variante : superblock magic 0x137F
#define MINIX_NAME_LEN 14
struct minix_dir_entry {
u16 inode;
char name[MINIX_NAME_LEN];
};
```
- Taille d'un `dir_entry` en bytes ?
[//]: # ----------------------------------------------------------------
## Structure du superbloc
Structure du superbloc dans MINIX-fs v1.0 :
\vspace{.2cm}
```{.c .tiny}
struct minix_super_block {
u16 s_ninodes; // total number of inodes
u16 s_nzones; // total number of blocks (including superblock)
u16 s_imap_blocks; // inodes bitmap size in blocks
u16 s_zmap_blocks; // data blocks bitmap size in blocks
u16 s_firstdatazone; // index of first data block
u16 s_log_zone_size; // block size in bytes = 1024*2^s_log_zone_size
u32 s_max_size; // max file size in bytes
u16 s_magic; // 0x137f = v1 with 14 characters dir_entry
// 0x138f = v1 with 30 characters dir_entry
u16 s_state; // was the FS properly unmounted?
};
```
- Taille du superbloc en bytes ?
[//]: # ----------------------------------------------------------------
## Exemple de superbloc
- Soit un disque de 20 MB et une taille de bloc de 1 KB\
$\rightarrow$ `fs_blocks` = nombre de blocs au total
- Nombre inodes = `(fs_blocks/3 + 32) & 0xFFFFFFE0`[^1]
\vspace{.2cm}
```{.c .tiny}
struct minix_super_block {
u16 s_ninodes = 6848; // total number of inodes
u16 s_nzones = 20480; // total number of blocks
// = (20*1024^2)/1024
u16 s_imap_blocks = 1; // inodes bitmap size in blocks
// need 6848 bits
// -> 1 block = 8192 bits
u16 s_zmap_blocks = 3; // data blocks bitmap size in blocks
// need 20480 bits -> 3 blocks = 8192*3 bits
u16 s_firstdatazone = 220; // index of first data block
u16 s_log_zone_size = 0; // block size = 1024*2^s_log_zone_size
// = 1024*2^0 = 1024
u32 s_max_size = 268966912; // max file size in bytes
// = (7+(1024/2)+(1024/2)^2)*1024
u16 s_magic = 0x137F; // 0x137f Minix filesystem version 1
u16 s_state = 1; // was the FS properly unmounted?
};
```
[^1]: \scriptsize permet d'arrondir au prochain multiple de la taille d'un inode
[//]: # ----------------------------------------------------------------
## Exemple de superbloc
```{.c .tiny}
struct minix_super_block {
u16 s_ninodes = 6848; // total number of inodes
u16 s_nzones = 20480; // total number of blocks
// = (20*1024^2)/1024
u16 s_imap_blocks = 1; // inodes bitmap size in blocks
// need 6848 bits
// -> 1 block = 8192 bits
u16 s_zmap_blocks = 3; // data blocks bitmap size in blocks
// need 20480 bits -> 3 blocks = 8192*3 bits
u16 s_firstdatazone = 220; // index of first data block
u16 s_log_zone_size = 0; // block size = 1024*2^s_log_zone_size
// = 1024*2^0 = 1024
u32 s_max_size = 268966912; // max file size in bytes
// = (7+(1024/2)+(1024/2)^2)*1024
u16 s_magic = 0x137F; // 0x137f Minix filesystem version 1
u16 s_state = 1; // was the FS properly unmounted?
};
```
\centering
![](images/minix_example.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Exemple d'inode - fichier répertoire
Contenu de l'inode 1, la racine du FS
\vspace{.2cm}
```{.c .verysmall}
struct minix_inode {
u16 i_mode = 0x41ED; // 0x4 = directory
// 0x1ED = 755 in octal
// = rwx r-x r-x
u16 i_uid = 0; // 0 = root
u32 i_size = 256; // 256/16 = 16 dir_entry
u32 i_time = 1701436374; // seconds since 1/1/1970
u8 i_gid = 0; // 0 = root
u8 i_nlinks = 8; // 8 dir entries point to
// this inode
u16 i_zone[7] = {220, 0, 0, 0, 0, 0, 0 }; // 1 data block
u16 i_indir_zone = 0; // no indirect block
u16 i_dbl_indir_zone = 0; // no double indirect block
};
```
[//]: # ----------------------------------------------------------------
## Exemple de bloc de données - contenu répertoire
\footnotesize
1er bloc de données référencé par l'inode 1\
- bloc 220 (offset = 220*1024 = 0x37000)
```{.tiny}
00037000 01 00 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037010 00 00 79 6F 00 00 00 00 00 00 00 00 00 00 00 00 ..yo............
00037020 01 00 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037040 02 00 72 6F 6F 74 00 00 00 00 00 00 00 00 00 00 ..root..........
00037050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037060 03 00 62 69 6E 00 00 00 00 00 00 00 00 00 00 00 ..bin...........
00037070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037080 04 00 75 73 72 00 00 00 00 00 00 00 00 00 00 00 ..usr...........
00037090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000370A0 0A 00 65 74 63 00 00 00 00 00 00 00 00 00 00 00 ..etc...........
000370B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000370C0 0F 00 74 6D 70 00 00 00 00 00 00 00 00 00 00 00 ..tmp...........
000370D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000370E0 32 00 64 65 76 00 00 00 00 00 00 00 00 00 00 00 2.dev...........
000370F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
```
\scriptsize
- Les noms `.` (0x2E) et `..` (0x2E2E) pointent sur l'inode 1 (la racine)
- 7 répertoires : `root`, `bin`, `usr`, `etc`, `tmp`, `dev` (inodes 1, 2, 3, 4, 0xA, 0xF, 0x32)
- 8 `dir_entry` inutilisées (inodes à 0) ; rappel : une entrée fait 16 bytes
[//]: # ----------------------------------------------------------------
## Exemple d'inode - fichier répertoire
Contenu de l'inode 2, répertoire `/root`
\vspace{.2cm}
```{.c .verysmall}
struct minix_inode {
u16 i_mode = 0x41ED; // 0x4 = directory
// 0x1ED = 755 in octal
// = rwx r-x r-x
u16 i_uid = 0; // 0 = root
u32 i_size = 160; // 160/16 = 10 dir_entry
u32 i_time = 1701436512; // seconds since 1/1/1970
u8 i_gid = 0; // 0 = root
u8 i_nlinks = 2; // 2 dir entries point to
// this inode
u16 i_zone[7] = {221, 0, 0, 0, 0, 0, 0 }; // 1 data block
u16 i_indir_zone = 0; // no indirect block
u16 i_dbl_indir_zone = 0; // no double indirect block
};
```
[//]: # ----------------------------------------------------------------
## Exemple de bloc de données - contenu répertoire
\small
1er bloc de données référencé par l'inode 2\
- bloc 221 (offset = 221*1024 = 0x37400)
\vspace{.2cm}
```{.tiny}
00037400 02 00 2E 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037410 6C 03 6C 69 6E 75 78 00 00 00 00 00 00 00 00 00 l.linux.........
00037420 01 00 2E 2E 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037440 09 00 73 79 73 74 65 6D 00 00 00 00 00 00 00 00 ..system........
00037450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037460 0B 00 68 65 6C 6C 6F 2E 63 00 00 00 00 00 00 00 ..hello.c.......
00037470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00037480 0E 00 2E 62 61 73 68 5F 6C 6F 67 69 6E 00 00 00 ...bash_login...
00037490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
```
\footnotesize
- Le nom `.` (0x2E) pointe sur l'inode 2 (lui même)
- Le nom `.` (0x2E2E) pointe sur le répertoire parent, l'inode 1 (la racine)
- Il y a 2 répertoires : `linux` (inode 0x36C) et `system` (inode 0x9)
- Il y a 2 fichiers : `hello.c` (inode 0xB) et `.bash_login` (inode 0xE)
- Il y a 4 `dir_entry` inutilisées (inodes à 0)
[//]: # ----------------------------------------------------------------
## Exemple d'inode - fichier régulier
Contenu de l'inode 11 (0xB)
\vspace{.2cm}
```{.c .verysmall}
struct minix_inode {
u16 i_mode = 0x81A4; // 0x8 = regular file
// 0x1A4 = 644 in octal
// = rw- r-- r--
u16 i_uid = 0; // 0 = root
u32 i_size = 63; // 1 data block (1 KB/block)
u32 i_time = 1426700385; // seconds since 1/1/1970
u8 i_gid = 0; // 0 = root
u8 i_nlinks = 1; // 1 dir entry points to this inode
u16 i_zone[7] = { 583 0 0 0 0 0 0 }; // 1 data block
u16 i_indir_zone = 0; // no indirect block
u16 i_dbl_indir_zone = 0; // no double indirect block
};
```
[//]: # ----------------------------------------------------------------
## Exemple de bloc de données - contenu fichier régulier
\small
Contenu du 1er bloc de données référencé par l'inode 11\
- bloc 583 (offset = 583*1024 = 0x91C00)
\vspace{.2cm}
```{.tiny}
00091C00 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E #include <stdio.
00091C10 68 3E 0A 0A 76 6F 69 64 20 6D 61 69 6E 28 29 0A h>..void main().
00091C20 7B 0A 09 09 70 72 69 6E 74 66 28 22 48 65 6C 6C {...printf("Hell
00091C30 6F 20 57 6F 72 6C 64 5C 6E 22 29 3B 0A 7D 0A 00 o World\n");.}..
00091C40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091C50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091C60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091C70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091C80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091C90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091CA0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091CB0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091CC0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00091CD0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
```
[//]: # ----------------------------------------------------------------
## Exemple d'inode - fichier régulier
Contenu de l'inode 16
\vspace{.2cm}
```{.c .verysmall}
struct minix_inode {
u16 i_mode = 0x81C9; // 0x8 = regular file
// 0x1C9 = 711 in octal
// = rwx --x --x
u16 i_uid = 0; // 0 = root
u32 i_size = 283652; // 278 data blocks (1 KB/block)
u32 i_time = 1426700385; // seconds since 1/1/1970
u8 i_gid = 0; // 0 = root
u8 i_nlinks = 2; // 2 dir entries point to this inode
u16 i_zone[7] = { 588 589 590 591 592 593 594 };
// 7 data blocks
u16 i_indir_zone = 595; // block 595 contains 271 pointers
u16 i_dbl_indir_zone = 0; // no double indirect block
};
```
[//]: # ----------------------------------------------------------------
## Exemple de bloc de données - contenu fichier régulier
\small
Contenu du bloc indirect référencé par l'inode 11\
- bloc 595 (offset = 595*1024 = 0x94C00)
\vspace{.2cm}
```{.tiny}
00094C00 54 02 55 02 56 02 57 02 58 02 59 02 5A 02 5B 02 T.U.V.W.X.Y.Z.[.
00094C10 5C 02 5D 02 5E 02 5F 02 60 02 61 02 62 02 63 02 \.].^._.`.a.b.c.
00094C20 64 02 65 02 66 02 67 02 68 02 69 02 6A 02 6B 02 d.e.f.g.h.i.j.k.
00094C30 6C 02 6D 02 6E 02 6F 02 70 02 71 02 72 02 73 02 l.m.n.o.p.q.r.s.
00094C40 74 02 75 02 76 02 77 02 78 02 79 02 7A 02 7B 02 t.u.v.w.x.y.z.{.
00094C50 7C 02 7D 02 7E 02 7F 02 80 02 81 02 82 02 83 02 |.}.~...........
00094C60 84 02 85 02 86 02 87 02 88 02 89 02 8A 02 8B 02 ................
00094C70 8C 02 8D 02 8E 02 8F 02 90 02 91 02 92 02 93 02 ................
00094C80 94 02 95 02 96 02 97 02 98 02 99 02 9A 02 9B 02 ................
00094C90 9C 02 9D 02 9E 02 9F 02 A0 02 A1 02 A2 02 A3 02 ................
00094CA0 A4 02 A5 02 A6 02 A7 02 A8 02 A9 02 AA 02 AB 02 ................
...
```
- Prochains blocs de données : 0x254, 0x255, 0x256, 0x257, ...
[//]: # ----------------------------------------------------------------
## Important : inodes
\small
- Le nombre total d'inodes pouvant être créés dans le FS est indiqué par le champs `ninodes` du superbloc
- La table des inodes possède `ninodes` entrées
- Le premier inode de la table (à l'indice 0) est l'inode 1
- \footnotesize il n'y a donc pas d'inode 0 !
- **Attention** : le bit 0 du bitmap indique l'état de l'inode 0\ !
- \footnotesize le bit 0 est toujours à 1 (utilisé), bien que l'inode 0 n'existe pas
- un FS vide aura donc 2 bits à 1 dans le bitmap\ : le bit 0 (inode 0) et le bit 1 (inode 1 = répertoire racine)
En conséquence :
\vspace{-.3cm}
- Pour lire le contenu de l'inode `n`, il faut lire l'entrée à l'indice `(n-1)` dans la table des inodes
- Pour savoir si l'inode `n` est utilisé, il faut lire le bit à l'indice `n` dans le bitmap des inodes
[//]: # ----------------------------------------------------------------
## Important : blocs de données
\small
- Les n° de blocs dans l'inode sont relatifs au début du FS
- Le bitmap des blocs de données indique uniquement l'état des **blocs de données** utilisés (donc pas superbloc, bitmaps, etc.)
- **Attention** : le bit 0 du bitmap des blocs de données est à **ignorer**\ !
- \footnotesize il est toujours à 1 et ne représente aucun bloc de données
- le bit 1 du bitmap correspond au bloc `firstdatazone` indiqué dans le superbloc
- il correspond donc au premier bloc de données
En conséquence[^2] :
\vspace{-.3cm}
- Tout bloc n indiqué dans l'inode correspond à l'indice `(n-firstdatazone+1)` dans le bitmap des blocs de données
- Nombre total de blocs de données : `(nzones-firstdatazone)`
[^2]: \scriptsize \texttt{firstdatazone} et \texttt{nzones} sont les champs du même nom dans le superbloc
<!--
-`firstdatazone` est le champs du même nom dans le superbloc (= nombre de blocs utilisés par\ : superbloc + bitmaps + table d'inodes)
- \footnotesize si le premier bloc de données est le bloc 110, celui-ci correspond au bit 1 dans le bitmap
- le bit 3 du bitmap correspond donc au bloc 113, etc.
-->
[//]: # ----------------------------------------------------------------
## Rappel : *endianness* (1/2)
- L'*endianness* défini la manière dont les entiers sont stockés en mémoire
\vspace{.2cm}
- ***Big-endian***
- le byte le plus significatif (d'un mot) est stocké à l'adresse la plus basse
- le byte le moins significatif est stocké à l'adresse la plus haute
\vspace{.2cm}
- ***Little-endian***
- le byte le plus significatif (d'un mot) est stocké à l'adresse la plus haute
- le byte le moins significatif est stocké à l'adresse la plus basse
[//]: # ----------------------------------------------------------------
## Rappel : *endianness* (2/2)
Exemple de valeurs 8 bits, 16 bits et 32 bits, en représentation hexadécimale, où les adresses "grandissent" de gauche à droite :
\vspace{.3cm}
\small
**Taille de mot** **Valeur** **Big-endian** **Little-endian**
----------------- ----------- -------------- -----------------
8 bits (1 byte) `4c` `4c` `4c`
16 bits (2 bytes) `4c3f` `4c 3f` `3f 4c`
32 bits (4 bytes) `4c3f85ed` `4c 3f 85 ed` `ed 85 3f 4c`
[//]: # ----------------------------------------------------------------
## Sérialisation/déserialisation de structure
- **Sérialisation** de structure = écriture, en une opération, d'une structure sur un fichier, un socket, un pipe, etc.
- typiquement via un appel à `write` ou `fwrite`
\vspace{.3cm}
- **Déserialisation** de structure = lecture, en une opération, depuis un fichier, un socket, un pipe, etc. dans une structure
- typiquement via un appel à `read` ou `fread`
[//]: # ----------------------------------------------------------------
## Danger avec la sérialisation/déserialisation
```{.c .tiny}
struct st1 { struct __attribute__ ((__packed__)) st2 {
uint8_t tab[7]; uint8_t tab[7];
uint16_t n; uint16_t n;
uint32_t big; uint32_t big;
uint8_t x; uint8_t x;
uint8_t y; uint8_t y;
}; };
int main() {
printf("%ld %ld\n", sizeof(struct st1), sizeof(struct st2));
return 0;
}
```
::: incremental
- Affichage ?
- **`20 15`**
- Pourquoi ?
- Conséquence : **\textcolor{myred}{toujours}** utiliser l'attribut `__packed__` sur les structures sérialisées\ !
:::
[//]: # ----------------------------------------------------------------
## Ressources
\small
- `mkfs.minix` source code\
\footnotesize [\textcolor{myblue}{https://github.com/util-linux/util-linux/blob/master/disk-utils/mkfs.minix.c}](https://github.com/util-linux/util-linux/blob/master/disk-utils/mkfs.minix.c)
\small
- `minix-fs` on-disk structures\
\footnotesize [\textcolor{myblue}{https://github.com/util-linux/util-linux/blob/master/include/minix.h}](https://github.com/util-linux/util-linux/blob/master/include/minix.h)
---
author: Florent Gluck - Florent.Gluck@hesge.ch
title: Systèmes de fichiers - Implémentation
date: \vspace{.5cm} \footnotesize \today
institute: \vspace{0.5cm} \tiny \textsuperscript{*}Remerciements à Mickaël Hoerdt
pandoc-latex-fontsize:
- classes: [tiny]
size: tiny
- classes: [verysmall]
size: scriptsize
- classes: [small]
size: footnotesize
- classes: [huge, important]
size: huge
---
## TODO
- Ajouter suppression d'un fichier
- méthode rapide : seul le bitmap des inode et des blocs est modifié
- méthode sécurisée : les blocs de données et le contenus des inodes sont également effacés
[//]: # ----------------------------------------------------------------
# Adressage des blocs de données
[//]: # ----------------------------------------------------------------
## Facilité d'adressage
On désire obtenir un accès ordonné aux blocs qui composent le contenu d'un fichier : début du fichier en bloc 0, suite en bloc 1, etc.
\vspace{.5cm}
\centering
![](images/blocks_simple_addr.png){ width=60% }
[//]: # ----------------------------------------------------------------
## Adressage : problème 1
Les blocs de données d'un fichier ne sont pas toujours contigus sur le disque
\centering
![](images/blocks_addr_problem.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Adressage souhaité
On désire une fonction `bmap` qui mappe un numéro de bloc du fichier (0, 1, 2, ...) vers un numéro de bloc du disque :
\vspace{.2cm}
```{.c .small}
// i : numero du bloc (logique) du fichier
// renvoie le numero du bloc physique sur disque
int bmap(inode, i);
```
\centering
![](images/bmap.png){ width=50% }
\footnotesize
- `bmap(inode, 0)` $\rightarrow$ 18
- `bmap(inode, 1)` $\rightarrow$ 20
- `bmap(inode, 2)` $\rightarrow$ 25
- `bmap(inode, 3)` $\rightarrow$ 11
[//]: # ----------------------------------------------------------------
## Adressage : problème 2
Certains blocs peuvent être des blocs indirects, c'est à dire contenir les adresses d'autres blocs
\vspace{.2cm}
\centering
![](images/blocks_addr_problem2.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Problème des indirections
\footnotesize
- Selon le même principe, on peut ajouter des blocs doublement, triplement, etc. indirects
- La distinction entre bloc simple, bloc indirect et bloc double indirect se fait sur sa position dans le tableau des adresses de l'inode
\centering
![](images/blocks_indirections.png){ width=90% }
[//]: # ----------------------------------------------------------------
## Repenser la structure de données
Ainsi la structure des inodes de MINIX :
```{.c .verysmall}
struct minix_inode {
...
u16 i_zone[7]; // direct pointers
u16 i_indir_zone; // indirect pointer
u16 i_dbl_indir_zone; // double indirect pointer
};
```
peut s'écrire :
```{.c .verysmall}
struct minix_inode {
...
u16 i_zone[9]; // i_zone[7] = indirect pointers
// i_zone[8] = double indirect pointers
};
```
[//]: # ----------------------------------------------------------------
## Fonction bmap : algorithme (1/2)
```{.c .tiny}
// i : numero du bloc (logique) du fichier
// renvoie le numero du bloc physique sur disque
int bmap(inode, i);
```
\small
Pseudo-code avec 2 niveaux d'indirections :
```{.c .tiny}
if (i < nb_blocs_adressables_directement) { // cas 1
return inode.i_zone[i]
}
i = i-nb_blocs_adressables_directement
if (i < nb_blocs_adressables_avec_une_seule_indir) { // cas 2
indir_bloc = read_block(inode.i_zone[indice_du_bloc_des_indir_simples])
return indir_bloc[i]
}
i = i-nb_blocs_adressables_avec_une_seule_indir
if (i < nb_blocs_adressables_avec_une_double_indir) { // cas 3
indir_bloc = read_block(inode.i_zone[indice_du_bloc_des_indir_doubles])
indir2_bloc = read_block(
indir_bloc[i/nb_blocs_adressables_avec_une_seule_indir])
return indir2_bloc[i % nb_blocs_adressables_avec_une_seule_indir]
}
```
[//]: # ----------------------------------------------------------------
## Fonction bmap : algorithme (2/2)
- Pourquoi la soustraction entre chaque cas ?
- pour réajuster l'indice dans le bloc lors d'une indirection : on passe d'un indice absolu à un indice relatif au bloc indirect
\vspace{.2cm}
- Exemple : si 7 blocs sont adressables directement, mais qu'on veut le 8ème, on veut le premier indice du bloc
indirect, pas l'indice 8
[//]: # ----------------------------------------------------------------
## Fonction bmap : exemple (1/4)
\footnotesize
- Nombre de blocs adressables directement : 2
- Nombre de blocs adressables avec une seule indirection : 4
- Nombre de blocs adressables avec une double indirection : 4*4
\centering
![](images/bmap_example.png){ width=90% }
[//]: # ----------------------------------------------------------------
## Fonction bmap : exemple (2/4)
```{.c .tiny}
if (i < 2) { // cas 1
return inode.i_zone[i]
}
i = i-2
if (i < 4) { // cas 2
indir_bloc = read_block(inode.i_zone[indice_du_bloc_des_indir_simples])
return indir_bloc[i]
}
i = i-4
if (i < 16) { // cas 3
indir_bloc = read_block(inode.i_zone[indice_du_bloc_des_indir_doubles])
indir2_bloc = read_block(indir_bloc[i/4])
return indir2_bloc[i % 4]
}
```
[//]: # ----------------------------------------------------------------
## Fonction bmap : exemple (3/4)
\scriptsize
**i = 4** :
- pas à inférieur à **2** $\rightarrow$ on rejette le cas 1
- 4-**2** = **\textcolor{mygreen}{2}**
- **\textcolor{mygreen}{2}** inférieur à **4** $\rightarrow$ on entre dans le cas 2
- lecture du bloc d'indirection simple
- indice **\textcolor{mygreen}{2}** dans bloc d'indirection simple pointe bien vers bloc 4
**i = 6** :
- pas inférieur à **2** $\rightarrow$ on rejette le cas 1
- 6-**2** = **\textcolor{mygreen}{4}**
- **\textcolor{mygreen}{4}** pas inférieur à **4** $\rightarrow$ on rejette le cas 2
- **\textcolor{mygreen}{4}**-**4** = **\textcolor{myred}{0}**
- **\textcolor{myred}{0}** inférieur à **16** $\rightarrow$ on entre dans le cas 3
- lecture du bloc d'indirection simple d'indice **\textcolor{myred}{0}**/**4** = 0
- \scriptsize indice **\textcolor{myred}{0}** % **4** (0) dans bloc d'indirection simple pointe bien vers bloc 6
[//]: # ----------------------------------------------------------------
## Fonction bmap : exemple (4/4)
\scriptsize
**i = 9** :
- pas inférieur à **2** $\rightarrow$ on rejette le cas 1
- 9-**2** = **\textcolor{mygreen}{7}**
- **\textcolor{mygreen}{7}** pas inférieur à **4** $\rightarrow$ on rejette le cas 2
- **\textcolor{mygreen}{7}**-4 = **\textcolor{myred}{3}**
- **\textcolor{myred}{3}** inférieur à **16** $\rightarrow$ on entre dans le cas 3
- lecture du bloc d'indirection simple d'indice **\textcolor{myred}{3}**/**4** = 0
- \scriptsize indice **\textcolor{myred}{3}** % **4** (3) dans bloc d'indirection simple pointe bien vers bloc 9
**i = 10** :
- pas inférieur à **2** $\rightarrow$ on rejette le cas 1
- 10-**2** = **\textcolor{myred}{8}**
- **\textcolor{myred}{8}** pas inférieur à **4** $\rightarrow$ on rejette le cas 2
- **\textcolor{myred}{8}**-**4** = **\textcolor{myred}{4}**
- **\textcolor{myred}{4}** inférieur à **16** $\rightarrow$ on entre dans le cas 3
- lecture du bloc d'indirection simple d'indice **\textcolor{myred}{4}**/**4** = 1
- \scriptsize indice **\textcolor{myred}{4}** % **4** (0) dans bloc d'indirection simple pointe bien vers bloc 10
[//]: # ----------------------------------------------------------------
# Résolution du chemin d'accès
[//]: # ----------------------------------------------------------------
## Problème du chemin d'accès
- Les inodes n'ont pas de noms, juste un numéro...
\vspace{.5cm}
- Comment retrouver le numéro d'un inode à partir de son chemin d'accès dans la chaîne des répertoires du système de fichiers ?
[//]: # ----------------------------------------------------------------
## Fonction namei
On désire une fonction `namei` qui retourne le numéro d'un inode à partir de son chemin d'accès dans le système de fichiers :
\vspace{.2cm}
```{.c .small}
// renvoie le numero d'inode du fichier dont le
// chemin d'acces est path
int namei(path);
```
- La recherche débute depuis :
- l'inode de la racine si le chemin d'accès est absolu
- le répertoire courant du processus si le chemin d'accès est relatif
- `namei` est typiquement utilisée par tous les appels systèmes qui prennent un chemin d'accès en argument
[//]: # ----------------------------------------------------------------
## Fonction namei : example
P.ex. appeler `namei` sur le chemin `"/usr/bin/bash"` parcourt le contenu des inodes suivants et renvoie 21 :
\vspace{.3cm}
\centering
![](images/namei_example.png){ width=100% }
[//]: # ----------------------------------------------------------------
## Fonction namei : algorithme
Pseudo-code pour un chemin absolu :
\vspace{.2cm}
```{.c .small}
int namei(path) {
inode = ROOT_INODE
pour chaque composant du path p {
inode = lookup_entry(inode, p)
}
return inode
}
```
[//]: # ----------------------------------------------------------------
## Fonction lookup_entry
\small
\vspace{.2cm}
```{.c .small}
// renvoie le numero d'inode correspondant a name
int lookup_entry(dir_inode, name);
```
- La fonction `lookup_entry` recherche un fichier dans un répertoire et renvoie son inode
- `lookup_entry` réalise une recherche linéaire de la chaîne de caractères `name` dans les entrées de répertoire (`dir_entry`) du répertoire dont l'inode est `dir_inode` :
**Attention** :
- Le contenu du répertoire peut-être réparti sur plusieurs blocs $\rightarrow$ utiliser `bmap`
- Aucune garantie que la taille du répertoire soit un multiple de la taille des blocs : utiliser le champs taille de l'inode pour limiter la recherche
[//]: # ----------------------------------------------------------------
## Fonction lookup_entry : algorithme
Pseudo-code :
\vspace{.2cm}
```{.c .small}
int lookup_entry(dir_inode, name) {
pour chaque bloc de dir_node et dans la limite
de dir_inode.size {
if (dir_entry.name == name) {
return dir_entry.inode
}
}
return not_found
}
```
[//]: # ----------------------------------------------------------------
## Fonction del_entry
\small
```{.c}
del_entry(dir_inode, name)
```
- La fonction `del_entry` supprime un fichier d'un répertoire
- `del_entry` réalise une recherche linéaire de la chaîne de caractères `name` dans les entrées de répertoire (`dir_entry`) du répertoire dont l'inode est `dir_inode` :
- Attention : tout comme pour `lookup_entry`, le contenu du répertoire peut-être réparti sur plusieurs blocs
- Une fois l'entrée de répertoire (`dir_entry`) trouvée, son champs inode est mis à zéro et le bloc modifié est écrit sur disque
9.filesystems/images/FAT_alloc.png

122 KiB

9.filesystems/images/FAT_disk_layout.png

64.1 KiB

9.filesystems/images/addressing.png

16.3 KiB

9.filesystems/images/addressing_example.png

25.8 KiB

9.filesystems/images/block_and_cluster.png

42.8 KiB

9.filesystems/images/blocks_addr_problem.png

92.4 KiB

9.filesystems/images/blocks_addr_problem2.png

89.8 KiB

9.filesystems/images/blocks_indirections.png

170 KiB

9.filesystems/images/blocks_simple_addr.png

12 KiB

9.filesystems/images/bmap.png

49.3 KiB

9.filesystems/images/bmap_example.png

173 KiB

9.filesystems/images/contiguous_alloc.png

1.05 MiB

9.filesystems/images/dir_content.png

116 KiB

9.filesystems/images/external_fragmentation.png

45.4 KiB

9.filesystems/images/hdd.png

352 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment