- Quelle est la différence entre la pile du noyau et la pile utilisateur?
En bref, rien - à part l'utilisation d'un emplacement différent dans la mémoire (et donc une valeur différente pour le registre de stackpointer), et généralement différentes protections d'accès à la mémoire. C'est-à-dire que lors de l'exécution en mode utilisateur, la mémoire du noyau (dont une partie est la pile du noyau) ne sera pas accessible même si elle est mappée. Vice versa, sans être explicitement demandée par le code du noyau (sous Linux, via des fonctions comme copy_from_user()
), la mémoire utilisateur (y compris la pile utilisateur) n'est généralement pas directement accessible.
- Pourquoi une pile de noyau [distincte] est-elle utilisée?
Séparation des privilèges et de la sécurité. D'une part, les programmes de l'espace utilisateur peuvent faire de leur pile (pointeur) tout ce qu'ils veulent, et il n'y a généralement aucune exigence architecturale pour même en avoir une valide. Le noyau ne peut donc pas faire confiance au pointeur de pile de l'espace utilisateur pour être valide ou utilisable, et par conséquent nécessitera un ensemble sous son propre contrôle. Différentes architectures de CPU implémentent cela de différentes manières; Les processeurs x86 commutent automatiquement de pointeur de pile lorsque des commutations de mode de privilège se produisent, et les valeurs à utiliser pour différents niveaux de privilège sont configurables - par code privilégié (c'est-à-dire uniquement le noyau).
- Si une variable locale est déclarée dans un ISR, où sera-t-elle stockée?
Sur la pile du noyau. Le noyau (noyau Linux, c'est-à-dire) n'accroche pas les ISR directement aux portes d'interruption de l'architecture x86, mais délègue à la place l'envoi d'interruption à un mécanisme commun d'entrée / sortie d'interruption du noyau qui enregistre l'état du registre de pré-interruption avant d'appeler le (s) gestionnaire (s) enregistré (s) . Le processeur lui-même lors de la distribution d'une interruption peut exécuter un privilège et / ou un commutateur de pile, et ceci est utilisé / configuré par le noyau de sorte que le code d'entrée d'interruption commun puisse déjà compter sur la présence d'une pile de noyau.
Cela dit, les interruptions qui se produisent lors de l'exécution du code du noyau utiliseront simplement (continueront) d'utiliser la pile du noyau en place à ce stade. Cela peut, si les gestionnaires d'interruption ont des chemins d'appels profondément imbriqués, entraîner des débordements de pile (si un chemin d'appel profond du noyau est interrompu et que le gestionnaire provoque un autre chemin profond; sous Linux, le code RAID du système de fichiers / logiciel est interrompu par le code réseau avec iptables actif est connu pour déclencher une telle situation dans les noyaux plus anciens non réglés ... la solution est d'augmenter la taille de la pile du noyau pour de telles charges de travail).
- Chaque processus a-t-il sa propre pile de noyau?
Pas seulement chaque processus - chaque thread a sa propre pile de noyau (et, en fait, sa propre pile d'utilisateurs également). N'oubliez pas que la seule différence entre les processus et les threads (sous Linux) est le fait que plusieurs threads peuvent partager un espace d'adressage (formant un processus).
- Comment le processus se coordonne-t-il entre ces deux piles?
Pas du tout - ce n'est pas nécessaire. La planification (comment / quand différents threads sont exécutés, comment leur état est enregistré et restauré) est la tâche du système d'exploitation et les processus n'ont pas besoin de se préoccuper de cela. Au fur et à mesure que les threads sont créés (et que chaque processus doit avoir au moins un thread), le noyau crée des piles de noyau pour eux, tandis que les piles de l'espace utilisateur sont soit explicitement créées / fournies par le mécanisme utilisé pour créer un thread (fonctions comme makecontext()
ou pthread_create()
permettent à l'appelant de spécifier une région mémoire à utiliser pour la pile du thread "enfant"), ou héritée (par clonage de mémoire à l'accès, généralement appelé "copie en écriture" / COW, lors de la création d'un nouveau processus).
Cela dit,(état, parmi lesquels se trouve le pointeur de pile du thread). Il y a plusieurs façons pour cela: signaux UNIX, setcontext()
, pthread_yield()
/ pthread_cancel()
... - mais cela est disgressing un peu de la question initiale.
Ma réponse est collectée à partir d'autres questions SO avec mes affaires.
En tant que programmeur du noyau, vous savez que le noyau doit être limité aux programmes utilisateur erronés. Supposons que vous gardiez la même pile pour le noyau et l'espace utilisateur, puis un simple segfault dans l'application utilisateur plante le noyau et doit être redémarré.
Il y a une "pile de noyau" par CPU comme ISR Stack et une "pile de noyau" par Processus. Il y a une "pile utilisateur" pour chaque processus, bien que chaque thread ait sa propre pile, y compris les threads utilisateur et noyau.
http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html
Ainsi, lorsque nous sommes en mode noyau, un mécanisme de type pile est nécessaire pour traiter les appels de fonction, des variables locales similaires à l'espace utilisateur.
http://www.kernel.org/doc/Documentation/x86/kernel-stacks
Il sera stocké dans la pile ISR (IRQSTACKSIZE). L'ISR s'exécute sur une pile d'interruptions distincte uniquement si le matériel le prend en charge. Sinon, les cadres de pile ISR sont poussés sur la pile du thread interrompu.
L'espace utilisateur ne sait pas et ne se soucie franchement pas de savoir si l'interruption est servie dans la pile de noyau du processus actuel ou dans une pile ISR séparée. Comme les interruptions viennent par processeur, la pile ISR doit donc être par processeur.
Oui. Chaque processus a sa propre pile de noyau.
La réponse de @ FrankH me va très bien.
la source
Prenant référence au développement du noyau Linux de Robert Love, la principale différence est la taille:
De plus, la pile du noyau contient un pointeur vers la structure thread_info contenant des informations sur le thread.
la source