\include{parameters}
\usetheme{JuanLesPins}
\usepackage[french]{babel}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{bortzmeyer-utils}

\title{Systèmes d'exploitation}
\author{Stéphane Bortzmeyer \texttt{<stephane@bortzmeyer.org>}}
\date{23 janvier 2008}

%\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex} 
% \setlength{\parskip}{15pt} 
\setlength{\parskip}{15pt plus 10pt minus 10pt} 

\begin{document}

\maketitle

\begin{frame}
  \titlepage
\end{frame}

\begin{frame}[fragile]
\frametitle{Un petit programme tout seul}  
\begin{info}
import urllib2
import time

results_filename = "test.out"
url = "http://www.pasteur.fr/"
n = 100 # Read only the first n characters
results_file = open(results_filename, 'w')
try:
    web_data = urllib2.urlopen(url).read(n)
except Exception:
    web_data = None
results_file.write("Result for \"%s\" at %s is \"%s\"\n" % \
                 (url, time.strftime("%H:%M:%S",
		            time.localtime(time.time())),
                    web_data))
results_file.close()
\end{info}
\end{frame}

\begin{frame}
\frametitle{Que fait ce programme ?}
\begin{enumerate}
\item Il ouvre en écriture un fichier nommé "test.out"
(\computer{open()} est une fonction pré-définie en Python),
\item Il récupère une page Web, "http://www.pasteur.fr/" (le
module urllib2 fait partie de la bibliothèque standard),
\item Il stocke les 100 premiers caractères de cette page dans le
fichier (\computer{write()} est une méthode des objets Fichier).
\end{enumerate}
\end{frame}

\begin{frame}
\frametitle{Qui évalue ce programme ?} 

