wake-up-neo.net

Kernel-Stack und User-Space-Stack

Was ist der Unterschied zwischen Kernel-Stack und User-Stack? Warum wird der Kernel-Stack verwendet? Wenn eine lokale Variable in einem ISR deklariert ist, wo wird sie gespeichert? Hat jeder Prozess einen eigenen Kernel-Stack? Wie koordiniert dann der Prozess zwischen diesen beiden Stapeln?

91
jkv
  1. Was ist der Unterschied zwischen Kernel-Stack und User-Stack?

Kurz gesagt, nichts - außer der Verwendung eines anderen Speicherorts (und damit eines anderen Werts für das Stackpointer-Register) und normalerweise eines anderen Speicherzugriffsschutzes. Das heißt Bei Ausführung im Benutzermodus kann auf den Kernelspeicher (zu dem auch der Kernelstapel gehört) nicht zugegriffen werden, selbst wenn er zugeordnet ist. Umgekehrt ist der Benutzerspeicher (einschließlich des Benutzerstapels) normalerweise nicht direkt zugänglich, ohne vom Kernel-Code explizit angefordert zu werden (unter Linux über Funktionen wie copy_from_user()).

  1. Warum wird [ein separater] Kernel-Stack verwendet?

Trennung von Privilegien und Sicherheit. Zum einen können Userspace-Programme ihren Stack (Zeiger) beliebig machen, und es gibt normalerweise keine architektonische Anforderung, um überhaupt einen gültigen zu haben. Der Kernel kann daher nicht darauf vertrauen, dass der User-Space-Stackpointer gültig oder verwendbar ist, und benötigt daher einen Satz, der von ihm gesteuert wird. Unterschiedliche CPU-Architekturen implementieren dies auf unterschiedliche Weise. x86-CPUs wechseln automatisch die Stapelzeiger, wenn der Berechtigungsmodus wechselt, und die für verschiedene Berechtigungsstufen zu verwendenden Werte sind konfigurierbar - durch privilegierten Code (d. h. nur den Kernel).

  1. Wenn eine lokale Variable in einem ISR deklariert ist, wo wird sie gespeichert?

Auf dem Kernelstapel. Der Kernel (also der Linux-Kernel) bindet keine ISRs direkt an die Interrupt-Gates der x86-Architektur, sondern delegiert den Interrupt-Versand an einen gemeinsamen Kernel Interrupt-Eingangs-/Ausgangs-Mechanismus, der den Status des Vor-Interrupt-Registers speichert, bevor die registrierten Handler aufgerufen werden. Die CPU selbst führt beim Auslösen eines Interrupts möglicherweise einen Berechtigungs- und/oder Stack-Switch aus, der vom Kernel verwendet/eingerichtet wird, sodass der gemeinsame Interrupt-Eintrittscode bereits darauf vertrauen kann, dass ein Kernel-Stack vorhanden ist.
Das heißt, Interrupts, die während der Ausführung von Kernel-Code auftreten, verwenden einfach (weiterhin) den an diesem Punkt vorhandenen Kernel-Stack. Dies kann, wenn Interrupt-Handler tief verschachtelte Aufrufpfade haben, zu Stapelüberläufen führen (wenn ein tiefer Kernel-Aufrufpfad unterbrochen wird und der Handler einen anderen tiefen Pfad verursacht) bekanntermaßen solche in nicht abgestimmten älteren Kerneln auslösen ... Lösung besteht darin, die Kernel-Stack-Größen für solche Workloads zu erhöhen).

  1. Verfügt jeder Prozess über einen eigenen Kernel-Stack?

Nicht nur jeder Prozess - jeder Thread hat einen eigenen Kernel-Stack (und in der Tat auch einen eigenen User-Stack). Denken Sie daran, dass der einzige Unterschied zwischen Prozessen und Threads (unter Linux) darin besteht, dass mehrere Threads einen Adressraum gemeinsam nutzen können (einen Prozess bilden).

  1. Wie koordiniert der Prozess zwischen diesen beiden Stapeln?

