[Notes de lecture] Conception du noyau Linux et appel du système d'implémentation

L'implémentation de l'interface de l'appel système vise principalement à assurer la stabilité et la fiabilité du système et à éviter une application arbitraire de l'application.

1. Communication nucléaire de Yonai

Les appels système ajoutent une couche intermédiaire entre les processus de l'espace utilisateur et les périphériques matériels.
Le rôle est le suivant:

  1. Fournit une interface matérielle abstraite pour l'espace utilisateur;
  2. Assurer la stabilité et la sécurité du système;
  3. Chaque processus s'exécute dans un système virtuel et fournit une telle interface commune dans l'espace utilisateur et le reste du système.

ps: Dans les systèmes Linux, les appels système sont le seul moyen d'accéder à l'espace utilisateur du noyau; à l'exception des exceptions et des interruptions, ils sont le seul point d'entrée légal pour le noyau.

2. Bibliothèques API, POSIX et C

En général, les applications sont programmées via des interfaces de programmation d'application (API) implémentées dans l'espace utilisateur plutôt que directement via des appels système.
ps: les applications qui utilisent cette interface de programmation n'ont pas réellement besoin de correspondre aux appels système fournis par le noyau.

Comme le montre la figure pour approfondir la compréhension:
Insérez la description de l'image ici
il existe une maxime sur la conception de l'interface du mécanisme de fourniture unix (quelles fonctions doivent fournir) au lieu de la stratégie (comment réaliser ces fonctions) . C'est-à-dire que l'appel système Unix résume les fonctions permettant d'accomplir un certain but. Quant à la façon d'utiliser ces fonctions, le noyau n'a pas besoin d'être concerné.

3. Appel système

Pour accéder à l'appel système (souvent appelé syscall sous Linux), généralement via l'appel de fonction défini dans la bibliothèque C.
Lorsqu'une erreur d'appel système se produit, la bibliothèque C écrit le code d'erreur dans la variable globale errno. Cette variable peut être traduite en une chaîne d'erreur que l'utilisateur peut comprendre en appelant la fonction de bibliothèque oerror ().

Q: Comment définir l'appel système?
R: Afin d'assurer la compatibilité des systèmes 32 bits et 64 bits, les appels système ont différents types de valeur de retour dans l'espace utilisateur et l'espace noyau, int dans l'espace utilisateur et long dans l'espace noyau. Le nom de la fonction est également préfixé par sys_. Par exemple, l'appel système getpid () est défini comme sys_getpid () dans le noyau.

3.1 Fonction d'appel système correspondant au numéro d'appel système

Sous Linux, chaque appel système reçoit un numéro d'appel système (unique).
Lorsqu'un processus dans l'espace utilisateur exécute un appel système, le numéro d'appel système est utilisé pour indiquer quel appel système doit être exécuté. Le processus ne mentionne pas le nom de l'appel système (le numéro d'appel système est donc important).

Linux a un appel système "non implémenté" sys_ni_syscall (), qui ne fait rien d'autre que retourner -ENOSYS.

Le noyau enregistre une liste de tous les appels système enregistrés dans la table d'appels système et les stocke dans sys_call_table. Ce tableau spécifie un numéro d'appel système unique pour chaque appel système valide.

3.2 Performance des appels système

Les appels système Linux s'exécutent plus rapidement que de nombreux autres systèmes d'exploitation.
Pourquoi
A: Linux est court laps de temps de changement de contexte est une raison importante, et hors du noyau ont été optimisés pour être simple et efficace,
suivi par le gestionnaire d'appels système et chaque appel système lui - même est très simple.

4. Gestionnaire d'appels système

Les programmes de l'espace utilisateur ne peuvent pas exécuter directement le code du noyau.
L'application doit notifier le système d'une certaine manière et laisser le noyau effectuer des appels système dans l'espace du noyau au nom de l'application.
Le mécanisme de notification du noyau est implémenté par des interruptions logicielles : en levant une exception, le système passe à l'état du noyau pour exécuter le gestionnaire d'exceptions, le gestionnaire d'appels système.

4.1 Spécifiez l'appel système approprié

Parce que tous les appels système tombent dans le noyau de la même manière, il ne suffit pas de tomber dans l'espace du noyau. Le numéro d'appel système doit être transmis au noyau.
Insérez la description de l'image ici

4.2 Passage de paramètres

En plus du numéro d'appel système, la plupart des appels système nécessitent également une entrée de paramètre externe. Par conséquent, lorsqu'un piège se produit, ces paramètres doivent être passés de l'espace utilisateur au noyau. Le moyen le plus simple consiste à stocker ces paramètres dans le registre comme en passant le numéro d'appel système.

5. Mise en œuvre de l'appel système

5.1 Implémentation d'appels système

La première étape de la mise en œuvre d'un nouvel appel système consiste à déterminer son objectif. Chaque appel système doit avoir un objectif clair. Il n'est pas recommandé d'utiliser des appels système polyvalents sous Linux (un appel système choisit d'exécuter différentes tâches en transmettant différentes valeurs de paramètres).

