Read Only Real-Time Linux: Eine Beispielumsetzung für den Raspberry Pi

More
4 years 11 months ago - 4 years 9 months ago #49 by Rainer Poisel
Kurzfassung

In einem der letzten Artikel wurde erläutert, wie ein echtzeitfähiger Linux-Kernel erstellt werden kann. Darauf aufbauend soll das System derart modifiziert werden, dass nie auf die eingebundenen Datenträger, wie z. B. die SD-Karte geschrieben wird. Natürlich ist es möglich persistente Datenspeicher einzubinden, auf denen Daten dauerhaft abgelegt werden können.

Als Nebeneffekt wird gezeigt, wie binäre Dateien fremder Architekturen auf dem lokalen System ausgeführt werden können. Im konkreten Fall werden Binaries für die ARM-Architektur auf einem x86_64 System ausgeführt.

Hinweis: Nutzung des Tutorials, sowie des Beispiel-Abbilds bitte auf eigene Gefahr. Ich habe die Beschreibung nach bestem Wissen und Gewissen ausgeführt, übernehme jedoch keine Haftung bei Nutzung, Nachmachen, usw.!

Übrigens: Alle Kommandos, mit Ausnahme der gekennzeichneten, können ohne Root-Rechte ausgeführt werden. Schützen Sie ihr System und verwenden sie sudo, su, usw. nur dann, wenn es wirklich notwendig ist!

Einführung

Das Verhindern von Schreibvorgängen auf die gewünschten Datenträger bzw. -bereiche wird durch zweierlei Maßnahmen erreicht. Einerseits werden Datenbereiche im read-only Modus in das laufende System eingehängt. Andererseits wird über die nur-lesbaren Bereiche eine transparente RAM-Disk gelegt in die alle Schreiboperationen "umgebogen" werden. Hinsichtlich der potentiellen Dateisysteme bieten sich unionfs, overlayfs, AUFS, usw. an. Im Rahmen dieses Artikels wird auf die Verwendung von AUFS eingegangen.

Installationsschritte

Die Installation lässt sich in 3 Teilbereiche untergliedern:
  1. Patchen des Linux-Kernels (PREEMPT_RT, AUFS)
  2. Erstellen einer initial RAM-Disk
  3. Konfiguration des Linux-Systems, sowie des Startvorganges

Als Vorlage für dieses Tutorial dient der Artikel " aufs root filesystem " von "kinsa". Zusätzlich zu den im genannten Tutorial erwähnten Schritte wird der Kernel auf den Echtzeiteinsatz vorbereitet und erklärt, wie sich das System auf elegante Weise aktualisieren lässt.

Patchen des Linux-Kernels

Im ersten Schritt werden einige der im referenzierten HowTo " Echtzeitfähige Linux-Systeme: Eine Beispielumsetzung anhand des Raspberry Pi's " angeführten Schritte ausgeführt: Klonen des Raspberry Pi Kernel Git-Repositoriums und Einspielen des PREEMPT_RT Patches .
git clone --depth=1 https://github.com/raspberrypi/linux.git linux-raspberrypi
wget https://www.kernel.org/pub/linux/kernel/projects/rt/3.12/patch-3.12.26-rt40.patch.xz
xz -d -c ../patch-3.12.26-rt40.patch.xz | patch --dry-run -p 1

Hinweis: Der eingesetzte Patch muss zur Kernel-Version passen. Es ist möglich, dass es in der Zwischenzeit bereits eine neuere Version gibt als die hier referenzierte!

Der Patch lässt sich bis auf einen kleinen Teil erfolgreich anwenden.
xz -d -c ../patch-3.12.26-rt40.patch.xz | patch -p 1

Bei den aktuellen Kernel-Versionen lässt sich der Fehler beim Patchen durch folgendes Kommando beheben:
echo 'obj-$(CONFIG_HWLAT_DETECTOR)   += hwlat_detector.o' >> `find . -type f -iname '*.rej' | sed 's/.rej//'`

Nun können die AUFS-Patches eingespielt werden:
# Downloaden des AUFS Source-Codes
git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git
cd aufs3-standalone
git checkout remotes/origin/aufs3.12.x

# Einspielen der Patches
cp -a fs ../linux-raspberrypi
cp include/uapi/linux/aufs_type.h ../linux-raspberrypi/include/uapi/linux
cd ../linux-raspberrypi
patch -p1 < ../aufs3-standalone/aufs3-kbuild.patch
patch -p1 < ../aufs3-standalone/aufs3-base.patch
patch -p1 < ../aufs3-standalone/aufs3-mmap.patch
patch -p1 < ../aufs3-standalone/aufs3-standalone.patch

Das Übersetzen des Kernels erfolgt mit den im referenzierten Artikel erläuterten Kommandos:
export CROSS_COMPILE=/usr/local/toolchains/gcc-arm-bcm2708/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
export ARCH=arm

make mrproper
make bcmrpi_defconfig
make xconfig

