Linux auf eine andere Plattform portieren [closed]

28

Ich weiß, dass Linux verfügbar ist und für viele verschiedene Plattformen wie X86, ARM, PowerPC usw. portiert wurde.

Was ist jedoch in Bezug auf die Portierung genau erforderlich?

Ich verstehe, dass Linux Software ist, die in C geschrieben wurde. Wenn Sie also Linux ursprünglich von X86 nach ARM oder andere portieren, müssen Sie dann nicht nur den Code mit dem Compiler für die spezifische Zielarchitektur neu kompilieren?

Abgesehen von den Gerätetreibern für verschiedene Peripheriegeräte müsste bei der Portierung von Linux auf eine neue Architektur noch etwas getan werden. Kümmert sich der Compiler nicht um alles?

Engineer999
quelle
11
Können wir annehmen, dass Sie sich die architekturspezifischen Kernelquellen angesehen haben? git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/…
Kusalananda

Antworten:

57

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.

filbranden
quelle
7
Sehr schöne Nachricht! Die Variation in der Anzahl der Systemaufrufe hängt hauptsächlich mit dem Verlauf zusammen: Neue Ports enthalten die zum Zeitpunkt des Ports gültigen Systemaufrufe. Sie stören nicht das in älteren Häfen vorhandene historische Gepäck, sodass veraltete Systemaufrufe in der Regel nicht in den Häfen vorhanden sind neuer als die Abwertung. (Das deckt nicht alle Szenarien ab ...)
Stephen Kitt
10

Zusätzlich zur Portierung des Linux-Kernels müssen Sie die Application Binary Interface (ABI) für "User Space" -Programme definieren und die untersten Schichten des User Space-Software-Stacks portieren. Linux wird normalerweise mit Low-Level-User-Space-Komponenten aus dem GNU-Projekt verwendet, von denen die kritischsten sind:

  • Der C-Compiler, Assembler und Linker: GCC- und GNU-Binutils . Für eine völlig neue CPU-Architektur müssen Sie diese Software portieren, bevor Sie überhaupt mit der Portierung des Kernels beginnen, da der Kernel selbst ein C-Programm ist und kompiliert werden muss. Wenn es für die CPU Ihrer Plattform bereits Back-End-Unterstützung gibt, jedoch nicht für Linux als Betriebssystemkernel, müssen Sie erheblich weniger Arbeit leisten, und Sie können möglicherweise den größten Teil der Arbeit verschieben, bis der Kernel aktiv ist Laufen.
  • Die C-Laufzeitbibliothek: " GNU libc ". Diese Bibliothek enthält den Code, der Systemaufrufe ausführt und ansonsten direkt mit dem Kernel interagiert.
  • Die Bibliothek "Foreign Function Interface" ( Fremdfunktionsschnittstelle) , libffi , die ein wesentlicher Bestandteil vieler Hochspracheninterpreter ist und eine der wenigen verbleibenden Aufgaben ausführt, für die ein geringer Teil der handgeschriebenen Assemblersprache erforderlich ist.

Viele andere Softwareteile verfügen optional über plattformabhängige Komponenten. Das Surfen im Internet ist beispielsweise wesentlich schneller, wenn Sie handoptimierte kryptografische Grundelemente für NSS und OpenSSL für Ihre neue CPU-Architektur und Back-Ends für die Just-in-Time-Kompilierung für IonMonkey und V8 schreiben . Dies ist jedoch nicht unbedingt erforderlich, um eine neue Plattform aufzurufen.

zwol
quelle
1

Sie müssen dem Kernel mitteilen, auf welche Hardware Sie portieren. Der Kernel hat die Aufgabe, eine direkte Schnittstelle zur Hardware herzustellen. Damit der Kernel ordnungsgemäß funktioniert, muss er über die CPU, die Oszillatoren (Uhren) und alle Peripheriegeräte wie die verschiedenen Arten von seriellen Ports (SPI, CAN, I2C usw.).

Früher haben Sie dazu plattformspezifischen Code geschrieben, mit dem die Treiber dann funktionieren. In diesen Tagen geschieht dies durch Schreiben einer Gerätebaumdefinition .

Badeente
quelle