L'interpréteur Python fait une partie du
travail (affectation aux variables, gestion de l'exception, \ldots).

Certaines tâches (open(), le réseau, l'horloge) sont déléguées au \emph{Système d'exploitation}.
\end{frame}

\begin{frame}
  \frametitle{Pourquoi un système d'exploitation ?}
  \begin{itemize}
    \item Pour aider (pour éviter aux applications de tout
    réimplémenter, certaines tâches sont faites par le SE et mises à
    la disposition de toutes),
    \item<2-> Pour gêner et contrarier (si c'était uniquement pour aider,
    le SE pourrait se réduire à une \emph{bibliothèque}
    d'utilitaires ; mais il faut aussi protéger les applications les
    unes contre les autres, par exemple en vérifiant les permissions
    au moment du open()).
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Les tâches du système d'exploitation}
  \begin{itemize}
    \item Fournir des abstractions de niveau élevé, par exemple
    l'application doit voir des \emph{fichiers} plutôt que des blocs
    sur un disque dur. Elle doit voir la mémoire comme un grand
    tableau, et pas comme un mélange de barettes et d'espace sur le
    disque dur,
   \item Garder le temps et l'indiquer aux applications qui en ont
   besoin.
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{Les tâches du système d'exploitation, suite}
\begin{itemize}
   \item Gérer le matériel, les accès concurrents (sur un
   quadri-processeur, un maximum de quatre tâches peuvent être actives
   en même temps), les pannes et la reprise,
   \item Protéger les tâches les unes contre les autres (mémoires
   distinctes, par exemple),
   \item Protéger les utilisateurs les uns contre les autres (sur un
   SE multi-utilisateurs), par exemple en faisant respecter les
   permissions des fichiers,
   \item<2-> etc (il n'y a pas de limites absolues à cette liste, certains
   SE en font plus que d'autres).
  \end{itemize}
\end{frame}

\begin{frame}
\frametitle{En quoi consiste un système d'exploitation ?}
Deux parties (attention, c'est une vision simplifiée) :
\begin{itemize}
  \item Un ensemble de bibliothèques et de programmes utilitaires,
  \item Le \emph{noyau} du SE, la partie qui parle au matériel.
\end{itemize}
\begin{block}<2->
{Et entre les deux ?}{On trouve les \emph{appels système}, seul moyen
de communication.}
\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Appels système de notre petit programme}
\begin{info}
% strace -f ./test.py |& more
...
open("test.out", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
...
\end{info}
(open = ouverture d'un fichier, distinct du open Python)

Ce petit programme fait en tout 2980 appels système\ldots

Beaucoup sont des chargements de bibliothèques Python.
\end{frame}

\begin{frame}
\frametitle{Petite introduction aux modèles en couches}
\begin{block}
{Pour aider à découper le problème, on l'organise souvent en \emph{couches}
successives.}
{Les couches les plus hautes sont celles qui touchent à
l'utilisateur. Les couches les plus basses sont celles qui touchent au
matériel.}
\end{block}
Le SE et les autres couches nous permettent de monter plus haut (de
faire d'avantage de travail en moins de temps).
\end{frame}

\begin{frame}
\frametitle{Exemple de couche supplémentaire}

Python, en tant que langage de haut
niveau, nous fournit plein de services au dessus du SE, services qu'on
n'aura pas à développer.

En programmant en C, le petit programme utilisé comme exemple serait
bien plus long.
\end{frame}

\begin{frame}
\frametitle{La partie haute du SE}
C'est un ensemble d'utilitaires et de bibliothèques considérées comme
indispensables au fonctionnement des applications.
\end{frame}

\begin{frame}
\frametitle{Il y a une part de flou dans cette définition}

Exemples :
\begin{itemize}	
\item Sur MS-Windows, l'interface graphique est considérée comme
faisant partie du SE. Pas sur Unix.
\item Sur FreeBSD, il existe une claire séparation entre le
\emph{système de base} (« la partie haute du SE ») et
applications. Pas sur Gentoo ou Debian.
\item Certains spécialistes réservent le terme de SE au noyau (la
partie basse du SE).
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{Ce qu'on trouve dans la partie haute}
\begin{itemize}
\item Sur Unix, des programmes comme ls ou rm,
\item Sur Unix, la bibliothèque C standard (libc) qui fait des choses
comme la résolution de noms de machine en adresses IP,
\item Sur Unix, des démons de base comme cron.
\end{itemize}

Points communs : sur un PC/Unix, un utilisateur ordinaire, sans privilège, \emph{peut}
remplacer complètement cette partie.

\end{frame}

\begin{frame}
\frametitle{La partie haute et l'utilisateur}
C'est cette partie haute qui est vue par l'utilisateur, pas le noyau.

Par exemple, pour l'utilisateur ordinaire, il y a une très grosse
différence entre MacOS X et FreeBSD, alors que leurs noyaux sont
presque les mêmes.
\end{frame}

\begin{frame}[fragile]
\frametitle{Les bibliothèques}
Sur Unix, on les trouve typiquement dans \path{/lib} et \path{/usr/lib}.

La plus connue est la libc, dont dépendent presque tous les
programmes.

Une bibliothèque peut être \emph{statique} (incluse au programme lors
de l'édition de liens) ou \emph{dynamique} (chargée au moment de
l'exécution).
\end{frame}

\begin{frame}[fragile]
\frametitle{Trouver les bibliothèques}
Sur Unix, on peut afficher la liste des bibliotèques dynamiques
chargées par un programme avec ldd :
\begin{info} 
% ldd /usr/bin/echoping
        libpopt.so.0 => /lib/libpopt.so.0 (0xb7ec9000)
        libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7ea3000)
        libidn.so.11 => /usr/lib/libidn.so.11 (0xb7e72000)
        libgnutls.so.13 => /usr/lib/libgnutls.so.13 (0xb7e02000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7c25000)
...
\end{info}
Ici, ce programme utilise la libc, mais aussi la bibliothèque de
cryptographie GNU TLS, la bibliothèque mathématique libm, etc.
\end{frame}

\begin{frame}
\frametitle{Bibliothèques sur Windows}
On les nomme DLL pour \foreign{Dynamic Linking Library}. 

Comme elles sont chargées dynamiquement, le changement de la DLL
modifie le comportement d'un programme, même si celui-ci n'a pas été
touché.

Internet Explorer, par exemple, n'est qu'un petit programme, presque
tout est fait par des DLL (c'est pour cela qu'il est difficile d'avoir
deux versions d'IE sur la même machine).
\end{frame}

\begin{frame}
\frametitle{Pourquoi les problèmes récurrents avec les DLL}
Les DLL sont une bonne chose\ldots sauf si on a modifié une DLL importante
sans faire attention (ce que font parfois les scripts d'installation).

Se méfier à chaque nouveau jeu à installer :-)
\end{frame}

\begin{frame}
\frametitle{Le noyau}
Le noyau est la partie basse du SE, celle qui est au contact direct du
matériel.

Sur un système comme Unix ou MS-Windows, il s'exécute dans un mode
particulier du processeur (\foreign{Ring-0} sur les Intel), pour
assurer la sécurité.
\end{frame}

\begin{frame}
\frametitle{Activités du noyau}

\begin{itemize}
\item Arbitrer les accès au matériel (une seule tâche - on dit aussi
processus - à la fois dans
le processeur),
\item Présenter une vision abstraite du matériel (l'appel système
\computer{write()} va se traduire par des instructions très
différentes selon que le disque parle IDE ou SCSI),
\item Présenter une version abstraite des données, c'est le
\emph{système de fichiers}, qui permet d'utiliser les mêmes
applications, qu'on écrive sur le disque SCSI d'un serveur ou sur la
carte SD de son appareil photo numérique,
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{Activités du noyau, suite}
\begin{itemize}
\item Présenter une version abstraite de la mémoire, la \emph{mémoire
virtuelle},
\item Faire respecter les permissions, par exemple l'appel système
\computer{kill()} vérifie que le processus qu'on vise appartient au
même utilisateur (pas le droit de tuer les processus des autres),
\item Faire respecter la séparation des tâches et des utilisateurs
(pas le droit d'écrire dans la mémoire des autres, que ce soit par
méchanceté ou par accident). 
\end{itemize}
\end{frame}

\begin{frame}
\frametitle{Ces tâches sont typiquement couplées}
La gestion de la mémoire
virtuelle protège également contre les accès des autres processus.

\end{frame}

\begin{frame}
\frametitle{Mémoire virtuelle}
Une des tâches importantes d'un SE moderne est de gérer la
\emph{mémoire virtuelle}. Il s'agit de présenter aux programmes une
mémoire linéaire (les \emph{adresses} sont des nombres entiers) et de grande taille. 

Un effet utile de la mémoire virtuelle est d'isoler complètement la
mémoire de deux processus différents.
\end{frame}

\begin{frame}[fragile]
\frametitle{Et si la mémoire physique est limitée ?}

La mise en \oe{}uvre de la mémoire
virtuelle fait appel à une zone du disque dur, le \foreign{swap}.

Le SE déplace les données de la mémoire physique vers le 
\foreign{swap} si nécessaire (mais c'est lent).

\begin{info}
% free
*             total       used       free     shared    buffers     cached
Mem:       2066364    2014016      52348          0       7284    1646108
-/+ buffers/cache:     360624    1705740
Swap:      4586548       1900    4584648
\end{info}
\end{frame}

\begin{frame}[fragile]
\frametitle{Système de fichiers}
Le système de fichiers présente une vue ordonnée des données :
celles-ci sont dans des abstractions, nommées \emph{fichiers}, ayant
un nom, et organisés en \emph{répertoires}.

Le système de fichiers garde également trace des \emph{méta-données}
(permissions, date de modification, type des données - sur BeOS).
\end{frame}

\begin{frame}[fragile]
\frametitle{Le système de fichiers fait respecter les permissions}

\begin{info}
% rm -f /etc/hosts
rm: cannot remove `/etc/hosts': Permission denied
\end{info}

Ce n'est pas rm, une application du SE, mais qui tourne en mode
utilisateur, qui fait respecter les permissions.

\end{frame}

\begin{frame}[fragile]
\frametitle{Notion d'utilisateurs}
La plupart des SE sont \emph{multi-utilisateurs}. Ils ont une base
d'utilisateurs (sur Unix, \path{/etc/passwd}).

Tout objet (processus, fichier) a un propriétaire.

Le SE empêche de toucher aux objets des autres.

\begin{info}
% id
uid=1000(stephane) ...

% ps auxww
root      4867  0.0  0.0  12560  2008 ?        Ssl  17:36   0:00 /usr/sbin/NetworkManager --pid-file /var/run/NetworkManager/NetworkManager.pid

% kill 4867
kill: kill 4867 failed: operation not permitted
\end{info}

\end{frame}

\begin{frame}
\frametitle{To be or not to be root}
Ou pourquoi il n'y a guère de virus sur Unix

Sur Unix, un utilisateur est particulier, \computer{root}. Il a tous
les droits.

L'utilisateur ordinaire ne peut toucher qu'à ses objets ou à ce que
root lui autorise.

Même si un virus est contenu dans une application, il n'aura que les
permissions de l'utilisateur, il ne pourra pas affecter le système.

\end{frame}

\begin{frame}[fragile]
\frametitle{Notion de tâche et de processus}
Un \emph{processus} est un programme en train de s'exécuter. 

On peut l'afficher avec la commande \computer{ps}.

\begin{info}
% ps 
7010 pts/0    00:00:02 emacs
\end{info}
Ici, le processus de numéro 7010 exécute le programme emacs (un
éditeur).

Le processus a sa propre mémoire virtuelle, il ne peut tout simplement
pas voir celle des autres.
\end{frame}

\begin{frame}
\frametitle{Tâche}
Le terme de « tâche » est souvent utilisé pour une version légère du
processus (qui partage sa mémoire avec d'autres tâches).
\end{frame}

\begin{frame}
\frametitle{Gestion des E/S}
Les E/S (\emph{entrées-sorties}) sont une des tâches les plus
complexes car le matériel est très varié... et parfois défaillant.


\end{frame}

\begin{frame}
\frametitle{Pilote de périphérique}
Le \emph{pilote} est une partie du noyau qui gère un type de
périphérique (disque Flash, carte Wifi, carte son, \ldots).

Sur un PC, le code de tous les pilotes fait la majorité du noyau\ldots
et des bogues.

C'est du code de bas niveau, difficile à écrire, d'autant plus que les
constructeurs réservent en général leur documentation à Microsoft.
\end{frame}

\begin{frame}
\frametitle{Le matériel}
Continuant notre descente, nous arrivons au matériel, qui n'est pas
couvert dans cet exposé.
\end{frame}

\begin{frame}
\frametitle{L'aventure d'un write()}
\begin{enumerate}
\item Le programmeur a écrit \computer{myfile.write(mydata)}. Python
l'exécute.
\item L'interpréteur Python, une application ordinaire ne tournant pas
en mode noyau, cherche \computer{myfile} et la traduit dans un
identificateur compris par le SE. Il appelle l'appel système
\computer{write()} (qui est distinct du write Python) avec cet
identificateur (\emph{où} écrire) et les données (\emph{quoi} écrire).
\item Le noyau a vérifié les permissions au moment de l'ouverture du
fichier (il ne laisse pas les applications le faire).
\end{enumerate}
\end{frame}

\begin{frame}
\frametitle{L'aventure du write(), suite}
\begin{enumerate}
\item Le noyau se souvient d'où on en était dans le fichier (depuis
son ouverture),
\item Le noyau exécute le code du système de fichiers considéré (il y
en a plusieurs), ce code traduit le nom de fichier en des emplacements
sur le disque dur,
\end{enumerate}
\end{frame}

\begin{frame}
\frametitle{L'aventure du write(), suite encore}
\begin{enumerate}
\item Le noyau envoie alors des instructions au \emph{pilote} du
disque concerné. Il existe plusieurs pilotes, selon le modèle de
disque. Avec SCSI, les instructions sont simples (« écris ce bloc de
données en 18234 »), avec IDE, bien plus complexe (« déplace ta tête
sur le troisième cylindre, puis écris ce bloc de données
sur le deuxième secteur du huitième plateau »).
\item Le matériel se met en mouvement et applique les ordres.
\end{enumerate}
\end{frame}

\begin{frame}
\frametitle{L'aventure du write(), fin}
\begin{enumerate}
\item Le noyau attend une réponse positive du disque et libère alors
l'application (ou bien signale une erreur). 
\end{enumerate}
Et, pendant ce temps, le noyau a géré les autres processus, la mémoire
virtuelle du nôtre, etc\ldots
\end{frame}


\end{document}