Obwohl der größte Teil des Codes im Linux-Kernel in C geschrieben ist, gibt es immer noch viele Teile dieses Codes, die für die Plattform, auf der er ausgeführt wird, sehr spezifisch sind und dies berücksichtigen müssen.
Ein besonderes Beispiel hierfür ist der virtuelle Speicher, der auf den meisten Architekturen (Hierarchie von Seitentabellen) auf ähnliche Weise funktioniert, jedoch für jede Architektur spezifische Details enthält (z. B. die Anzahl der Ebenen in jeder Architektur, und dies hat sogar auf x86 mit zugenommen Einführung neuer größerer Chips.) Mit dem Linux-Kernelcode werden Makros eingeführt, die das Durchlaufen dieser Hierarchien ermöglichen. Diese können vom Compiler auf Architekturen mit weniger Seitentabellenebenen entfernt werden (sodass der Code in C geschrieben wird, aber Details zur Architektur berücksichtigt) Berücksichtigung.)
Viele andere Bereiche sind für jede Architektur sehr spezifisch und müssen mit archspezifischem Code behandelt werden. Meist handelt es sich jedoch um Code in Assemblersprache. Beispiele sind:
Kontextumschaltung : Bei der Kontextumschaltung wird der Wert aller Register für den zu schaltenden Prozess gespeichert und die Register aus dem gespeicherten Satz des geplanten Prozesses in der CPU wiederhergestellt. Sogar die Anzahl und der Satz von Registern sind für jede Architektur sehr spezifisch. Dieser Code wird normalerweise in der Assembly implementiert, um den vollständigen Zugriff auf die Register zu ermöglichen und um sicherzustellen, dass er so schnell wie möglich ausgeführt wird, da die Ausführung der Kontextumschaltung für das System kritisch sein kann.
Systemaufrufe : Der Mechanismus, mit dem der Userspace-Code einen Systemaufruf auslösen kann, ist in der Regel spezifisch für die Architektur (und manchmal sogar für das jeweilige CPU-Modell, z. B. haben Intel und AMD unterschiedliche Anweisungen dafür eingeführt, ältere CPUs verfügen möglicherweise nicht über diese Anweisungen denn die werden immer noch einzigartig sein.)
Interrupt-Handler : Details zur Behandlung von Interrupts (Hardware-Interrupts) sind in der Regel plattformspezifisch und erfordern in der Regel einen Klebstoff auf Assembly-Ebene, um die für die Plattform verwendeten spezifischen Aufrufkonventionen zu handhaben. Grundelemente zum Aktivieren / Deaktivieren von Interrupts sind in der Regel plattformspezifisch und erfordern auch Assembler-Code.
Initialisierung : Details darüber, wie die Initialisierung erfolgen soll, umfassen in der Regel auch Details, die für die Plattform spezifisch sind und häufig Assembler-Code erfordern, um den Einstiegspunkt für den Kernel zu verwalten. Auf Plattformen mit mehreren CPUs (SMP) sind Details zum Onlineschalten anderer CPUs in der Regel ebenfalls plattformspezifisch.
Sperrprimitive : Die Implementierung von Sperrprimitiven (wie Spinlocks) umfasst in der Regel auch plattformspezifische Details, da einige Architekturen unterschiedliche CPU-Anweisungen bereitstellen (oder bevorzugen), um diese effizient zu implementieren. Einige implementieren atomare Operationen, einige stellen ein cmpxchg bereit, das atomar getestet / aktualisiert werden kann (aber fehlschlägt, wenn ein anderer Writer zuerst eintritt), andere enthalten einen "Lock" -Modifizierer für CPU-Anweisungen. Dazu gehört häufig auch das Schreiben von Assembly-Code.
Es gibt wahrscheinlich andere Bereiche, in denen plattform- oder architekturspezifischer Code in einem Kernel (oder speziell im Linux-Kernel) benötigt wird. Im Kernel-Quellbaum gibt es architekturspezifische Teilbäume unter arch/
und unter include/arch/
denen Sie mehr finden Beispiele dafür.
Einige sind tatsächlich überraschend, zum Beispiel werden Sie feststellen, dass die Anzahl der für jede Architektur verfügbaren Systemaufrufe unterschiedlich ist und einige Systemaufrufe in einigen Architekturen und nicht in anderen vorhanden sind. (Auch unter x86 unterscheidet sich die Liste der Systemaufrufe zwischen einem 32-Bit- und einem 64-Bit-Kernel.)
Kurz gesagt, es gibt viele Fälle, bei denen ein Kernel sich bewusst sein muss, dass sie für eine Plattform spezifisch sind. Der Linux-Kernel versucht, die meisten dieser Algorithmen zu abstrahieren, sodass Algorithmen höherer Ebenen (z. B. die Funktionsweise von Speicherverwaltung und -planung) in C implementiert werden können und auf allen Architekturen gleich (oder größtenteils gleich) funktionieren.