5.2 Vérification des paramètres

Les appels système doivent vérifier soigneusement si tous leurs paramètres sont légaux et valides . Empêchez les utilisateurs de transmettre des entrées illégales au noyau.
Chaque paramètre doit être vérifié pour s'assurer qu'il est non seulement valide et valide, mais également correct. Un processus ne doit pas laisser le noyau accéder aux ressources auxquelles il n'a pas accès.
Le type de vérification le plus important consiste à vérifier si le pointeur fourni par l'utilisateur est valide.
Avant de recevoir un pointeur d'espace utilisateur, le noyau doit garantir ce qui suit:

  1. La zone mémoire pointée par le pointeur appartient à l'espace utilisateur. Le processus ne doit pas amadouer le noyau pour lire les données dans l'espace du noyau;
  2. La zone mémoire pointée par le pointeur se trouve dans l'espace d'adressage du processus. Les processus ne doivent pas inciter le noyau à lire les données d'autres processus;
  3. S'il est lu, la mémoire doit être marquée comme lisible; si elle est écrite, la mémoire doit être marquée comme accessible en écriture; si elle est exécutable, la mémoire doit être marquée comme exécutable. Les processus ne doivent pas contourner les restrictions d'accès à la mémoire.

Le noyau propose deux méthodes pour effectuer les vérifications nécessaires et copier les données dans les deux sens entre l'espace du noyau et l'espace utilisateur. Comme indiqué dans le tableau suivant:

La méthode Fonction Explication Valeur de retour
copy_to_user () Écrire des données dans l'espace utilisateur Le premier paramètre est l'adresse mémoire de destination dans l'espace de processus, le second est l'adresse source dans l'espace noyau, et le dernier paramètre est la longueur des données à copier (nombre d'octets) Échec de l'exécution: nombre d'octets de données qui n'ont pas pu être copiés; réussite: 0; lorsque l'erreur ci-dessus se produit, l'appel système renvoie la norme -EFAULT
copy_from_user () Lire les données de l'espace utilisateur Il existe également trois paramètres, similaires à copy_to_user, les données à la position spécifiée par le deuxième paramètre sont copiées à la position spécifiée par le premier paramètre, et la longueur des données copiées est déterminée par le troisième paramètre Comme ci-dessus

ps: copy_to_user () et copy_from_user () peuvent provoquer un blocage. Lorsque des pages contenant des données utilisateur sont échangées sur le disque dur plutôt que sur la mémoire physique, un blocage se produit. À ce stade, le processus se mettra en veille jusqu'à ce que le gestionnaire d'erreur de page renvoie la page du disque dur à la mémoire physique.

Le dernier contrôle concerne l'autorisation légale .
La nouvelle version du noyau Linux fournit un mécanisme de «capacité» plus fin et le nouveau système permet de vérifier les autorisations spéciales pour des ressources spécifiques. L'appelant peut utiliser la fonction enable () pour vérifier s'il a le droit d'opérer sur la ressource spécifiée. S'il renvoie une valeur non nulle, l'appelant a le droit d'effectuer l'opération et renvoie 0 pour n'avoir aucun droit d'opérer.
par exemple:

