stack de kernel et stack d’espace utilisateur

Quelle est la différence entre la stack du kernel et la stack utilisateur? Pourquoi la stack du kernel est utilisée? Si une variable locale est déclarée dans un ISR, où sera-t-elle stockée? Chaque processus a-t-il sa propre stack de kernel? Alors comment le processus se coordonne entre ces deux stacks?

  1. Quelle est la différence entre la stack du kernel et la stack utilisateur?

En bref, rien – hormis 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’access à la mémoire. Par exemple, lors de l’exécution en mode utilisateur, la mémoire du kernel (dont la stack du kernel fait partie) ne sera pas accessible même si elle est mappée. Inversement, sans être explicitement demandé par le code du kernel (sous Linux, via des fonctions telles que copy_from_user() ), la mémoire utilisateur (y compris la stack utilisateur) n’est généralement pas directement accessible.

  1. Pourquoi est-ce qu’une stack de kernel séparée est utilisée?

Séparation des privilèges et de la sécurité. D’une part, les programmes en espace utilisateur peuvent faire de leur stack (pointeur) tout ce qu’ils veulent, et il n’y a généralement aucune exigence architecturale pour en avoir un qui soit valide. Le kernel ne peut donc pas faire confiance au pointeur d’espace utilisateur pour qu’il ne soit ni valide, ni utilisable, et par conséquent il faudra un seul ensemble sous son propre contrôle. Différentes architectures de processeurs implémentent cela de différentes manières. Les processeurs x86 changent automatiquement de pointeur de stack lorsque des changements 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 kernel).

  1. Si une variable locale est déclarée dans un ISR, où sera-t-elle stockée?

Sur la stack du kernel. Le kernel (kernel Linux, c’est-à-dire) n’accède pas directement aux ISR des portes d’interruption de l’architecture x86, mais délègue la dissortingbution des interruptions à un mécanisme d’entrée / sortie d’interruption du kernel commun qui enregistre . Lors de l’envoi d’une interruption, le processeur lui-même peut exécuter un commutateur de privilège et / ou de stack, qui est utilisé / configuré par le kernel pour que le code d’entrée d’interruption commun puisse déjà être présent.
Cela dit, les interruptions qui surviennent lors de l’exécution du code du kernel utiliseront simplement (continueront à utiliser) la stack du kernel à cet endroit. Cela peut, si les gestionnaires d’interruption ont des chemins d’appel profondément nesteds, conduire à des débordements de stack (si un chemin d’appel profond du kernel est interrompu et que le gestionnaire provoque un autre chemin profond; sous Linux, le code RAID logiciel interrompu par le code réseau avec iptables actif est connu pour déclencher de tels kernelx plus anciens non réglés … la solution consiste à augmenter la taille de la stack du kernel pour de telles charges de travail).

  1. Chaque processus a-t-il sa propre stack de kernel?

Pas seulement chaque processus – chaque thread a sa propre stack de kernel (et, en fait, sa propre stack utilisateur). Rappelez-vous que la seule différence entre les processus et les threads (vers Linux) est le fait que plusieurs threads peuvent partager un espace d’adressage (formant un processus).

  1. Comment le processus se coordonne-t-il entre ces deux stacks?

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 s’en préoccuper. Lorsque des threads sont créés (et que chaque processus doit avoir au moins un thread), le kernel crée pour eux des stacks de kernel, tandis que les stacks d’espace utilisateur sont explicitement créées / fournies par le mécanisme utilisé pour créer un thread (fonctions makecontext() ou pthread_create() permet à l’appelant de spécifier une région mémoire à utiliser pour la stack du thread “enfant”), ou héritée (par clonage de mémoire à l’access, généralement appelée “copy on write” / COW, lors de la création d’un nouveau processus).
Cela dit, le processus peut influencer la planification de ses threads et / ou influencer le contexte (état, parmi lesquels se trouve le pointeur de stack du thread). Il y a plusieurs façons pour cela: les signaux UNIX, setcontext() , pthread_yield() / pthread_cancel() , … – mais c’est un peu dégoûtant de la question initiale.

Ma réponse provient d’autres questions de SO avec mes affaires.

 What's the difference between kernel stack and user stack? 

En tant que programmeur du kernel, vous savez que le kernel doit être limité aux programmes utilisateur erronés. Supposons que vous gardiez la même stack à la fois pour le kernel et pour l’espace utilisateur, puis que le simple segfault dans l’application utilisateur bloque le kernel et nécessite un redémarrage.

Il y a une “stack de kernel” par processeur comme ISR Stack et une “stack de kernel” par processus. Il existe une “stack utilisateur” pour chaque processus, bien que chaque thread ait sa propre stack, y compris les threads utilisateur et kernel.

http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html

 Why kernel stack is used? 

Donc, lorsque nous sums en mode kernel, un mécanisme de type stack est nécessaire pour traiter les appels de fonctions, des variables locales similaires à l’espace utilisateur.

http://www.kernel.org/doc/Documentation/x86/kernel-stacks

 If a local variable is declared in an ISR, where it will be stored? 

Il sera stocké dans la stack ISR (IRQSTACKSIZE). L’ISR s’exécute sur une stack d’interruptions distincte uniquement si le matériel le prend en charge. Sinon, les frameworks de stack ISR sont poussés dans la stack du thread interrompu.

L’espace utilisateur ne sait pas et franchement ne se soucie pas de savoir si l’interruption est servie dans la stack du kernel du processus en cours ou dans une stack ISR distincte. Comme les interruptions viennent par CPU, la stack ISR doit donc être par processeur.

  Does each process has its own kernel stack ? 

Oui. Chaque processus a sa propre stack de kernel.

  Then how the process coordinates between both these stacks? 

La réponse de @ FrankH me va très bien.

  1. Quelle est la différence entre la stack du kernel et la stack des utilisateurs

En prenant comme référence le développement de kernel Linux de Robert Love, la principale différence est la taille:

L’espace utilisateur peut s’en tirer avec l’allocation statique de nombreuses variables sur la stack, y compris les structures énormes et les tableaux de milliers d’éléments.
Ce comportement est légal car l’espace utilisateur a une grande stack qui peut se développer dynamicment.
La stack du kernel n’est ni grande ni dynamic; il est petit et de taille fixe.
La taille exacte de la stack du kernel varie selon l’architecture.
Sur x86, la taille de la stack est configurable au moment de la compilation et peut atteindre 4 Ko ou 8 Ko.
Historiquement, la stack du kernel est composée de deux pages, ce qui implique généralement qu’il s’agit de 8 Ko sur des architectures 32 bits et de 16 Ko sur des architectures 64 bits – cette taille est fixe et absolue.
Chaque processus reçoit sa propre stack.

La stack du kernel contient également un pointeur vers la structure thread_info contenant des informations sur le thread.