| UNIX - principes de fonctionnement Index interface de programmation, appels système, fichiers, contrôle de processus, tubes (pipes), signaux, interface utilisateur, shells, entrées-sorties standards, scripts C-shell Dans les chapitres précédents nous avons jeté les bases pour l’introduction d’un système d’exploitation. Un système d’exploitation est un programme nécessaire pour pouvoir gérer les ressources matérielles et logicielles (données, programmes) d’un système informatique. Un système d’exploitation tout seul n’est pas un système informatique. Nous avons choisi est le système UNIX et ce chapitre présente les fonctions principales de ce système. Ces fonctions seront approfondies dans les chapitres suivants en s’appuyant sur des exemples de programmation. Introduction Le système UNIX est un système fonctionnant en temps partagé, c’est qui signifie l’exécution de plusieurs programmes gerés en temps réel et découpés en tranches dites quanta. Le système de fichiers est conçu comme un arbre à plusieurs niveaux. Les utilisateurs peuvent créer leur propres sous-répertoires. Chaque fichier utilisateur est une simple séquence d’octets (bytes). Les unités de disques et autres périphériques (e.g. périphériques standard: clavier et écran) sont gérés de la façon la plus proche possible des fichiers . Différentes caractéristiques fonctionnelles des périphériques sont “cachées” par les programmes de pilotage (drivers). Le système UNIX gère plusieurs programmes en exécution, ces entités actives s’appellent processus. Un processus peut facilement créer un autre processus. La gestion des processus est basée sur un simple mécanisme de priorité. UNIX est composé de deux parties importantes et indépendantes: le noyau et les programmes système. Le noyau s’appuie sur les fonctions BIOS et permet de gérer le système de fichiers, le système mémoire, le(s) processeur(s) et les périphériques. Les programmes système exploitent les fonctions du noyau par le biais des appels système.
Un fichier UNIX est une séquence d’octets. Les programmes utilisateurs peuvent interpréter les contenus des fichiers selon leurs besoins; le noyau n’impose aucune structure interne aux fichiers. Par exemple, le caractère ASCII 0 (en binaire: 00000000), qui est utilisé pour marquer la fin d’une chaîne de caractères au niveau des applications, n’a aucune signification spécifique pour le noyau UNIX. Le système de fichiers est organisé sous la forme d’une structure arborescente de répertoires. Les fichiers répertoires sont eux mêmes des fichiers qui contiennent les liens vers d’autres fichiers. Un chemin (path) vers un fichier est une chaîne de caractères qui mène via les noms des sous-répertoires au fichier lui-même. Par exemple, /usr/include/signal.h est un chemin complet vers le fichier signal.h. Ce chemin est appelé chemin absolu parce qu’il débute à la racine du système de fichiers. Un fichier peut être connu sous plusieurs noms; ces noms sont des liens. Un fichier existant doit avoir au moins un lien. Il y a deux sortes de liens: les liens soft et les liens hard. Les liens soft (symboliques) peuvent pointer les répertoires et peuvent transcender la frontière d’un système de fichiers (un autre système peut être installé sur un autre disque). Le nom “.” dans un répertoire est lien hard qui pointe vers le répertoire lui-même. Le nom “..” est un lien hard qui pointe vers le répertoire parent. Les périphériques ont des noms dans le système de fichiers; ils s’appellent fichiers spéciaux (special files). Le répertoire initial, le root, contient un certain nombre de sous-répertoires de base: bin, lib, user, etc, tmp, dev, .. Ces répertoires sont disponibles dans tous les systèmes UNIX/LINUX. Les fichiers d’administration sont gardés dans le répertoire /etc; nous y trouvons le fichier passwd qui contient les noms et les paramètres des utilisateurs enregistrés dans le système. L’accès aux fichiers répertoires et au fichiers ordinaires peut être réalisé par le biais des appels système tels que:
Ces appels de base ou primitives système nous serviront pour le développement des applications (commandes UNIX). Nous allons voir que ces appels fonctionnent avec des descripteurs. Un descripteur est un index dans un tableau qui répertorie les fichiers ouverts dans un programme en exécution. Un processus est un programme en exécution. Les processus sont identifiés par leurs identificateurs (process identifier) qui sont des entiers. Un nouveau processus est créé par l’appel système fork(). Le nouveau processus (processus fils) est une copie de l’espace d’adressage du processus père: le même programme avec les mêmes variables avec les mêmes valeurs.
Les deux processus continuent exécution concurrente du même programme à partir de l’instruction qui suit l’appel fork().
La gestion plus complète des processus par un programme système implique l’utilisation des appels système suivants:
Dans l’ensemble, les primitives permettent d’organiser le lancement d’exécution d’un programme et l’attente de la fin de son exécution.
Nous allons utiliser ces appels pour le développement d’une application de type interpréteur de commandes. La communication entre les processus est très importante pour toutes les applications complexes qui engendrent plusieurs processus. La solution la plus simple consisterait à exploiter un fichier commun à plusieurs processus. Malheureusement ce moyen est très lent. Le mécanisme de communication le plus approprié pour la communication rapide entre les processus est un tube (pipe). Le pipe est un tampon dans la mémoire principale, géré par le système d’exploitation et permettant une communication directe et organisée entre deux ou plus processus. Les primitives système utilisées pour la gestion des tubes sont:
L’accès d’un processus à l’unité centrale (processeur) est géré en mode partage de temps (time-sharing) par le noyau du système (programme ordonnanceur). Selon sa priorité et son état, le processus peut (ou non) obtenir la tranche de temps suivante pour son exécution.
Les signaux UNIX sont des mécanismes de signalisation permettant de gérer les événements de type interruptions logiciel ou matériel. Chaque type de signaux correspond à différentes conditions. Un signal peut être généré par le clavier (e.g. ^C), par le gestionnaire de fenêtres, par une erreur de fonctionnement d’un processus (e.g. dépassement de l’espace mémoire alloué au processus), etc. Les signaux peuvent être également générés par l’appel système kill. Les signaux ont toujours une cible qui est un processus. L’arrivée d’un signal vers un processus arrête son fonctionnement. Néanmoins les processus peuvent ignorer l’occurrence d’un signal en bloquant son utilisation dans le tableau des vecteurs d’interruption associés à ce processus. Les principaux appels système utilisés pour la gestion des signaux sont:
Les utilisateurs du système UNIX et certains programmeurs ont besoin d’un ensemble de programmes système pour réaliser leurs tâches applicatives. Ces programmes font d’eux mêmes les appels systèmes nécessaires pour leur fonctionnement. Les programmes système ou les commandes peuvent être regroupés en plusieurs catégories. La plupart des commandes gère les répertoires et les fichiers. Quelques unes de ces commandes sont citées ci-dessous:
Parmi les programmes applicatifs se trouvent les compilateurs, les éditeurs du texte, les logiciel de montage audio et vidéo, les logiciels CAO, le navigateurs WEB, etc.. Tous ces logiciels résident initialement sur le disque dur sous la forme de fichiers exécutables. L’exécution des programmes applicatifs et des commandes est lancée par un interpréteur de la ligne de commandes. L’interpréteur de commandes est un processus normal du système UNIX. Il est également appelé shell (coquille) parce qu’il englobe le noyau du système. Dans le mode UNIX il y a plusieurs interpréteurs de commandes. Le plus ancien est le Bourne shell ou shell tout court. Parmi les interpréteurs, le plus répandus est le C-shell développé par Bill Joy le fondateur de Sun Microsystems. Sous LINUX on utilise souvent le shell appelé bash. bash est assez proche du C-shell. Les programmes shells possèdent leurs langages de commandes permettant d’enchaîner l’exécution de plusieurs activités à réaliser pendant une session de travail. Le shell indique qu’il est prêt à accepter une nouvelle commande par l’affichage d’une invitation ( prompt) (% pour C-shell). Exemple Les commandes peuvent prendre des arguments et des options. Ces données sont des mots séparés par des espaces. Les programmes shell intègrent un certain nombre de commandes qui sont liées à l’état d’une session. Par exemple, les commandes cd ou pwd sont des commandes internes. D’autres commandes sont de simples fichiers exécutables. Une liste de plusieurs répertoires est maintenue par le shell. Pour chaque commande, tous les répertoires de cette liste sont scrutés pour y trouver le nom (le fichier) de la commande. Si le fichier est trouvé, il est chargé et son exécution est lancée. L’exécution d’une commande est effectuée par l’appel système fork() suivi de exec() avec le fichier à charger et exécuter. Le programme shell normalement attend la fin d’exécution de la commande sur l’appel wait. Si l’utilisateur veut lancer une commande en “arrière plan” (background) il doit taper le caractère & après le nom de la commande. Dans ce cas le programme du shell, qui est le processus père n’attend pas la fin d’exécution du programme de processus fils et affiche à nouveau un prompt. Exemple: C-shell introduit la notion de job (tâche). Le contrôle des jobs permet d’envoyer un processus en arrière-plan ou de le rappeler en avant-plan (foreground). Dans un système à interface graphique, chaque fenêtre est traitée comme un terminal. Avec plusieurs fenêtres, plusieurs processus peuvent être en avant-plan à un instant donné. Les processus peuvent ouvrir des fichiers à demande, mais les trois premiers fichiers associés aux entrées/sorties standards, sont ouverts par défaut dans chaque processus. Ces fichiers spéciaux désignent le clavier (descripteur 0: entrée standard), l’écran (descripteur 1: sortie standard), et l’écran d’erreurs (descripteur 2). Le premier fichier ouvert explicitement dans un processus est désigné par le descripteur numéro 3. La plupart des programmes acceptent un fichier à la place d’une entrée ou sortie standard. Cette solution permet d’effectuer les redirections en sortie et en entrée. Exemples: Les redirections peuvent être également effectuées sur des pipes. Cette solution permet d’enchaîner le fonctionnement de plusieurs commandes communicant par les tubes. Exemple: Les scripts sont des programmes écrits en langage shell. Un langage shell exploite les variables système et ses propres variables locales et interprète les instructions de contrôle de type if, else, loop. L’exécution d’une commande ressemble à l’évocation d’une fonction. La programmation shell permet de combiner l’exécution de plusieurs programmes et de créer des applications complexes. Exemple: #la diese est necessaire pour indiquer l’utilisation du C-shell set a=0 # creation d’une variable Résumé Dans ce chapitre nous avons parcouru les grandes fonctions d’un système d’exploitation. Un système d’exploitation est composé d’un noyau et d’une interface utilisateur développée à partir des fonctions du noyau. Le programme noyau gère le système de fichiers, le temps de l’unité centrale partagé par plusieurs processus, la mémoire principale et la mémoire virtuelle et l’ensemble des périphériques accessibles dans la configuration matérielle du système. Dans le chapitre suivant, nous nous intéressons à la conception et au fonctionnement du système de fichiers et aux appels système permettant d’effectuer les opérations sur les fichiers ordinaires et les répertoires UNIX. |
||