


Les appels système sous Linux ne sont pas des entrées légales dans le noyau
Sous Linux, les appels système sont le seul moyen pour l'espace utilisateur d'accéder au noyau. Ils constituent la seule entrée légale au noyau. En fait, d'autres méthodes telles que les fichiers de périphérique et /proc sont finalement exécutées via des appels système.
Normalement, les applications sont programmées via des sockets de programmation d'application (API) plutôt que directement via des appels système, et ces sockets de programmation n'ont pas réellement besoin de correspondre aux appels système fournis par le noyau. Une API définit un ensemble de sockets de programmation utilisés par les applications. Ils peuvent être implémentés sous la forme d'un seul appel système ou en appelant plusieurs appels système. Il n'y a aucun problème même si aucun appel système n'est utilisé. En fait, les API peuvent être implémentées sur différents systèmes d'exploitation, fournissant exactement les mêmes sockets aux applications, mais leur implémentation sur ces systèmes peut être très différente.
Dans le monde Unix, les sockets de programmation d'applications les plus populaires sont basés sur la norme POSIX et Linux est compatible POSIX.
Du point de vue des programmeurs, ils n'ont besoin de s'occuper que de l'API, et le noyau ne s'occupe que des appels système ; la façon dont les fonctions de bibliothèque et les applications utilisent les appels système ne concerne pas le noyau.
Les appels système (souvent appelés appels système sous Linux) sont généralement appelés via des fonctions. Ils nécessitent généralement la définition d'un ou plusieurs paramètres (entrées) et peuvent provoquer certains effets secondaires. Cet effet secondaire est représenté par une longue valeur de retour indiquant le succès (valeur 0) ou l'erreur (valeur négative). Lorsqu'une erreur se produit lors d'un appel système, le code d'erreur est écrit dans la variable globale errno. En appelant la fonction perror(), cette variable peut être traduite en une chaîne d'erreur que l'utilisateur peut comprendre.
Il y a deux particularités dans l'implémentation des appels système : 1) Il y a un qualificatif asmlinkage dans la déclaration de fonction, qui est utilisé pour notifier au compilateur d'extraire uniquement les paramètres de la fonction de la pile. 2) L'appel système getXXX() est défini comme sys_getXXX() dans le noyau. Il s'agit de la convention de dénomination que tous les appels système sous Linux doivent suivre.
Numéro d'appel système : sous Linux, chaque appel système se voit attribuer un numéro d'appel système, et l'appel système peut être associé à ce numéro unique. Lorsqu'un processus de 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 ; Une fois le numéro d'appel système attribué, il ne peut plus être modifié (sinon l'application compilée plantera). Si un appel système est supprimé, le numéro d'appel système qu'il occupe ne peut pas être recyclé. Linux a un appel système "inutilisé" sys_ni_syscall(), qui non seulement renvoie -ENOSYS mais n'effectue aucun autre travail. Ce numéro d'erreur est spécifiquement conçu pour les appels système non valides. Cela semble rare, mais si un appel système est supprimé, cette fonction se charge de « combler le vide ».
Le noyau enregistre une liste de tous les appels système enregistrés dans la table des appels système et la stocke dans sys_call_table. Il est lié à l’architecture et généralement défini dans Entry.s. Ce tableau attribue un numéro d'appel système unique à chaque appel système valide.
Il est difficile pour les programmes de l'espace utilisateur d'exécuter directement le code du noyau. Ils ne peuvent pas appeler directement des fonctions dans l'espace du noyau, car le noyau réside dans un espace d'adressage protégé. L'application doit informer le système sous une forme ou une autre, indiquant au noyau qu'il doit exécuter un appel système, et le système passe à l'état du noyau. appel du noyau Linux , afin que le noyau puisse exécuter l'appel système au nom de l'application. Ces mécanismes de notification au noyau sont implémentés via des interruptions logicielles. Les interruptions logicielles sur les systèmes x86 sont formées par l'instruction int$0x80. Cette instruction déclenchera une exception, obligeant le système à passer en mode noyau et à exécuter le gestionnaire d'exceptions n° 128. Ce programme est le gestionnaire d'appels système et son nom est system_call(). Il est étroitement lié à l'architecture matérielle et est généralement. dans l'entrée Compilé en langage assembleur dans le fichier .s.
Tous les appels système sont piégés dans le noyau sous la même forme que le système Linux drapeau rouge, donc le simple piégeage dans l'espace du noyau ne suffit pas. Par conséquent, le numéro d’appel système doit être transmis au noyau. Sur x86, ce transfert s'effectue en plaçant le numéro d'appel dans le registre eax avant de déclencher le softirq. De cette façon, une fois le gestionnaire d'appels système exécuté, les données peuvent être obtenues à partir d'eax. Le system_call() mentionné ci-dessus vérifie la validité du numéro d'appel système donné en le comparant avec NR_syscalls. S'il est inférieur ou égal à NR_syscalls, la fonction renvoie -ENOSYS. Sinon, l'appel système correspondant est exécuté : call*sys_call_table(,%eax,4);
Étant donné que les entrées de la table des appels système sont stockées en type 32 bits (4 octets), le noyau doit diviser le numéro d'appel système donné par 4, puis utiliser le résultat pour interroger la position du périphérique dans la table. . Comme le montre la figure 1 :
Il a déjà été mentionné que non seulement le numéro d'appel du système, mais également la saisie de certains paramètres externes sont requis. Le moyen le plus simple consiste à stocker ce paramètre dans un registre, tout comme en passant le numéro d'appel système. Sur les systèmes x86, ebx, ecx, edx, esi et edi stockent les 5 premiers paramètres dans l'ordre. Dans le cas peu probable où six paramètres ou plus seraient requis, un registre distinct devrait être utilisé pour stocker les pointeurs pointant vers les adresses de l'espace utilisateur de tous ces paramètres. Les valeurs de retour vers l'espace utilisateur sont également transmises via des registres. Sur les systèmes x86, il est stocké dans le registre eax.
Les appels système doivent vérifier soigneusement si tous leurs paramètres sont légaux et valides. Les appels système sont exécutés dans l'espace du noyau. Si les utilisateurs sont autorisés à transmettre des entrées illégales au noyau, la sécurité et la stabilité du système seront mises à rude épreuve. Le test le plus important consiste à détecter si le pointeur de surveillance fourni par l'utilisateur est valide. Avant que le noyau ne reçoive un pointeur de surveillance de l'espace utilisateur, le noyau doit s'assurer :
.1) La zone mémoire vidéo pointée par l'aiguille de la montre appartient à l'espace utilisateur
2) La zone mémoire pointée par l'aiguille du compteur se trouve dans l'espace d'adressage du processus
3) S'il s'agit d'une lecture, la mémoire lue doit être marquée comme lisible. En cas d'écriture, la mémoire doit être marquée comme inscriptible.
Le noyau propose deux manières d'effectuer la détection nécessaire et de copier les données entre l'espace noyau et l'espace utilisateur. L'une de ces deux méthodes doit être appelée.
copy_to_user() : écriture des données dans l'espace utilisateur, nécessitant 3 paramètres. Le premier paramètre est l'adresse mémoire de destination dans l'espace de processus. La seconde est l'adresse source dans l'espace noyau
.Le troisième est la largeur des données (nombre d'octets) qui doivent être copiées.
copy_from_user() : La lecture des données depuis l'espace utilisateur nécessite 3 paramètres. Le premier paramètre est l'adresse mémoire de destination dans l'espace de processus. Le second est la source dans l'espace noyau
Adresse. Le troisième est la largeur des données (nombre d'octets) qui doivent être copiées.
Remarque : ces deux éléments peuvent provoquer une obstruction. Ces situations se produisent lorsque les pages contenant des données utilisateur sont transférées sur le disque dur plutôt que dans la mémoire mathématique. À ce moment-là, le noyau Linux appelle et le processus se mettra en veille jusqu'à ce que le gestionnaire de défauts de page remplace la page du disque dur vers la mémoire chimique.
Le noyau est dans le contexte du processus lors de l'exécution d'un appel système, et le pointeur actuel pointe vers la tâche en cours, qui est le processus qui a provoqué l'appel système. Dans le contexte d'un processus, le noyau peut dormir (par exemple, en bloquant un appel système ou en appelant explicitement planning()) mais peut être occupé. Lorsque l'appel système revient, le contrôle reste dans system_call(), qui est en fin de compte responsable du basculement vers l'espace utilisateur et de permettre au processus utilisateur de poursuivre son exécution.
Il est très simple d'ajouter un temps d'appel système à Linux. Comment concevoir et implémenter un appel système est le dilemme. La première étape de l'implémentation d'un appel système consiste à décider de son objectif. Cet objectif doit être clair et unique. N'essayez pas d'écrire un appel système polyvalent. ioctl est un matériel pédagogique back-end. Les paramètres, valeurs de retour et codes d'erreur du nouvel appel système sont très importants. Une fois qu'un appel système est compilé, l'enregistrer comme appel système à venir est une tâche fastidieuse, qui suit généralement les étapes suivantes :
1) Ajoutez une entrée à la fin de la table des appels système (généralement située dans Entry.s). En comptant à partir de 0, la position d'une entrée système dans le tableau est son numéro d'appel système. Comme le premier
10 appels système sont attribués au numéro d'appel système 9
2) Pour toute architecture, le numéro d'appel système doit être défini dans include/asm/unistd.h
3) Les appels système doivent être compilés dans l'image du noyau (ne peuvent pas être compilés en modules). Cela doit juste être placé dans un fichier associé sous kernel/.
Généralement, les appels système sont pris en charge par la bibliothèque C. Les programmes utilisateur peuvent utiliser des appels système (ou utiliser des fonctions de bibliothèque, qui sont ensuite réellement appelées) en incluant des fichiers d'en-tête standard et en établissant une liaison avec la bibliothèque C. Heureusement, Linux lui-même fournit un ensemble de macros permettant un accès direct aux appels système. Il définira le registre et appellera l'instruction int$0x80. Cette macro s'appelle _syscalln(), où n va de 0 à 6. Elle représente le nombre de paramètres qui doivent être transmis à l'appel système. En effet, la macro doit savoir exactement combien d'arguments sont insérés dans les registres et dans quel ordre. Prenons l'exemple de l'appel système ouvert :
L'appel système open() est défini comme suit :
longopen(constchar*nom de fichier,intflags,intmode)
La façon d'appeler directement la macro de cet appel système est :
#defineNR_open5
_syscall3(long,open,constchar*,filename,int,flags,int,mode)
De cette façon, l'application peut utiliser directement open(). Appelez simplement l'appel système open() et placez directement la macro dans l'application. Pour chaque macro, il y a 2+2*n paramètres. La signification de chaque paramètre est simple et claire, et ne sera pas expliquée en détail ici.
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!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Pour ouvrir un fichier web.xml, vous pouvez utiliser les méthodes suivantes: Utilisez un éditeur de texte (tel que le bloc-notes ou TextEdit) pour modifier les commandes à l'aide d'un environnement de développement intégré (tel qu'Eclipse ou NetBeans) (Windows: Notepad web.xml; Mac / Linux: Open -A TextEdit web.xml)

Le multithreading dans la langue peut considérablement améliorer l'efficacité du programme. Il existe quatre façons principales d'implémenter le multithreading dans le langage C: créer des processus indépendants: créer plusieurs processus en cours d'exécution indépendante, chaque processus a son propre espace mémoire. Pseudo-Multithreading: Créez plusieurs flux d'exécution dans un processus qui partagent le même espace mémoire et exécutent alternativement. Bibliothèque multi-thread: Utilisez des bibliothèques multi-threades telles que PTHEADS pour créer et gérer des threads, en fournissant des fonctions de fonctionnement de thread riches. Coroutine: une implémentation multi-thread légère qui divise les tâches en petites sous-tâches et les exécute tour à tour.

Linux est mieux utilisé comme gestion de serveurs, systèmes intégrés et environnements de bureau. 1) Dans la gestion des serveurs, Linux est utilisé pour héberger des sites Web, des bases de données et des applications, assurant la stabilité et la fiabilité. 2) Dans les systèmes intégrés, Linux est largement utilisé dans les systèmes électroniques intelligents et automobiles en raison de sa flexibilité et de sa stabilité. 3) Dans l'environnement de bureau, Linux fournit des applications riches et des performances efficaces.

