= 11. Introduction au Noyau Linux =
Bien que les fonctionnalités décrites plus haut sont > codées dans le noyau, quelques outils sont nécessaires > en espace utilisateur (userspace) pour les activer et les controler. Ces outils en userspace communiquent généralement > avec le noyau via des appels système (syscalls). Le chapitre qui suit décrit les liens entre espace kernel > et espace utilisateur, comment les appels système, > méthode simple pour communiquer entre les processus et le > noyau, fonctionnent. == 11.0. Espace Noyau et Espace Utilisateur == Sous Linux et les systèmes d'exploitation similaires, > l'espace noyau et l'espace utilisateur sont séparés, et > l'espace d'adressage est divisé en deux parties. Dans L'espace > noyau réside le code noyau, alors que les programmes > utilisateur vivent dans l'espace utilisateur. Bien entendu, > un programme ne peut écrire dans la mémoire noyau, ni dans > la mémoire d'un autre processus. Malheureusement, c'est aussi le cas pour le code du noyau. > Le code kernel n'a pas le droit d'écrire dans l'espace utilisateur. > Qu'est-ce que cela signifie ? Lorsqu'un driver de périphérique > a besoin d'écrire ses octets destinés à un programme dans l'espace > utilisateur, il ne peut pas le faire directement, mais doit passer > par des fonctions noyau spécifiques à la place. De même, lorsque > des paramètres sont passés au noyau par référence à une fonction kernel, > la fonction kernel ne peut pas lire les paramètres directement. Elle doit > utiliser d'autres fonctions noyau pour lire chaque octet des paramètres. Bien entendu, il existe des fonctions écrites tout spécialement pour > les transfer depuis et vers l'espace utilisateur. <code> copy_to_user(void *to, const void *from, long n); copy_from_user(void *to, const void *from, long n); </code> get_user() and put_user() > Prendre ou placer l'octet, le mot, ou l'entier long depuis l'espace utilisateur > ou vers celui-ci. C'est une macro, et elle se fie au type de ses arguments pour > évaluer le nombre d'octets à transférer. == 11.1. Appels système Linux (Syscalls) == La plupart des appels libc s'appuient sur les appels système, > la plus petite forme de fonction qu'un programme peut appeler. Ces appels système sont implémentés dans le noyau lui-même, > ou dans des modules, parties de code noyau chargeables > dynamiquement. Ils sont implémentés via un multiplexeur appelé avec un masque > d'interruption précis. Sous Linux, ce masque d'interruption est > int 0x80. Lorsque l'instruction 'int 0x80' est exécutée, le contrôle > est donné au noyau (ou, plus précisément, à la fonction _system_call() ), > et le démultipléxage proprement dit prend place. Comment fonctionne la fonction _system_call() ? Tout d'abord, tous les registres sont sauvegardés, et le contenu > du registre %eax est comparé à la table des appels systèmes, > qui recense tous les appels systèmes et leur adresse respective. On peut acceder à cette table via la variable > extern void *sys_call_table[] > Il existe un nombre et une adresse mémoire données > dans cette table pour chacun des appels système. Ceux-ci sont référencés dans le fichier > /usr/include/sys/syscall.h. Ils sont de la forme SYS_nomappelsysteme. > si l'appel système n'est pas implémenté, la cellule > correspondante dans la table sys_call_table est à 0, > et une erreur est retournée. Sinon, l'appel système sort, et l'entrée correspondante > dans la table donne l'adresse du code ou se trouve l'appel > système. |