Maison > Article > développement back-end > Quel est le but de l'appel système
Le but de l'appel système est de demander des services système. Le système d'exploitation ne permet pas aux utilisateurs d'exploiter directement diverses ressources matérielles, de sorte que les programmes utilisateur ne peuvent demander au noyau ses services que via des appels système et utiliser diverses ressources indirectement.
Les fonctions fournies par le système d'exploitation ne sont généralement pas implémentées par l'application elle-même. Par exemple, pour opérer sur des fichiers, l'application doit effectuer des appels système, car seul le système d'exploitation a le pouvoir de gérer directement les périphériques. Un autre exemple est l'opération d'exclusion mutuelle synchrone entre processus ou threads, qui doit également être effectuée par le système d'exploitation pour conserver les variables du noyau.
Regardez un système informatique complet de bas en haut : matériel physique->noyau du système d'exploitation->service du système d'exploitation->application. Le noyau du système d'exploitation joue ici un rôle clé dans la « connexion du précédent et du suivant », en gérant le matériel physique vers le bas et en fournissant des interfaces pour les services et les applications du système d'exploitation vers le haut. L'interface ici est l'appel système.
Le processus d'application s'exécute généralement en mode utilisateur. Lorsqu'il appelle un appel système, le processus entre en mode noyau et exécute le code à l'intérieur du noyau, ayant ainsi le pouvoir d'exécuter des instructions privilégiées et d'exécuter des fonctions spécifiques. En d’autres termes, les appels système permettent aux applications d’accéder activement au noyau du système d’exploitation.
Comme son nom l'indique, les fonctions sont mises dans des bibliothèques. Il s'agit de compiler certaines fonctions couramment utilisées et de les mettre dans un fichier pour que d'autres puissent les utiliser. Lorsque d'autres l'utilisent, ajoutez-y simplement le nom du fichier en utilisant #include, généralement dans le fichier lib.
Les fonctions de la bibliothèque sont principalement fournies par deux parties : l'une est fournie par le système d'exploitation ; l'autre est fournie par un tiers.
Ces fonctions fournies par le système encapsulent ou combinent des appels système pour réaliser plus de fonctions. De telles fonctions de bibliothèque peuvent implémenter certaines opérations plus complexes pour le noyau. Par exemple, la fonction de lecture peut lire directement des fichiers en fonction de paramètres, mais les fichiers cachés derrière, tels que la piste, le secteur et la mémoire qui y sont chargés, sont des problèmes dont les programmeurs n'ont pas à se soucier. Ces opérations incluent également les appels système. Par exemple, la fonction système write() appellera l'appel système du même nom pour terminer l'opération d'écriture.
Pour les bibliothèques tierces, elles sont en fait les mêmes que les bibliothèques système, sauf qu'elles sont moins susceptibles d'utiliser directement les appels système, mais sont implémentées via l'interface API fournie par le système. . Par exemple, printf appelle en fait la fonction système write(). La plupart des fonctions de bibliothèques tierces sont des encapsulations de fonctions système.
La connexion entre les appels système et les fonctions de la bibliothèque :
En fait, ce que les appels système fournissent aux utilisateurs est directement En ce qui concerne les services purement avancés, si nous voulons être plus conviviaux et disposer de fonctions plus adaptées à des situations spécifiques, nous devons alors être définis par les utilisateurs eux-mêmes, de sorte que les fonctions de la bibliothèque soient dérivées, qui enveloppent certains appels système. Par exemple, lorsque nous voulons imprimer une phrase en langage C, si la fonction de bibliothèque printf n'est pas utilisée, nous devons alors l'implémenter nous-mêmes et appeler certaines fonctions système telles que putc() et write(). Cela semble plus gênant, donc les appels système sont destinés à la commodité d'utilisation de l'interface du système d'exploitation, tandis que les fonctions de bibliothèque sont destinées à la commodité de la programmation des utilisateurs.
Par exemple, sous le système d'exploitation Linux, la fonction de la bibliothèque en langage C printf utilise en fait l'appel système write ; tandis que la fonction de la bibliothèque strcpy (copie de chaîne) n'utilise aucun appel système. De plus, l'interface d'appel système d'un système est généralement le plus petit ensemble capable de remplir toutes les fonctions nécessaires. Il peut y avoir plusieurs fonctions de bibliothèque qui encapsulent le même appel système. Par exemple, sous Linux, les trois fonctions de bibliothèque malloc, calloc et free sont toutes complétées en appelant l'appel système brk.
La relation entre les applications, les fonctions de bibliothèque et les appels système est illustrée dans la figure ci-dessous :
La différence entre les appels système et fonctions de bibliothèque :
Les appels de fonctions de bibliothèque font partie du langage ou de l'application, tandis que les appels système font partie du système d'exploitation.
L'appel système est l'interface permettant aux applications d'interagir avec le noyau. Dans la programmation à long terme, les gens ont découvert que l’utilisation des fonctions système présente un inconvénient majeur, à savoir la portabilité du programme. Par exemple, les fonctions d'appel système fournies par Linux sont différentes de celles de Windows.
Les appels de fonctions de bibliothèque sont destinés au développement d'applications et sont équivalents aux API d'application. Il existe de nombreuses raisons d'adopter cette approche :
2. Le mode noyau et le mode utilisateur du CPU.
Habituellement, le processeur a deux modes : "mode utilisateur" et "mode noyau". Un bit de balise est utilisé pour identifier dans quel mode il se trouve actuellement. Le mode noyau peut exécuter toutes les instructions, y compris les instructions privilégiées (principalement certaines instructions de gestion matérielle, telles que les instructions qui modifient le contenu du registre d'adresses de base), tandis que le mode utilisateur ne peut pas exécuter d'instructions privilégiées. Ce type de conception concerne principalement des problèmes de sécurité, c'est-à-dire que le système d'exploitation est responsable de la gestion du matériel afin d'éviter les problèmes matériels causés par une conception incorrecte des applications de couche supérieure.
Étant donné que seul le système d'exploitation peut faire fonctionner directement le matériel, le système d'exploitation doit fournir des interfaces pour permettre aux applications d'accéder aux fonctions matérielles. Ces interfaces sont appelées appels système.
Lorsque le système d'exploitation reçoit la demande d'appel système, le processeur passe en mode noyau pour exécuter des instructions telles que des opérations d'E/S et modifier le contenu du registre d'adresses de base après avoir traité le contenu de l'appel système. , l'opération Le système ramènera le processeur en mode utilisateur pour exécuter le code utilisateur.
Correspond au mode noyau et au mode utilisateur du CPU. L'état d'exécution du processus est divisé en mode tube (mode noyau) et mode œil (mode utilisateur). Pour plus de détails, veuillez consulter l'article : Système d'exploitation - Mode utilisateur et mode noyau
Interruption. (Interruption) Cela signifie généralement qu'un événement en attente se produit à l'intérieur ou à l'extérieur du CPU, le CPU doit donc modifier l'ordre d'exécution des instructions en cours pour gérer de tels événements. Avant d’introduire la relation entre les interruptions et les appels système, commençons par classer les interruptions.
Les interruptions peuvent être grossièrement divisées en deux catégories :
Interruptions asynchrones (interruptions externes) : générées par un autre matériel en dehors du CPU, dites ceci Les interruptions de classe sont asynchrones, ce qui signifie que le signal d'interruption peut être émis à tout moment, quel que soit le battement d'horloge du CPU lui-même. Tels que l'interruption de l'horloge, l'interruption des demandes de service de lecture et d'écriture du disque dur, etc.
Interruptions synchrones (interruptions/exceptions internes ) : générées à l'intérieur du CPU. Ce type d'interruption est dit synchrone, ce qui signifie que le temps de transmission du CPU. Le signal d'interruption doit être à l'heure actuelle. Une fois l'exécution de l'instruction terminée. Généralement, ils proviennent d'événements internes au CPU ou d'événements lors de l'exécution d'un programme, tels que des opcodes illégaux, une adresse hors limites, un débordement de virgule flottante, etc.
Les interruptions synchrones (exceptions) sont divisées dans les catégories suivantes :
Exceptions détectées par le processeur : Le processeur est Interruptions détectées lors de l'exécution d'instructions, telles qu'une opération de division par zéro.
Défauts : une condition anormale se produit, mais une fois la condition anormale éliminée, le flux du programme d'origine peut continuer à s'exécuter sans aucun impact, tel qu'une page manquante. anormal. Notez que l'instruction qui a déclenché l'interruption sera réexécutée.
Traps : Interruptions causées par des instructions piégées, généralement utilisées pour le débogage du programme.
Abandons : Une erreur importante se produit à l'intérieur du CPU, comme une erreur matérielle ou une erreur dans la valeur de la table système. Une fois cette interruption survenue, l'erreur est irrécupérable et le processus en cours ne peut être que terminé.
Exceptions programmées : également appelées interruptions logicielles (interruptions logicielles), interruptions activement initiées par le code du programmeur, utilisées pour implémenter les appels système . Par exemple, sous Linux, l'instruction int 0x80
est utilisée pour implémenter les appels système.
Jusqu'à présent, nous avons découvert la relation entre les interruptions et les appels système : Les appels système sont un type spécial d'interruption (interruption logicielle) .
5. Traitement par le noyau des appels système
Dans les machines x86, un nombre de 8 bits (0 ~ 255) est utilisé pour distinguer Pour diverses interruptions, ce nombre est appelé vecteur d'interruption. L'un des vecteurs d'interruption, 128 (0x80), est spécifiquement utilisé pour exécuter des appels système.
Dans le système Linux, il existe une table système appelée Interrupt DescriptorTable, ou IDT en abrégé. Il y a 256 entrées dans la table IDT, qui stocke la relation de mappage des vecteurs d'interruption aux routines de traitement correspondantes (gestionnaire d'interruption ou d'exception). Lorsqu'une interruption se produit, la CPU trouve l'adresse de la routine de traitement correspondante dans la table IDT et l'exécute.
La routine de traitement des appels système occupe une entrée dans la table IDT. Cet élément est initialisé dans la fonction trap_init, comme suit : set_system_gate(SYSCALL_VECTOR,&system_call);
. Comme mentionné précédemment, la valeur de SYSCALL_VECTOR dans le code ci-dessus est 128.
Lorsqu'un appel système se produit, la routine d'appel système system_call est appelée via le mécanisme d'interruption. Son processus d'exécution est grossièrement divisé en 4 étapes :
1. Prenez le numéro d'appel système et les paramètres d'entrée du registre, puis transférez les valeurs de ces registres dans la pile du noyau. Recherchez dans la table de répartition des appels système en fonction du numéro d'appel système et recherchez la routine de service d'appel système (une fonction du noyau).
2. Appelez la routine de service d'appel système trouvé.
3. Extrayez la valeur de retour de la routine de service d'appel système de la pile et enregistrez-la à nouveau dans le registre.
La routine d'appel système system_call décrite ci-dessus est exécutée dans l'espace noyau. Avant l'exécution, le numéro d'appel système et les paramètres d'entrée ont été stockés dans le registre, et ce processus de stockage est complété par le code de l'espace utilisateur. En fait, comme mentionné dans la première section, chaque appel système réel possède essentiellement une fonction de bibliothèque qui l'encapsule. Généralement, le numéro d'appel système et les paramètres d'entrée sont enregistrés dans cette fonction de bibliothèque. Lorsque la routine d'appel système system_call est exécutée, la valeur de retour est renvoyée à la fonction de bibliothèque d'espace utilisateur via le registre.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!