Les principales raisons pour lesquelles vous ne pouvez pas vous connecter à MySQL en tant que racines sont des problèmes d'autorisation, des erreurs de fichier de configuration, des problèmes de mot de passe incohérents, des problèmes de fichiers de socket ou une interception de pare-feu. La solution comprend: vérifiez si le paramètre Bind-Address dans le fichier de configuration est configuré correctement. Vérifiez si les autorisations de l'utilisateur racine ont été modifiées ou supprimées et réinitialisées. Vérifiez que le mot de passe est précis, y compris les cas et les caractères spéciaux. Vérifiez les paramètres et les chemins d'autorisation du fichier de socket. Vérifiez que le pare-feu bloque les connexions au serveur MySQL.

J'ai développé un projet appelé Lua-Libuv et je suis heureux de partager mon expérience. L'intention initiale du projet est d'explorer comment utiliser Libuv (une bibliothèque d'E / S asynchrone écrite en c) pour créer un serveur HTTP simple sans avoir à apprendre le langage C en profondeur. Avec l'aide de Chatgpt, j'ai terminé le code de base de HTTP.C. Lorsque je traite des connexions persistantes, j'ai réussi à mettre en œuvre la clôture de la connexion et à libérer les ressources au bon moment. Au début, j'ai essayé de créer un serveur simple qui a mis fin au programme principal en fermant la connexion, mais j'ai eu quelques problèmes. J'ai essayé d'envoyer des blocs de données à l'aide de streaming, et pendant que cela fonctionne, cela bloque le thread principal. En fin de compte, j'ai décidé d'abandonner cette approche parce que mon objectif n'était pas d'apprendre la langue C en profondeur. Enfin, je

