Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Kapitel 02: Einrichtung & Erstes Programm (Hardware- & Systemsicht)

Dieses Kapitel analysiert die physikalischen Abläufe der Rust-Compilation, die Statik der Linker-Infrastruktur, die Funktionsweise von Hardware-Entropiequellen und Optimierungen der Binärgröße.

1. Lernziele

Sie werden in diesem Abschnitt:

  • Die Übersetzungsschritte von Rust-Sourcecode über LLVM IR zu nativem Maschinencode nachvollziehen.
  • Den Unterschied zwischen statischem und dynamischem Linken analysieren.
  • Verstehen, wie der Zufallszahlengenerator auf CPU-Instruktionen (RDRAND/RDSEED) zugreift.
  • Techniken zur Minimierung der Binärgröße (Stripping, Panic-Verhalten) anwenden.

2. Die Rust-Kompilierungspipeline (LLVM)

Der Rust-Compiler rustc übersetzt den Code nicht direkt in Maschinencode, sondern nutzt das LLVM-Compiler-Backend:

[Rust Quellcode] 
      │ (rustc Frontend)
      ▼
[HIR / MIR (Mid-level Intermediate Representation)]
      │ (Transkription zu LLVM)
      ▼
[LLVM IR (Plattformunabhängiger Zwischencode)]
      │ (LLVM Optimierungs-Passes)
      ▼
[Plattformspezifischer Maschinencode (x86_64, ARM, etc.)]
  • MIR (Mid-level IR): Hier führt Rust seine Typsicherheits- und Borrow-Checker-Prüfungen durch. Das MIR ist stark vereinfacht und ideal für Programmanalysen.
  • LLVM IR: LLVM führt die hardwarenahen Optimierungen durch (z. B. Vektorisierung, Loop-Transformationen und Inlining).

3. Statisches Linken vs. Dynamisches Linken

Wenn Sie ein Standard-Rust-Programm kompilieren, ist das resultierende Binär-Artefakt vergleichsweise groß (oft mehrere Megabytes für ein einfaches Programm).

Der Grund: Rust linkt standardmäßig statisch.

  • Statisch: Alle benötigten Standardbibliotheken (std) und externen Abhängigkeiten (wie das rand-Crate) werden direkt in das finale Executable hineinkopiert. Das Programm läuft auf dem Zielrechner ohne externe Abhängigkeiten (keine Fehlermeldungen über fehlende .so- oder .dll-Dateien).
  • Dynamisch: Bei C/C++ oder Sprachen, die auf Systembibliotheken vertrauen, verweist das Executable nur auf externe Bibliotheken im Betriebssystem. Fehlen diese auf dem Zielsystem, stürzt das Programm ab.

4. Hardware-Entropie unter der Haube

Wenn wir rand::thread_rng() aufrufen, greift Rust auf Betriebssystem-Schnittstellen zurück, die wiederum Hardware-Entropiequellen abfragen:

  • Linux: Zugriff auf /dev/urandom oder den Systemaufruf getrandom().
  • CPU-Instruktionen: Moderne Prozessoren bieten integrierte Zufallsgeneratoren, die auf thermischem Rauschen basieren. LLVM übersetzt die Zugriffe bei aktivierten CPU-Features direkt in native Instruktionen wie RDRAND (liest eine hardwaregenerierte Zufallszahl) oder RDSEED (erzeugt einen Seed für Software-Generatoren).

5. Binärgrößen-Optimierung auf Systemebene

Für Embedded-Systeme oder WebAssembly-Targets ist die Standard-Binärgröße oft zu hoch. Folgende Stellschrauben in der Cargo.toml reduzieren die Größe drastisch:

[profile.release]
strip = true       # Entfernt alle Debug-Symbole und Symboltabellen aus der Binärdatei
opt-level = "z"    # Optimiert primär auf Binärgröße, nicht auf Ausführungsgeschwindigkeit
panic = "abort"    # Deaktiviert das Stack-Unwinding. Reduziert den Fehlerbehandlungscode.
  • Strip: Entspricht dem manuellen Ausführen des System-Befehls strip target/release/wuerfelspiel.
  • Panic Abort: Im Fehlerfall stürzt das Programm sofort ab, anstatt den Stack geordnet abzubauen (Unwinding). Das spart viel Boilerplate-Code im Compiler-Ausgabe-Artefakt.

6. Key Takeaways (Systemebene)

  • LLVM IR ermöglicht es Rust, hochoptimierten Maschinencode für Dutzende von CPU-Architekturen zu generieren.
  • Statisches Linken erhöht die Binärgröße, garantiert aber die absolute Portabilität des Kompilats.
  • Hardware-Zufall wird über CPU-spezifische Opcodes (RDRAND) realisiert, die durch OS-Entropie-Abfragen geschützt sind.