Folgende Kernel-Optionen müssen aktiviert bzw. fix in den Kernel einkompiliert sein (also NICHT als Modul):
CONFIG_PREEMPT_RT_FULL=yEchtzeiterweiterungen
CONFIG_HIGH_RES_TIMERS=yNotwendig für die Echtzeiterweiterungen
AUFS_FS=yUnterstützung für das AUFS
AUFS_BR_HFSPLUS=nwird nicht benötigt
CONFIG_BLK_DEV_INITRD=yUnterstützung für Initial RAM-Disks

Das eigentliche Übersetzen des Kernels passiert idealerweise in einem Terminal-Multiplexer, wie z. B. tmux , sodass ein versehentliches Schließen des Terminal-Fensters nicht zum Abbruch des Kompilierens führt.
tmux
make -j <Anzahl-CPU-Kerne + 1>

Während des Übersetzens kann bei Bedarf das Tutorial zur Verwendung von tmux zu Gemüte geführt werden.

Nach Beendigung des Kompiliervorganges steht das neue Kernel-Abbild im Verzeichnis arch/arm/boot/ zur Verfügung. Dieses wird im Folgenden in das Abbild einer Linux-Distribution transferiert. Als Vorlage dient " PipaOS " - eine etwas aktuellere und abgespecktere Variante der Raspbian Distribution.
wget "http://pipaos.mitako.eu/download/pipaos-2.6-tiny500mb.img.gz"
gunzip pipaos-2.6-tiny500mb.img.gz

# Installieren der sleuthkit Dateisystem-Tools (z. B. mmls)
apt-get install sleuthkit
mmls pipaos-2.6-tiny500mb.img

Das 'mmls'-Kommando hat folgende Ausgabe zur Folge:
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

     Slot    Start        End          Length       Description
00:  Meta    0000000000   0000000000   0000000001   Primary Table (#0)
01:  -----   0000000000   0000002047   0000002048   Unallocated
02:  00:00   0000002048   0000116735   0000114688   Win95 FAT32 (0x0c)
03:  -----   0000116736   0000118783   0000002048   Unallocated
04:  00:01   0000118784   0000993279   0000874496   Linux (0x83)
05:  -----   0000993280   0000993999   0000000720   Unallocated

Es lässt sich daraus ableiten, dass die Boot-Partition bei Sektor 2048, und das Root-Dateisystem bei Sektor 118784 beginnt. Mit Hilfe dieser Informationen kann das Dateisystem direkt aus dem Image in das laufende System eingehängt und modifiziert werden. Die Kommandos erfordern Root-Rechte!
# root werden
sudo su -

mkdir -p /mnt/{boot,root}

modprobe loop
mount -o rw,loop,offset=$((2048*512)) <pfad-zum-image>/pipaos-2.6-tiny500mb.img /mnt/boot
mount -o rw,loop,offset=$((118784*512)) <pfad-zum-image>/pipaos-2.6-tiny500mb.img /mnt/root

Das Ergebnis des Kernel-Compiles kann nun in das Abbild übertragen werden (Root-Rechte erforderlich!)
cp arch/arm/boot/zImage /mnt/boot/kernel-rt-aufs.img

Dies gilt auch für die Kernel-Module:
# ohne root-Rechte
make INSTALL_MOD_PATH=../modules.rt modules_install

# mit root-Rechten
cp -a ../modules.rt/* /mnt/root

Zur Verwendung des neuen Kernels, sowie zum Setzen der erforderlichen Kernel-Parameter müssen zwei Dateien der Boot-Partition angepasst werden:
# Nutzen des neuen Abbilds
sed -i 's/^kernel/#kernel/' /mnt/boot/config.txt
echo "kernel=kernel-rt-aufs.img" >> /mnt/boot/config.txt
echo "# set initial ramdisk" >> /mnt/boot/config.txt
echo "initramfs initrd.gz" >> /mnt/boot/config.txt

# Setzen der Kernel-Parameter
sed -i 's/$/ ro lapic sdhci_bcm2708.enable_llm=0 rwfs=tmpfs/' /mnt/boot/cmdline.txt

Damit sind die Anpassungen auf der Boot-Partition bereits abgeschlossen. Diese kann nun (mit root-Rechten) ausgehängt werden.
umount /mnt/boot

In den nächsten Schritten wird erklärt, wie die Initial RAM-Disk erstellt und in das System eingebunden wird. Weiters wird erläutert, welche Anpassungen am Betriebssystem notwendig sind und wie dieses im Bedarfsfalle aktualisiert werden kann.

Zusammenfassung und nächste Schritte

tbd.
Last edit: 4 years 9 months ago by Rainer Poisel.

Please Log in or Create an account to join the conversation.

LOGI.CALS AUSTRIA

Address

Europaplatz 7/1,
3100 St. Pölten

LOGI.CALS GERMANY

Address

Postfach 1306,
40738 Langenfeld
© 1987 - 2019 logi.cals GmbH