C La compilation conditionnelle du langage est un mécanisme pour compiler sélectivement les blocs de code en fonction des conditions de temps de compilation. Les méthodes d'introduction incluent: l'utilisation des directives #IF et #ELSE pour sélectionner des blocs de code en fonction des conditions. Les expressions conditionnelles couramment utilisées incluent STDC, _WIN32 et Linux. Cas pratique: imprimez différents messages en fonction du système d'exploitation. Utilisez différents types de données en fonction du nombre de chiffres du système. Différents fichiers d'en-tête sont pris en charge selon le compilateur. La compilation conditionnelle améliore la portabilité et la flexibilité du code, ce qui le rend adaptable aux modifications du compilateur, du système d'exploitation et de l'architecture du processeur.

1.0.1 Préface Ce projet (y compris le code et les commentaires) a été enregistré pendant ma rouille autodidacte. Il peut y avoir des déclarations inexactes ou peu claires, veuillez vous excuser. Si vous en profitez, c'est encore mieux. 1.0.2 Pourquoi Rustrust est-il fiable et efficace? La rouille peut remplacer C et C, par des performances similaires mais une sécurité plus élevée, et ne nécessite pas de recompilation fréquente pour vérifier les erreurs comme C et C. Les principaux avantages incluent: la sécurité de la mémoire (empêcher les pointeurs nuls de déréférences, les pointeurs pendants et la contention des données). Filetage (assurez-vous que le code multithread est sûr avant l'exécution). Évitez le comportement non défini (par exemple, le tableau hors limites, les variables non initialisées ou l'accès à la mémoire libérée). Rust offre des fonctionnalités de langue moderne telles que les génériques

Il existe de nombreuses raisons pour lesquelles la startup MySQL échoue, et elle peut être diagnostiquée en vérifiant le journal des erreurs. Les causes courantes incluent les conflits de port (vérifier l'occupation du port et la configuration de modification), les problèmes d'autorisation (vérifier le service exécutant les autorisations des utilisateurs), les erreurs de fichier de configuration (vérifier les paramètres des paramètres), la corruption du répertoire de données (restaurer les données ou reconstruire l'espace de la table), les problèmes d'espace de la table InNODB (vérifier les fichiers IBDATA1), la défaillance du chargement du plug-in (vérification du journal des erreurs). Lors de la résolution de problèmes, vous devez les analyser en fonction du journal d'erreur, trouver la cause profonde du problème et développer l'habitude de sauvegarder régulièrement les données pour prévenir et résoudre des problèmes.
