Zuletzt aktualisiert am 2. September 2026
Übersicht
Bei der Entwicklung von Embedded-Linux-Systemen mit dem Yocto Project® und OpenEmbedded ist zu beachten, dass die Optimierung in der Regel anhand von zwei unterschiedlichen Dimensionen gemessen wird: dem nichtflüchtigen Flash-Speicher und dem physischen RAM zur Laufzeit. Auch wenn eine kompilierte Anwendung im Root-Dateisystem unglaublich klein erscheint, kann sich ihr tatsächlicher Einfluss während der Systemausführung ganz anders darstellen. In dieser Studie untersuchen wir ein klassisches kompiliertes Beispiel – 95.01_hello-cpp – eingehend, um sowohl den Speicher-Overhead im Root-Dateisystem (rootfs) als auch den physischen Speicherbedarf auf dem Zielsystem gründlich zu analysieren. Für diese Untersuchung kombinieren wir die Verfolgung von Flash-Speicheränderungen mit der Low-Level-Verfolgung von Kernel-Systemaufrufen.
Code
hello-cpp_1.0.bb:
DESCRIPTION = "Simple helloworld application"
SECTION = "examples"
SUMMARY = "Simple helloworld application"
HOMEPAGE = "https:/www.ReliableEmbeddedSystems.com"
RECIPE_MAINTAINER = "Robert Berger <Robert.Berger@ReliableEmbeddedSystems.com>"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=1d10f40055ab4fb8f37eb56febff1d19"
SRCREV = "5669bcd6894a27e95454aadcea57054dd11b7612"
# upstream:
SRC_URI = "git://gitlab.com/exempli-gratia/hello-cpp.git;protocol=https;branch=master"
do_compile() {
${CXX} hello-cpp.cpp ${CFLAGS} ${LDFLAGS} -o hello-cpp
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello-cpp ${D}${bindir}
}
hello-cpp.cpp:
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world from C++ "<< endl;
return 0;
}
Wichtigste Erkenntnisse
- Das mikroskopische Blitzprofil:
- Auf Flash ist die C++-Binärdatei stark optimiert und benötigt nur eine winzige komprimierte Paketgröße von 3.000 Byte. Sie vergrößert das endgültige Rootfs-Layout um lediglich 84 KB.
- Die Rückstände der Deinstallation:
- Selbst beim Entfernen einfacher Anwendungspakete können „Geister“-Artefaktdateien zurückbleiben. Bei einer Standard-Deinstallation verbleibt ein dauerhafter Datenmüll von 8 KB in den Verzeichnissen /etc und den opkg-Statusverfolgungsverzeichnissen.
- Die C++-Laufzeitumgebung Premium:
- Trotz des geringen Speicherbedarfs erfordern das Laden der Abhängigkeiten und die Initialisierung der C++-Standardinfrastruktur genau 2,30 MB an tatsächlichem, physischem Ziel-RAM.
Fallstudie: 95.01_hello-cpp – Ressourcenkennzahlen
Die Bewertung einer Anwendung ausschließlich anhand ihrer Binärdateigröße führt zu erheblichen blinden Flecken bei der Planung der Embedded-Architektur. Nachfolgend finden Sie einen mehrdimensionalen Überblick darüber, wie eine einfache kompilierte Laufzeitumgebung den Flash-Speicher und den Arbeitsspeicher des Zielsystems belegt.
Auswirkungen auf den Speicherbedarf des Root-Dateisystems (rootfs)
| Metrisch | Wert |
|---|---|
| Größe der komprimierten .ipk-Datei | 3.000 Byte |
| Laufzeitabhängigkeiten (RDEPENDS) | libc6, libstdc++6 |
| Gesamtzuwachs der Rootfs-Größe (Delta) | +84 KB |
Nach der (De-)Installation
| Metrisch | Wert |
|---|---|
| Delta nach der Installation des Standardpakets | +84 KB |
| Nach der Deinstallation des Pakets verbleibende Delta-Dateien | +8 KB |
| Dauerhaft verbleibender Datenmüll (Flash Bloat) | 8 KB |
Profil des physischen Arbeitsspeichers zur Laufzeit
| Analysekennzahl | Speicherbedarf |
|---|---|
| Echte physische Heap-Zuweisung (brk) | 2,14 MB |
| Sofort aktive Karten (mmap) | 0,07 MB |
| Aktivierungspfade des Linkers (mprotect) | 0,10 MB |
| GESCHÄTZTER TATSÄCHLICHER ZIELWERT FÜR DEN RAM-VERBRAUCH | 2,30 MB |
| Ignorierte Zuweisungen virtueller Adressen | 5,55 MB |
Technische Zusammenfassung: Speicherrückstände und Kernel-Telemetrie
1. Das Speicherproblem: Warum bleiben Flash-Datenrückstände zurück?
Bei der Ausführung von „opkg remove –autoremove && opkg clean“ wird der ursprüngliche Zustand des Dateisystems nicht vollständig wiederhergestellt. Der zusätzliche permanente Speicherbedarf von 8 KB im Flash-Speicher ist auf Folgendes zurückzuführen:
- Der lokale interne Paketmanager speichert Änderungen in /var/lib/opkg/status.
- In bestimmten Dateien des Laufzeitsystems, wie beispielsweise /etc/ld.so.cache, ist ein leichter Anstieg der Datenmenge zu verzeichnen.
- OpenEmbedded enthält Sicherheitsmechanismen, die Konfigurations-Baselines im Verzeichnis /etc gezielt erhalten.
2. Das Laufzeit-Dilemma: Eine Analyse der Telemetriedaten von Systemaufrufen
Durch die Profilierung der Programmausführung mithilfe von perf record, protokollieren wir die genauen Interaktionen zwischen dem Linux-Speicherverwaltungssubsystem und der kompilierten Anwendungsdatei:
perf record -e syscalls:sys_enter_mmap -e syscalls:sys_enter_mprotect -e syscalls:sys_exit_brk -- hello-cpp
Hello world from C++
[ perf record: Captured and wrote 0.008 MB perf.data (31 samples) ]
Durch die Auswertung dieses Rohprotokolls mit unserem Skript„perf-calc-python3.py“werden inaktive Kernel-Maps herausgefiltert, um drei wichtige Ressourcenindikatoren zu extrahieren:
Tatsächliches Heap-Wachstum (brk): 2,14 MB
Hiermit wird die genaue Menge an physischem Speicher erfasst, die auf das Hauptheap-Segment des Systems abgebildet ist. Das Binärausführungsprotokoll erfasst aufeinanderfolgende Grenzen von Zuweisungsblöcken:
hello-cpp 1550: syscalls:sys_exit_brk: 0xaaaadc9dd000
hello-cpp 1550: syscalls:sys_exit_brk: 0xaaaadcc00000
Dieser Mehr-Megabyte-Heap-Aufwand ist die unvermeidliche Startgebühr des Sprachökosystems. Die C++-Standardbibliothek erstellt daher Standard-Kernabstraktionen, instanziiert anschließend globale Ein-/Ausgabepuffer (wie z. B. ), ordnet Tabellen für die Laufzeitausnahmebehandlung zu und organisiert schließlich interne statische Komponenten – und zwar in der Millisekunde, in der die Anwendung ihren Ausführungsweg betritt.
„Immediate Active Maps“: 0,07 MB
Diese stehen für physical maps: anonym, beschreibbar. Sie werden über mmap instanziiert, auf das während des Ausführungsdurchlaufs global zugegriffen werden kann. Da unsere Arbeitslast zudem streng single-threaded ist, wird der Overhead des mehrere Megabyte großen Thread-Stacks praktisch vollständig umgangen, wodurch dieser Pool minimal gehalten wird.
Über mprotect aktiviert: 0,10 MB
Dadurch werden anschließend virtuelle Blöcke registriert, die von den ersten Sicherheitsschichten als unzugänglich markiert worden waren, später jedoch in Laufzeitberechtigungen überführt wurden:
hello-cpp 1550: syscalls:sys_enter_mprotect: start: 0xffffadcff000, len: 0x00011000, prot: 0x0001
Da 95.01_hello-cpp von einer dynamischen gemeinsamen Infrastruktur (libstdc++.so, libm.so und libc.so) abhängt, muss der dynamische Linker (ld.so) die Berechtigungen für Speicherseiten aktiv überschreiben, um Referenzen auszuführen und Pfade zu statischen Variablen über globale Arrays hinweg herzustellen.
Ignorierter virtueller Speicherplatz: 5,55 MB (herausgefiltert)
Das Tracing-Tool markiert und verwirft absichtlich 5,55 MB an Speicherdefinitionen, die mit PROT_NONE (prot: 0x00000000) gekennzeichnet sind. Linux reserviert riesige, zusammenhängende Adressblöcke, um die gemeinsam genutzten Bibliotheken sicher unterzubringen, ohne den Systemspeicher zu fragmentieren. Da es keine physischen RAM-Chips gibt, die diese Zuweisung unterstützen, entsteht dadurch keinerlei strukturelle Belastung für Ihre Hardware-Zielplatine.
Praktische Schlussfolgerung
Die architektonische Analyse von 95.01_hello-cpp liefert eine wichtige Erkenntnis für den Entwurf kundenspezifischer eingebetteter Linux-Plattformen: Die Größe von Binärpaketen ist äußerst irreführend. Was den reinen Speicherbedarf angeht, ist eine kompilierte C++-Routine daher eine äußerst optimierte Wahl, da sie den Speicherbedarf eines Zielgeräte-Layouts vom Typ „Core Image Minimal“ um weniger als 100 KB erhöht.
Allerdings muss Ihre physische Hardware so ausgelegt sein, dass sie den unvermeidbaren Speicherbedarf der Standardbibliothek zur Laufzeit bewältigen kann. Die physische Zielhardware muss mindestens 2,30 MB aktiven Speicher bereitstellen, allein um Code-Abhängigkeiten zu laden und grundlegende Datenausgabepfade zu öffnen. Bei der Konzeption von Hardwaremodulen mit strengen Beschränkungen im Bereich weniger Megabyte müssen Plattformingenieure das Flash-Budget stets gegen die Initialisierungstabellen des dynamischen Linkers abwägen.
Verwandte Links
- Der Speicherbedarf von „Hello World“: Ein Vergleich der Paketabhängigkeiten von Yocto
- Der Flash-Speicherbedarf von „Hello World“: Ein Vergleich der Yocto-Paketabhängigkeiten
- Der RAM-Bedarf von „Hello World“: Ein Vergleich des Speicherverbrauchs von Yocto zur Laufzeit
- Prelink(2) - Zeit + Speicher = Geld
Anhang
Um zu erfahren, wie „ Embedded-Linux“ funktioniert, klicken Siehier. Um mehr über das Yocto Project® zu erfahren, klicken Siehier.