Überhaupt nicht - das muss es nicht. Die Planung (wie/wann verschiedene Threads ausgeführt werden, wie ihr Status gespeichert und wiederhergestellt wird) ist die Aufgabe des Betriebssystems und die Prozesse müssen sich nicht damit befassen. Wenn Threads erstellt werden (und jeder Prozess muss mindestens einen Thread haben), erstellt der Kernel Kernelstapel für sie, während Userspace-Stapel entweder explizit erstellt/bereitgestellt werden, je nachdem, welcher Mechanismus zum Erstellen eines Threads verwendet wird (Funktionen wie makecontext() oder pthread_create() ermöglichen es dem Aufrufer, einen Speicherbereich anzugeben, der für den Stapel des "untergeordneten" Threads verwendet werden soll. beim Anlegen eines neuen Prozesses).
Das heißt, der Prozess kann das Scheduling seiner Threads beeinflussen und/oder den Kontext beeinflussen (Status, darunter der des Threads) stackpointer). Hierfür gibt es mehrere Möglichkeiten: UNIX-Signale, setcontext(), pthread_yield()/pthread_cancel(), ... - aber dies weicht ein wenig von der ursprünglichen Frage ab.

165
FrankH.

Meine Antwort wird von anderen SO Fragen mit meinen Sachen gesammelt.

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

Als Kernel-Programmierer wissen Sie, dass der Kernel von fehlerhaften Benutzerprogrammen ausgeschlossen werden sollte. Angenommen, Sie behalten denselben Stapel für den Kernel und den Benutzerbereich bei, dann stürzt ein einfacher Segfault in der Benutzeranwendung den Kernel ab und muss neu gestartet werden.

Es gibt einen "Kernel-Stack" pro CPU wie ISR-Stack und einen "Kernel-Stack" pro Prozess. Es gibt einen "Benutzerstapel" für jeden Prozess, obwohl jeder Thread seinen eigenen Stapel hat, der sowohl Benutzer- als auch Kernelthreads enthält.

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

Why kernel stack is used?

Wenn wir uns also im Kernel-Modus befinden, ist eine Art Stack-Mechanismus für den Umgang mit Funktionsaufrufen erforderlich, also lokalen Variablen, die dem Benutzerbereich ähneln.

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

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

Es wird im ISR-Stack (IRQSTACKSIZE) gespeichert. Der ISR wird nur dann auf einem separaten Interrupt-Stack ausgeführt, wenn die Hardware dies unterstützt. Andernfalls werden die ISR-Stapelrahmen auf den Stapel des unterbrochenen Threads geschoben.

Der Benutzerraum weiß nicht und kümmert sich offen gesagt nicht darum, ob der Interrupt im Kernel-Stack des aktuellen Prozesses oder in einem separaten ISR-Stack bereitgestellt wird. Da Interrupts pro CPU kommen, muss der ISR-Stack pro CPU sein.

 Does each process has its own kernel stack ?

Ja. Jeder Prozess hat einen eigenen Kernel-Stack.

 Then how the process coordinates between both these stacks?

@ FrankHs Antwort sieht für mich toll aus.

15
Jeyaram
  1. Was ist der Unterschied zwischen Kernel-Stack und User-Stack?

Unter Bezugnahme auf die Linux-Kernel-Entwicklung von Robert Love besteht der Hauptunterschied in der Größe:

Der User-Space kann mit der statischen Zuordnung vieler Variablen auf dem Stack davonkommen, einschließlich riesiger Strukturen und Tausend-Elemente-Arrays.
Dieses Verhalten ist zulässig, da der Benutzerbereich über einen großen Stapel verfügt, der dynamisch wachsen kann.
Der Kernel-Stack ist weder groß noch dynamisch. Es ist klein und fest in der Größe.
Die genaue Größe des Kernel-Stacks hängt von der Architektur ab.
Auf x86 ist die Stapelgröße zur Kompilierungszeit konfigurierbar und kann entweder 4 KB oder 8 KB betragen.
Historisch gesehen besteht der Kernel-Stack aus zwei Seiten, was im Allgemeinen impliziert, dass er auf 32-Bit-Architekturen 8 KB und auf 64-Bit-Architekturen 16 KB groß ist - diese Größe ist fest und absolut.
Jeder Prozess erhält einen eigenen Stack.

Der Kernel-Stack enthält auch einen Zeiger auf die thread_info-Struktur, die Informationen über den Thread enthält.

3
arenard