Hallo,
kann mir jemand eine gute Lektüre + passenden RPi-Bausatz empfehlen, um
schnell in das Thema "Embedded Linux" einzusteigen? Am besten wäre es
wenn man C++ darauf programmiert/kompiliert. Evtl auch mal den Kernel
updaten.
Embedded Programmierung generell kann ich schon - nur bisher nicht auf
Linux Systemen.
Moin,
LFS-Book und BLFS-Book.
Dabei kommt zwar kein unbedingt "embedded-Linux" raus, aber man kann
doch mal lernen, wie das alles zusammenhaengt und funktioniert.
Gruss
WK
In meinem Sprachgebrauch hat ein RPi nicht unbedingt was mit embedded
Linux zu tun. Für "echtes" embedded Linux würde ich zumindest einen
RT-Kernel erwarten.
Auf den Pi's läuft ein "ganz normales" Linux (bloß halt auf einem ARM
anstatt auf einem PC). Wenn man lernen will, wie man damit umgeht (und
nicht unbedingt ein Buch braucht), sind die Seiten der RPI Foundation
m.E. dafür geeignet und ausreichend (z.B.):
https://curriculum.raspberrypi.org/physical-computing/creator/
Markus F. schrieb:> Auf den Pi's läuft ein "ganz normales" Linux
Sehe ich auch so. Den Kernel würde ich nur updaten, wenn ich dazu einen
guten Grund habe. Normalerweise übernimmt der Linux Distributor diese
Aufgabe.
Wenn du irgendwelche Anleitungen auf der Rasberry Pi Seite vermisst,
dann schau bei Ubuntu oder Debian nach. Diese beiden Distributionen
ähneln dem Rasbian sehr, und beide geben sich beide viel Mühe mit der
Doku.
Hier ist die Anleitung von Ubuntu für das Bauen eines eigenen Kernels:
https://wiki.ubuntuusers.de/Kernel/Kompilierung/
Um Linux richtig kennen zu lernen und zum Kernel kompilieren reicht auch
ein normaler PC.
Nehme deinen PC, lösche das Windows und arbeite ein Jahr nur mit Linux.
Dann bist du bereit für mehr. Denn in dem Jahr hast du so viel gelernt,
dass du Linux dann auch auf kleineren Prozessoren benutzen kannst.
PittyJ schrieb:> Nehme deinen PC, lösche das Windows
Linux und Windows können beide zusammen installiert sein. Sogar
Microsoft hat inzwischen gelernt, nicht bei jedem Update alle anderen
Betriebssysteme zu deaktivieren.
PittyJ schrieb:> Dann bist du bereit für mehr. Denn in dem Jahr hast du so viel gelernt,> dass du Linux dann auch auf kleineren Prozessoren benutzen kannst.
Dann aber mit Arch oder Gentoo Linux, weil man dann früher oder später
gezwungen ist irgendwas zu reparieren ;-)
Stefanus F. schrieb:> Linux und Windows können beide zusammen installiert sein.
Aber dann könnte man aus Faulheitsgründen "versehentlich" Windows
benutzen...
Dr. Sommer schrieb:> Dann aber mit Arch oder Gentoo Linux, weil man dann früher oder später> gezwungen ist irgendwas zu reparieren ;-)
Da ist was dran. Bei Ubuntu und Debian ist meine Strategie eher: Wenn
etwas nicht funktioniert, warte ein paar Wochen. Wenn es dann immer noch
nicht geht, suche nach Hilfe.
Es ist dort wirklich so, dass die allermeisten gravierenden Probleme
rasche von den Entwicklern und Distributoren gelöst werden. Ich habe den
Eindruck, dass das dort sogar einen Tick besser läuft, als bei Windows.
Stefanus F. schrieb:> Da ist was dran.
Durch Schmerz lernt man doch am Besten ;-) Ich habe schlauerweise auch
mit Gentoo angefangen (weil cool™) ohne jegliche Ahnung davon zu haben -
durch die nötige Bastelei habe ich dann einige Erfahrungen gesammelt...
Mittlerweile nehm ich aber auch Linux Mint weil ich keine Lust mehr habe
alle 3 Tage irgendwelche Paket-Konflikte aufzulösen...
Linuxxer schrieb:> Am besten wäre es> wenn man C++ darauf programmiert/kompiliert.
Das ist unter Linux zum Glück ganz einfach:
Dr. Sommer schrieb:> Das ist unter Linux zum Glück ganz einfach...
Und jetzt erkläre mal einem Teenager jedes einzelne Zeichen. Dann läuft
der/die schreiend weg und wird nie wieder programmieren wollen. So
sichern wir unseren Job :-)
Moin,
Einen hab' ich noch:
http://librta.org/book.html
Ansonsten wuerd' ich sagen, dass bei einem embedded linux solche Sachen
wie:
* Das Ding zu jedem Zeitpunkt vom Strom trennen koennen, ohne dass ein
Filesystem oder dessen Datentraeger kaputt geht.
* DAU tauglicher Update (Statt setup.exe anklicken nur "sudo apt-get
gedoens" tippern zu muessen ist nicht embedded-tauglich, wie soll das
auch gehen, ohne Tastatur/Monitor?)
* Anpassungen von Kernel und Driver auf die eigene Hardware, wenn's nix
von der Stange ist.
die entscheidenden Punkte sind.
Gruss
WK
Stefanus F. schrieb:> Dr. Sommer schrieb:>> Das ist unter Linux zum Glück ganz einfach...>> Und jetzt erkläre mal einem Teenager jedes einzelne Zeichen. Dann läuft> der/die schreiend weg und wird nie wieder programmieren wollen. So> sichern wir unseren Job :-)
Hier der Lehrplan für die 2te Woche:
https://de.m.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest
(um den TeufelsCreis zu brechen verzichte ich den Link zur Wikiseite auf
Srpski zu setzen)
Linuxxer schrieb:> Evtl auch mal den Kernel updaten.
Bei einer gut unterstützten Platform wie dem RPi besteht aufgrund des
guten Supports durch die bekannten Distributoren dazu meist kein Grund.
Kernel Updates kommen da direkt vom Distributor über den Package manager
zusammen mit all den anderen Updates.
Bei Plattformen, die vom Mainline Kernel https://www.kernel.org/
unterstützt werden, ist es ziemlich einfach, den Kernel selbst zu
kompilieren. Zuerst braucht man eine Konfig, in der die benötigten
Treiber für das System eingeschaltet sind. Wenn man schon eine hat, kann
man die in das /.config file im den Kernel sourcen kopieren. mit "make
menuconfig" kann man das dann noch anpassen.
Für diverse Boards gibt es bereits fertige im tree. Bei ARM z.B:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/configs
Bei ARM64 ist die Auswahl noch etwas entteuschend:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/configs
Man kann die ganze Liste der vordefinierten Configs mit "make ARCH=arm
help | grep defconfig" anschauen.
Die Configs können dan mit "make ARCH=arm defconfig
KBUILD_DEFCONFIG=name_der_defconfig" verwendet werden, um daraus die
.config zu erstellen. Um aus der .config wieder eine _defconfig zu
erstellen, kann man "make ARCH=arm savedefconfig" verwenden.
Das "ARCH=arm" ist nur nötig, wenn man cross compiliert. Wenn man den
Kernel auf dem Zielsystem kompiliert, kann man es weglassen. Dort kann
man, wenn man alle nötigen Module schon geladen hat, die Config dann
auch mit "make localyesconfig" oder "make localmodconfig" für eine
Minimalconfig erstellen.
Neben localdefconfig gibt es noch oldconfig (bestehende Konfig nehmen
und bei neuen Optionen nachfragen), defconfig (default config für
Architektur) und config (alle Optionen nachfragen, das dauert ein paar
Stunden bis Tage, wenn man alle durchliest.). Bei embeded Boards ist es
aber oft so, dass man gewisse Sachen für ein Spezifisches Board ein oder
ausstellen muss, speziell bei solchen wo man die nötigen Config Optionen
nicht kennt ist das nervig, und viele Boards und Treiber sind noch nicht
in Mainline. Hersteller von embeded Boards oder Smartphones haben oft
eigene Forks des Kernels, bis die Anpassungen in Mainline ankommen,
falls der Hersteller die überhaupt je einsendet kann es ewig dauern. In
dem Fall muss man den dann erstmal finden.
Zum kompilieren kann man dann einfach "make" eingeben. Beim Cross
compilieren muss man die Architektur und den Kompiler noch mitgeben,
also z.B. "make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-" oder "make
ARCH=arm CROSS_COMPILE=arm-linux-gnu-". Den jeweiligen Kompiler muss man
natürlich auch noch installiert haben. Für bekannte Distributionen, wie
z.B. Debian-basierte gibt es noch Targets, die den Kernel in Packete für
die Distribution verpackt. unter Debian wäre das z.B. "deb-pkg". Das
ganze Kommando währe dann also z.B. "make ARCH=arm64
CROSS_COMPILE=aarch64-linux-gnu-".
Das boot verfahren ist je nach Architektur, CPUs und Boards auch sehr
verschieden. Beim RPI z.B. wird der Kernel vom Grafikchip geladen!!!
Die meisten ARM Boards verwenden uboot um den Kernel zu laden. Dort ist
auch sehr vieles board spezifisch. Neuere Boards, besonders solche mit
arm64 Architektur benötigen gewisse Initialisierung schritte, die uboot
nicht enthält, und verwenden deshalb arm-trusted-firmware dafür als
first-stage bootloader, der dan uboot als second stage bootloader lädt,
der dann den Kernel lädt. Die arm-trusted-firmware (ATF) enthält auch
mechanismen, über die die Signatur der Bootloader mit einem Zertifikat
in einem Rom beim Boot verifiziert werden kann, und ist damit direkt
mitverantwortlich, dass man bei fast allen Smartphones als
Smartphonebesitzer den Bootloader usw. nicht ersetzen kann, also man
sein Eigentum nicht voll unter Kontrolle hat, was ich eine riesen
Schweinerei finde. Wie schwer wäre es gewesen, einen internen EEPROM
stat ROM zu nehmen, und einen Mechanismus zum Austausch der Zertifikate
der Benutzer einzubauen? Aber ich komme vom Thema ab. Wie die ATF
geladen wird, da bin ich auch noch überfragt.
Während bei PCs mit PCI und ACPI usw. die Hardware ermittelt werden
kann, verwendet Android andere Verfahren. Es werden device trees files
verwendet. Diese kommen in diversen Formen, können von uboot von einem
File geladen werden, in uboot mit ein kompiliert werden, in den Kernel
mit ein kompiliert werden, von uboot verändert werden, und uboot und der
Kernel können unterschiedliche device trees haben. In der regel braucht
man einfach eins, das zum Board passt. Bei uboot gibt es dann noch
diverse Möglichkeiten einzustellen, wie der Kernel geladen wird. Man
kann ein Script schreiben und mit uboot-mkimage in ein uboot script
umwandeln, oder die fest Einkompilieren, und vieles mehr.
Dann noch zum Starten des Systems durch den Linux kernel. in einer
intird oder initramfs wird in der regel zuerst /init mit pid 1
gestartet. Diese mounten dann die Dateisysteme und sstarten das
eigentliche init, wieder mit pid 1, mit einem exec in /init. Wird ohne
initrd/initramfs gebooted startet der Kernel statdessen /sbin/init,
/etc/init, /bin/init oder /bin/sh, jenachdem, welches er in der
Reihenfolge zuerst findet.
Der init Prozess kann auch ein Script sein. Es gibt 4 Arten, wie unter
Linux ein Programm gestartet werden kann.
1) Ein Script gibt das Program, welches dieses interpretiert, mit der
Shebang Zeile ganz am Anfang an, z.B. "#!/bin/bash" oder "#! /bin/sh"
oder "#! /bin/sh -l ". Der Abstand zwischen #! und dem Kommando wird
ignoriert. Es ist maximal ein zusätzliches Argument möglich. Das
Programm wird dann mit "/angegebenes/program argument_falls_vorhanden
pfad/mit/dem/das/script/gestartet/wurde" gestartet.
2) Bei statisch gelinkten Programmen wird das Programm in den Speicher
gemappt und direkt gestartet.
3) Bei dynamisch gelinkten elf Programmen gibt es eine .interp section,
die ein program/library angibt die statdessen vom kernel geladen wird,
und dann das eigentliche Programm in den Speicher mapt und ausführt. Das
ist der dynamic linker/loader, auch bekannt als ld.so.
4) Mit dem binfmt_misc Mechanismus kann man beliebige Dateiformate
anhand von magic numbers oder extension usw. mit einem interpreter
starten lassen. Damit kann man z.B. windows .exe direkt über wine
ausführbar machen ohne explizit "wine bla.exe" angeben zu müssen, oder
man kann es konfigurieren qemu-aarch64-static bei arm Binaries zu
verwenden, wodurch man diese dann direkt ausführen kann. So sind sogar
Chroots und Container mit komplett anderer Architektur möglich.
Unabhängig davon, welches verfahren verwendet wird, müssen beim Starten
einer Anwendung die Interpreter, Libraries und Loader einfach alle
vorhanden sein. Bei statischen Programmen hat man den Vorteil, dass man
sich um die verwendeten Libs keine Gedanken machen muss. Das einrichten
der ganzen build toolchain für eine eigene Distribution kann sehr
aufwendig sein.
Beim manuellen einrichten von Distributionen oder Images von einem
anderen System aus haben eigentlich alle Distributionen Tools und
verfahren das Bootstrapping zu vereinfachen. Gentoo bietet diverse
Tarballs an, die genug Tools beinhalten den rest zu compilieren und zu
emergen. Debian hat debootstrap, welches die wichtigsten Packete
herunterzuladen und zu entpacken. Auf diese weise kann man einfaches
Rootfs erstellen.
Linuxxer schrieb:> Am besten wäre es wenn man C++ darauf programmiert/kompiliert.
Will man aber nur eine bestehende Distro anpassen, kann man all das
ignorieren. Dann nimmt man einfach die Distro und ändert was auch immer
man will. Bei C++ installiert man halt g++, oder wenn amn cross
compillieren will halt den aarch64-linux-gnu-g++ oder arm-linux-gnu-g++,
je nachdem, was man vor hat.
Markus F. schrieb:> In meinem Sprachgebrauch hat ein RPi nicht unbedingt was mit embedded> Linux zu tun. Für "echtes" embedded Linux würde ich zumindest einen> RT-Kernel erwarten.
Embedded ≠ RT.
Eine eigene Frage?
Dieser Thread ist über 7 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.