if(!capable(CAP_SYSY_BOOT))	/* 启动系统的系统管理员 */
	return -EPERM;

Reportez-vous à <linux / capacity.h> pour une liste des capacités de propriété et leurs autorisations.

6. Contexte d'appel système

Le noyau est dans le contexte du processus lors de l'exécution des appels système. Le pointeur actuel pointe vers la tâche en cours, le processus qui a provoqué l'appel système.

Dans le contexte du processus , le noyau peut se mettre en veille (par exemple lorsqu'un appel système est bloqué ou lorsque Schedule () est explicitement appelé) et peut être préempté .

6.1 La dernière étape de la liaison d'un appel système

Q: Après avoir écrit un appel système, comment l'enregistrer en tant qu'appel système formel?
Un:

  1. Ajoutez une entrée à la fin de la table d'appels système (pour la plupart des architectures, cette table se trouve dans le fichier entry.s). Chaque système matériel qui prend en charge l'appel système doit effectuer ce type de travail. À partir de 0, la position de l'appel système dans ce tableau est son numéro d'appel système;
  2. Pour diverses architectures prises en charge, le numéro d'appel système doit être défini dans <asm / unistd.h>, et l'habitude d'appeler de bons commentaires est généralement ajoutée toutes les 5 entrées du fichier, que vous pouvez trouver dans l'appel système correspondant. Pour plus de commodité lors de l'appel
  3. Les appels système doivent être compilés dans l'image du noyau (ne peuvent pas être compilés en modules). Il suffit de le placer dans un fichier approprié sous kernel /, tel que sys.c, qui contient divers appels système.

6.2 Accéder aux appels système depuis l'espace utilisateur - Bibliothèque C / Macro Linux

Habituellement, les appels système sont pris en charge par la bibliothèque C. En incluant des fichiers d'en-tête standard et en établissant une liaison avec la bibliothèque C, les programmes utilisateur peuvent utiliser des appels système (ou appeler des fonctions de bibliothèque, qui sont en fait appelées par des fonctions de bibliothèque).
Linux lui-même fournit un ensemble de macros pour un accès direct aux appels système (pas besoin d'introduire les fichiers d'en-tête de la bibliothèque C), il établira des registres et des instructions d'interruption d'appel.
Ces macros sont _syscalln (), où n varie de 0 à 6, représentant le nombre de paramètres qui doivent être passés à l'appel système. En effet, la macro doit savoir combien de paramètres sont poussés dans le registre dans quel ordre.
Par exemple:
La définition d'appel système de open () est:

long open(const char *filename, int flags, int mode);

Sans le support de la bibliothèque C, la forme d'appel direct via la macro est:

#define NR_open 5		/* <asm/unistd.h>中定义的系统调用号 */
_syscall3(long, open, const char*, filename, int, flags, int, mode)  

Pour chaque macro, il y a 2 + 2xn paramètres.
Le premier paramètre correspond au type de valeur de retour de l'appel système.
Le deuxième paramètre est le nom de l'appel système.
Voici le type et le nom de chaque paramètre classés dans l'ordre des paramètres d'appel système.

6.3 Pourquoi ne pas utiliser l'appel système

Les systèmes Linux essaient d'éviter simplement d'ajouter un nouvel appel système chaque fois qu'une nouvelle abstraction apparaît.
Remplacez généralement l'appel système que vous souhaitez implémenter comme suit:
implémentez un nœud de périphérique et implémentez read () et write () pour cela. Utilisez ioctl pour opérer sur des paramètres spécifiques ou récupérer des informations spécifiques.

  1. Certaines interfaces comme les sémaphores peuvent être représentées par des descripteurs de fichiers, elles peuvent donc être utilisées comme décrit ci-dessus;
  2. Placez les informations ajoutées sous forme de fichier dans un emplacement approprié dans sysfs.
Publié 91 articles originaux · loué 17 · 50 000+ vues

Je suppose que tu aimes

Origine blog.csdn.net/qq_23327993/article/details/105382862
conseillé
Classement