Ainsi, lorsque nous compilons un code source simple, disons avec une simple fonction printf(), et que la compilation produit le code machine exécutable, chaque instruction de ce code machine sera-t-elle exécutée directement depuis la mémoire (une fois le code chargé dans la mémoire par le système d'exploitation) ou chaque commande du code machine devra-t-elle encore passer par le système d'exploitation (noyau) pour être exécutée ?
Essentiellement, seuls les appels système vont au noyau. Tout ce qui a trait aux E/S ou à l'allocation/désallocation de mémoire donne généralement lieu à un appel système. Certaines instructions ne peuvent être exécutées qu'en mode noyau et provoquent le déclenchement d'une exception par le CPU. Les exceptions provoquent un passage en mode noyau et un saut vers le code du noyau.
Le noyau ne traite pas chaque instruction d'un programme. Il se contente d'effectuer les appels système et de basculer entre les programmes en cours d'exécution pour partager l'unité centrale.
L'allocation de mémoire en mode utilisateur (sans le noyau) n'est pas possible, si vous accédez à une mémoire à laquelle vous n'avez pas la permission d'accéder, la MMU, préalablement programmée par le noyau, le remarque et provoque une exception de "défaut de segmentation" au niveau du CPU, qui déclenche le noyau, et le noyau tue le programme.
Il n'est pas possible d'effectuer des E/S en mode utilisateur (sans le noyau). Si vous accédez à des ports d'E/S ou à des registres de périphériques, ou à des adresses connectées à des périphériques (l'un ou les deux étant nécessaires pour effectuer des E/S), ceux-ci déclenchent une exception de la même manière.
Un exécutable a-t-il besoin d'un noyau d'OS pour fonctionner ?
Dépend du type d'exécutable.
Les noyaux, en plus de gérer l'accès partagé à la RAM et au matériel, remplissent également une fonction de chargeur.
De nombreux "formats exécutables", comme ELF ou PE, contiennent des métadonnées dans le fichier exécutable en plus du code, et c'est au chargeur de les traiter. Lisez le les détails sanglants du format PE de Microsoft をご覧ください。
Ces exécutables font également référence à des bibliothèques (Windows .dll
ou objet partagé Linux .so
) - leur code doit être inclus.
Si votre compilateur produit un fichier qui est censé être traité par un chargeur du système d'exploitation, et que ce chargeur n'est pas là, il ne fonctionnera pas.
- Pouvez-vous inclure du code qui fait le travail du chargeur ?
Bien sûr. Vous devez convaincre le système d'exploitation d'exécuter votre code brut sans traiter de métadonnées. Si votre code appelle les API du noyau, ça ne fonctionnera toujours pas.
- Et s'il n'appelle pas les API du noyau ?
Si vous chargez cet exécutable d'une manière ou d'une autre à partir d'un système d'exploitation (c'est-à-dire s'il permet de charger et d'exécuter du code brut), il sera toujours en mode utilisateur. Si votre code accède à des choses qui sont interdites en mode utilisateur, par opposition au mode noyau, comme de la mémoire non allouée ou des adresses/registres de périphériques d'E/S, il se plantera avec des violations de privilèges ou de segments (là encore, les exceptions vont en mode noyau et y sont traitées) et ne fonctionnera toujours pas.
- Et si vous l'exécutez en mode noyau.
Alors, ça marchera.