Comment faire des appels système de travail?
Je comprends qu'un utilisateur peut posséder un processus et chaque processus dispose d'un espace d'adressage (qui contient valide emplacements de mémoire, ce processus peut de référence). Je sais que d'un processus d'appel d'un appel système et de passer des paramètres à elle, comme toute autre fonction de la bibliothèque. Cela semble suggérer que tous les appels système sont dans un espace d'adressage du processus par le partage de la mémoire, etc. Mais peut-être, ce n'est qu'une illusion créée par le fait que dans le langage de programmation de haut niveau, des appels système ressemble à aucun autre fonction, lorsqu'un processus appelle.
Mais, maintenant permettez-moi de prendre un pas plus loin et d'analyser de plus près sur ce qui se passe sous le capot. Comment compilateur compiler un appel système? Il pousse peut-être le système d'appel le nom et les paramètres fournis par le processus dans une pile, puis mettre l'instruction d'assemblage dire "PIÈGE" ou quelque chose -- en gros l'assemblée instruction d'appeler une interruption logicielle.
Ce PIÈGE de l'assemblée instruction est exécutée par le matériel en premier pour faire basculer le mode de bits d'utilisateur à noyau, puis le réglage du code pointeur-à-dire au début de l'interruption de service de routine. À partir de ce point, le rapport de recherche internationale s'exécute en mode noyau, qui reprend les paramètres de la pile (c'est possible, parce que le noyau a accès à un emplacement de mémoire, même ceux possédés par des processus utilisateur) et exécute l'appel système et à la fin, elle abandonne le CPU, ce qui permet de basculer le mode de bits et le processus utilisateur commence à partir de là où il l'avait laissé.
Est ma compréhension correcte?
Joint est rude schéma de ma compréhension:
Vous devez vous connecter pour publier un commentaire.
Votre compréhension est assez proche; le truc, c'est que la plupart des compilateurs ne jamais écrire des appels système, car les fonctions que les programmes d'appel (par exemple,
getpid(2)
,chdir(2)
, etc.) sont effectivement fournis par la bibliothèque standard C. La bibliothèque standard C contient le code de l'appel système, si elle est appelée parINT 0x80
ouSYSENTER
. Ce serait un étrange programme qui fait des appels système sans une bibliothèque à faire le travail. (Même siperl
fournit unsyscall()
fonction de ce que peut directement faire des appels système! Fou, non?)Prochain, la mémoire. Le noyau du système d'exploitation parfois est facile de l'espace d'adressage d'accès de l'utilisateur de la mémoire du processus. Bien sûr, les modes de protection sont différents, et les données fournies par l'utilisateur doit être copié dans le noyau de l'espace d'adressage protégé pour empêcher toute modification des données fournies par l'utilisateur alors que l'appel système est en vol:
Alors qu'il n'est pas un système d'appel lui-même, est un fonction d'assistance appelée par le système d'appel des fonctions qui copie les noms de fichiers dans le noyau de l'espace d'adressage. Il vérifie que l'ensemble du nom de fichier réside dans les données de l'utilisateur gamme, appelle une fonction qui copie la chaîne de caractères à partir de l'espace utilisateur, et effectue quelques vérifications avant de la retourner.
get_fs()
et des fonctions similaires sont des vestiges de Linux x86-racines. Les fonctions ont implémentations de travail pour toutes les architectures, mais les noms restent archaïques.Tout le travail avec des segments est parce que le noyau et l'espace utilisateur pourrait partager une partie de l'espace d'adressage disponible. Sur une plate-forme 32 bits (où les chiffres sont faciles à comprendre), le noyau aura généralement un gigaoctet d'espace d'adressage virtuel, et les processus des utilisateurs ont généralement trois gigaoctets d'espace d'adressage virtuel.
Lorsqu'un processus d'appels dans le noyau, le noyau a 'corriger' la page table des autorisations pour permettre l'accès à l'ensemble de la gamme, et a l'avantage de pré-rempli TLB entrées pour l'utilisateur de la mémoire. Le plus grand succès. Mais lorsque le noyau doit contexte revenir à l'espace utilisateur, il a pour rincer le TLB pour supprimer le cache des privilèges sur l'espace d'adressage du noyau pages.
Mais le truc, c'est qu'un gigaoctet d'espace d'adressage virtuel est pas suffisant pour toutes les structures de données du noyau sur des machines énormes. Maintenir les métadonnées de mise en cache pour les systèmes de fichiers et de bloquer les pilotes de périphériques, la mise en réseau des piles, et les mappages de mémoire pour tous les processus sur le système, peut prendre une énorme quantité de données.
Si différents "splits" sont disponibles: deux concerts pour l'utilisateur, deux concerts pour le noyau, un concert pour l'utilisateur, trois concerts pour le noyau, etc. Comme l'espace pour le noyau monte, l'espace pour les processus utilisateur va vers le bas. Il y a donc un
4:4
mémoire split qui donne quatre gigaoctets à l'utilisateur de processus, de quatre gigaoctets pour le noyau, le noyau doit jouer avec des descripteurs de segment pour être en mesure d'accéder à la mémoire utilisateur. Le TLB est vidé en entrée et en sortie du système d'appels, ce qui est assez significative de la vitesse de la peine. Mais il permet au noyau de maintenir sensiblement plus grandes structures de données.Beaucoup plus de la page des tables et des plages d'adresses de 64 bits plates-formes fait probablement de toutes les précédentes aspect pittoresque. J'espère que oui, de toute façon.
Oui, vous l'avez assez juste. Un détail cependant, lorsque le compilateur compile un appel système, il va utiliser la nombre de l'appel système plutôt que de le nom. Par exemple, voici un liste de Linux syscalls (pour une ancienne version, mais le concept est toujours le même).
Vous fait appel de la bibliothèque runtime C. Ce n'est pas le compilateur qui insère PIÈGE, c'est la bibliothèque C qui encapsule PIÈGE dans un appel de la bibliothèque. Le reste de votre compréhension est correcte.
libc
. Et oui, les programmes peuvent appeler système des appels directement.Si vous voulez faire un appel directement à partir de votre programme, vous pouvez facilement le faire.
Il est dépendant de la plate-forme, mais disons que vous voulez lire à partir d'un fichier. Chaque appel système a un certain nombre. Dans ce cas, vous placez le numéro de la
read_from_file
appel système dans le registre EAX. Les arguments en faveur de l'appel système est placé dans différents registres ou de la pile (en fonction du système d'appel). Après les registres sont remplis avec les données correctes et que vous êtes prêt à effectuer l'appel système, vous exécutez l'instructionINT 0x80
(dépend de l'architecture).Cette instruction est une interruption qui provoque le contrôle d'aller à l'OS. Le système d'exploitation identifie ensuite le système de numéro d'appel dans le registre EAX, agit en conséquence et donne le contrôle de retour pour le processus de faire de l'appel système.
La façon dont les appels système sont utilisés, sont sujettes à changement et dépend de la plate-forme donnée. Par l'utilisation de bibliothèques qui fournit des interfaces facile à ces appels système, vous rendre vos programmes plus indépendant de la plateforme et votre code sera plus lisible et plus rapide à écrire. Envisager la mise en œuvre du système des appels directement dans un langage de haut niveau. Vous auriez besoin de quelque chose comme assembly en ligne pour s'assurer que les données sont à mettre dans le droit des registres.
Normal programmes habitude de ne pas "compiler des appels". Pour chaque syscall vous habituellement un correspondant de l'espace utilisateur de la bibliothèque de fonction (généralement mis en œuvre dans la libc sur les systèmes Unix). Par exemple, le
mkdir()
fonction transmet ses arguments à lamkdir
syscall.Sur des systèmes GNU (je suppose que c'est la même chose pour les autres), un
syscall()
fonction est utilisée à partir de la mkdir()' fonction. La fonction syscall/macros sont généralement mises en œuvre en C. Par exemple, ont un oeil àINTERNAL_SYSCALL
danssysdeps/unix/sysv/linux/i386/sysdep.h
ousyscall
danssysdeps/unix/sysv/linux/i386/sysdep.S
(glibc).Maintenant, si vous regardez
sysdeps/unix/sysv/linux/i386/sysdep.h
, vous pouvez voir que l'appel au noyau se fait parENTER_KERNEL
qui, historiquement, a été de demander à interrompre0x80
dans i386 Processeurs. Maintenant, il appelle une fonction (je suppose qu'il est mis en œuvre danslinux-gate.so
qui est virtuel, DONC fichier mappé par le noyau, il contient de la manière la plus efficace de faire un syscall pour votre type de CPU).Oui, votre compréhension tout à fait raison, un programme C peut appeler directement appel système, lorsque que l'appel système se produit, il peut être une série d'appels jusqu'à l'assemblée Piège. Je pense énormément votre compréhension peut aider un débutant.Vérifier ce code dans lequel je vais appeler "système" de l'appel système.