Il est important de noter que la programmation du noyau diffère considérablement de la programmation de l'espace utilisateur. Le noyau est une entité autonome, qui ne peut pas utiliser les bibliothèques de l'espace utilisateur, même libc sur Linux ou kernel32.dll sur Windows. De ce fait, les fonctions habituelles utilisées en espace utilisateur (printf, malloc, free, open, read, write, memcpy, strcpy, etc.) ne peuvent plus être utilisées.
En conclusion, la programmation du noyau est basée sur une API complètement nouvelle et indépendante qui n'est pas liée à l'API dans l'espace utilisateur, que l'on se réfère à POSIX , Win32 ou ANSI C. Une différence importante dans la programmation du noyau est la façon d'y accéder. et allocation de mémoire. Du fait que la programmation du noyau se fait à un niveau très proche de la machine physique, il existe des règles importantes concernant la gestion de la mémoire.
Tout d'abord, il fonctionne avec plusieurs types de mémoire :
– mémoire physique
– mémoire virtuelle dans l'espace d'adressage du noyau
– mémoire virtuelle de l'espace d'adressage d'un processus
– mémoire résidente – nous savons avec certitude que les pages consultées sont présentes dans la mémoire physique
La mémoire virtuelle dans l'espace d'adressage d'un processus ne peut pas être considérée comme résidente en raison des mécanismes de mémoire virtuelle mis en œuvre par le système d'exploitation : les pages peuvent être dans le swap, ou elles peuvent ne pas être présentes dans la mémoire physique à la suite du mécanisme de pagination de requête.
La mémoire dans l'espace d'adressage du noyau peut être résidente ou non. Les segments de données et de code d'un module et la pile du noyau d'un processus sont résidents.
Lamémoire dynamique peut être résidente ou non, selon la manière dont elle est allouée. Lorsque vous travaillez avec de la mémoire résidente, les choses sont simples : la mémoire est accessible à tout moment. Cependant, si vous travaillez avec de la mémoire non résidente, elle n'est accessible qu'à partir de certains contextes.
Lamémoire non résidente n'est accessible qu'à partir du contexte du processus. L'accès à la mémoire non résidente à partir du contexte d'interruption a des résultats imprévisibles et, par conséquent, lorsque le système d'exploitation détecte un tel accès, il prendra des mesures drastiques : bloquer ou réinitialiser le système, pour éviter toute corruption grave.
La mémoire virtuelle d'un processus n'est pas accessible directement depuis le noyau. Généralement, il est totalement déconseillé d'accéder à l'espace d'adressage d'un processus, mais il existe des situations dans lesquelles un pilote de périphérique doit le faire. Le cas typique est celui où le pilote de périphérique doit accéder à un tampon depuis l'espace utilisateur. Dans ce cas, le pilote de périphérique doit utiliser des fonctions spéciales et ne pas accéder directement au tampon. Ceci est nécessaire pour empêcher l'accès aux zones de mémoire non valides.
Une autre différence avec la programmation en espace utilisateur, relative au travail en mémoire, est due à la pile, la pile dont la taille est fixe et limitée. Dans le noyau Linux, une pile 4K est utilisée par défaut, et sous Windows, une pile 12K est utilisée. Pour cette raison, l'allocation de grandes structures sur la pile ou l'utilisation d'appels récursifs doivent être évités.
En ce qui concerne le mode d'exécution dans le noyau, nous distinguons deux contextes : le contexte de processus et le contexte d'interruption. Nous sommes dans le contexte du processus lorsque nous exécutons du code suite à un appel système ou lorsque nous exécutons dans le contexte d'un thread du noyau. Lorsque nous courons dans la routine de gestion d'une pause ou d'une action différée, nous courons dans un contexte de pause.
L'une des caractéristiques les plus importantes de la programmation du noyau est le parallélisme. Linux et Windows prennent en charge les systèmes SMP avec plusieurs processeurs, mais le noyau prend également en charge de manière préventive plusieurs processeurs. Cela rend la programmation du noyau plus difficile car l'accès aux variables globales doit être synchronisé avec des primitives de verrouillage ou de blocage.
Linux et Windows utilisent tous deux des noyaux préemptifs. La notion de multitâche préemptif ne doit pas être confondue avec la notion de noyau préemptif. La notion de multitâche préemptif fait référence au fait que le système d'exploitation interrompt l'exécution d'un processus de manière forcée, lorsqu'il a expiré le temps imparti et s'exécute en espace utilisateur, pour exécuter un autre processus.
Pour la programmation dans le noyau Linux, la convention utilisée pour appeler les fonctions pour indiquer le succès est identique à celle de la programmation UNIX : 0 pour le succès, ou une valeur autre que 0 pour l'échec.