Wie erstelle ich ein Linux-System, auf dem eine einzelne Anwendung ausgeführt wird?

17

Ich versuche, eine Linux-Anwendung auszuführen, und alles, was ich ausführen möchte, ist diese eine Anwendung vom Start weg. Ich brauche Netzwerk und das ist alles (kein Display, Peripheriegeräte usw.). Ich möchte, dass keine anderen Anwendungen ausgeführt werden, damit die von mir ausgeführte Anwendung 100% der CPU enthält. Ist das möglich?

dschatz
quelle
Es wird nicht in der Lage sein, 100% der CPU zu übernehmen, da Ihr Betriebssystem noch einige Ressourcen benötigt.
n0pe
@MaxMackie Natürlich, aber ich möchte, dass das Betriebssystem nur im Namen der Anwendung übernimmt (zum Beispiel für Netzwerkzwecke).
Dschatz
1
Sie erkennen, dass selbst wenn eine Desktop-Umgebung geladen ist, aber im Leerlauf sitzt, keine CPU-Zeit benötigt wird, oder? Der verwendete RAM kann ausgetauscht werden, wenn andere Anwendungen dies erfordern.
Psusi
@dschatz Es wäre hilfreich, wenn Sie weitere Details in Ihre Frage aufnehmen würden. Erzählen Sie uns mehr darüber, welche Anwendung Sie ausführen möchten, wie sie ausgeführt werden soll und welche Art von Hardware Sie verwenden.
NN
Wenn möglich, würde ich gerne wissen, warum Sie das wollen. Soweit ich weiß, möchten Sie alles aus dem Betriebssystem entfernen (einschließlich Konsole), um Ihre App auszuführen. Die Leistungssteigerungen werden marginal sein. Was bringt es also, all diese Arbeit zu haben?
nmat

Antworten:

13

Minimales Start-CPIO-Hallo-Welt-Programm Schritt für Schritt

Geben Sie hier die Bildbeschreibung ein

Kompilieren Sie eine Hallo-Welt ohne Abhängigkeiten, die in einer Endlosschleife endet. init.S::

.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

Wir können nicht verwenden sys_exit, sonst die Kernel-Panik.

Dann:

mkdir d
as --64 -o init.o init.S
ld -o init d/init.o
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

Dadurch wird ein Dateisystem mit unserer Hallo-Welt erstellt /init, das das erste Userland-Programm ist, das der Kernel ausführen wird. Wir hätten auch weitere Dateien hinzufügen können, auf d/die über das /initProgramm zugegriffen werden kann, wenn der Kernel ausgeführt wird.

Dann cdin den Linux - Kernel - Baum, Build ist wie üblich, und führen Sie es in QEMU:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

Und Sie sollten eine Linie sehen:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

auf dem Emulatorbildschirm! Beachten Sie, dass dies nicht die letzte Zeile ist. Sie müssen also etwas weiter nach oben schauen.

Sie können C-Programme auch verwenden, wenn Sie sie statisch verknüpfen:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

mit:

gcc -static init.c -o init

Sie können auf echter Hardware mit einem USB-Anschluss ausgeführt werden /dev/sdXund:

make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

Hervorragende Quelle zu diesem Thema: http://landley.net/writing/rootfs-howto.html Außerdem wird die Verwendung gen_initramfs_list.sheines Skripts aus dem Linux-Kernel-Quellbaum zur Automatisierung des Prozesses erläutert .

Nächster Schritt: Richten Sie BusyBox ein, damit Sie mit dem System interagieren können: /unix/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Getestet unter Ubuntu 16.10, QEMU 2.6.1.

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
quelle
3

Sie können den Kernel mit einem init=/path/to/myappin Ihrem Bootloader definierten Parameter starten .

Michał Šrajer
quelle
2
Dies ist eine ziemlich extreme Lösung. Wenn Sie das Startskript durch die Benutzeranwendung ersetzen, wird die Anwendung ohne Netzwerk ausgeführt, ohne dass andere Dateisysteme als die Rootfs bereitgestellt werden (keine sysfs oder proc oder tmpfs), und möglicherweise werden einige Geräteknoten nicht erstellt.
Sägemehl
2
@sawdust: Stimme voll und ganz zu. Aber die Frage war auch etwas extrem ... :-)
Michał Šrajer
2

Es hört sich so an, als würden Sie versuchen, einen Kiosk einzurichten . Die meisten Anleitungen im Internet konzentrieren sich auf einen Webbrowser wie Firefox als einzige Anwendung, die ausgeführt wird. In diesem Handbuch finden Sie Ideen.

William Jackson
quelle
2
Hmm, ich versuche wirklich nur, eine einzelne Anwendung mit Netzwerk auszuführen. Ich möchte nicht, dass X und so wenige andere Anwendungen wie möglich ausgeführt werden. Ich verstehe nicht, wie dies alle unnötigen Dämonen am Laufen hindert.
Dschatz
Kann die Anwendung jedoch ohne X ausgeführt werden?
Geselle Geek
2

Sie können nach dem Booten des Kernels sicher nur eine Benutzeranwendung ausführen. Es wird jedoch nicht 100% der CPU vorhanden sein, da einige andere kernelbezogene Prozesse vorhanden sein müssen. Dies geschieht üblicherweise bei Embedded-Linux-Geräten, z. B. WLAN-Routern. Ich habe auch Erfahrungen aus erster Hand damit, dies für eine Multithread-Anwendung zu tun.

Nach dem Start des Kernels wird ein Initialisierungs- oder Startskript ausgeführt. Informieren Sie sich über Linux- Runlevel und den Init-Prozess. Es werden verschiedene Startschemata verwendet, daher ist es nicht möglich, spezifisch zu sein. Mit Linux können Sie jedoch genau konfigurieren, welche Anwendungen und Daemons für Ihre Situation ausgeführt werden. Abgesehen von einer Startdatei im Stammverzeichnis befinden sich die zu ändernden Dateien in / etc und insbesondere in /etc/init.d

Übrigens, es sei denn, Sie sind ein Superprogrammierer oder bevor Sie einen Remote-GDB-Server zum Laufen bringen, benötigen Sie eine Art Debug-Konsole (entweder die PC-Konsole oder eine serielle Schnittstelle) für Ihre Anwendung. Auf diese Weise können Sie über Seg-Fehler, Busfehler und Assertionsfehler informiert werden. Planen Sie also neben "Networking" auch eine Art "Peripherie".

Sägespäne
quelle
1

Es gibt einige Systemanwendungen, die ausgeführt werden müssen. Außerdem können Sie den Rest der Computerressourcen dieser Anwendung zuweisen. Um das Minimum zu erreichen, können Sie sich wirklich kleine Linux-Distributionen wie TinyCore Linux usw. ansehen.

Es würde auch von der Anwendung selbst abhängen, welche Dienste sie neben dem Netzwerk usw. benötigt.

Ich denke, wenn Sie spezifischere Informationen liefern können, erhalten Sie eine detailliertere Antwort.

Wie welche Art von App usw.

bakytn
quelle
Meine Anwendung verwendet die pthread-Bibliothek, um eine mulithreaded-Workload (arithmetische Operationen) auszuführen, und kann angewiesen werden, verschiedene Berechnungen basierend auf der Eingabe von tcp / ip durchzuführen. Bei TinyCore Linux wird eine vollständige Desktop-Umgebung gestartet, die ich nicht möchte.
Dschatz
TinyCore hat einen kleineren Bruder namens MicroCore. Keine GUI, probier es aus.
n0pe
1
@ MaxMackie Ich möchte eigentlich keine Schnittstelle auf dem Computer selbst außerhalb des TCP / IP-Stacks. Die Anwendung kann einen Port blockieren und über TCP-Pakete gesteuert werden, die an diesen Port gesendet werden.
Dschatz
1
Ich würde eine Umgebung empfehlen, in der nur wenige Dienste ausgeführt werden ( siehe linuxhelp.blogspot.com/2006/04/… ) und kaum etwas anderes als Ihre Anwendung und die installierten Abhängigkeiten.
n0pe
1
@dschatz gut, dann musst du den Kernel hacken, alles andere entfernen und deine App darin kompilieren. kein Schlag nichts anderes. nur deine app..lol.
Bakytn
1

Wenn Sie wirklich nur den Linux-Kernel, das Netzwerk und Ihre Anwendung möchten, können Sie dies nur folgendermaßen tun:

  • Sie müssen Ihre Anwendung zu einem Kernelmodul machen - stellen Sie sicher, dass sie debuggt und gut getestet ist. Dieses Kernelmodul müsste Dinge initialisieren, die normalerweise über den Benutzerbereich ausgeführt werden, wie z. B. das Festlegen von Schnittstellen-IP-Adressen und all das Gute.
  • Sie müssen make menuconfigIhren eigenen benutzerdefinierten Kernel herunterladen und konfigurieren ( ) und alle Funktionen entfernen, die nicht mit der Ausführung des Systems und des Netzwerks zusammenhängen. Sie möchten deaktivieren, um die Ebene zu blockieren. Ich weiß nicht, wie dies bei den letzten Kerneln durchgeführt werden soll make menuconfig.
  • Sie müssen dann Ihr Modul in den Kernel aufnehmen, damit es als Teil des Kernels und nicht als ladbares Modul enthalten ist. Sie würden wahrscheinlich ladbare Module im obigen Schritt deaktivieren. Wenn Sie genug C / C ++ kennen, um ein Kernelmodul zu erstellen, sollte dies für Sie einfach sein.
  • Sie müssen den Teil des Kernels ändern, der in Panik gerät, wenn initdies nicht der Fall ist, oder Sie müssen darauf vorbereitet sein, mit einem zusätzlichen User-Space-Prozess zu leben.

Ich weiß, dass Kernelmodule Prozesse erstellen können - eine einfache ps auxwürde viele auf einem typischen System anzeigen (sie sind alle in Klammern angegeben). Sie möchten wahrscheinlich, dass Ihr Modul einen Kernelprozess erstellt. Um alle vom Kernel erstellten Prozesse außer Ihren zu entfernen, müssen Sie Threads [ kthreadd], Energieverwaltung [ pm], die Ereignisebene [ events] und andere deaktivieren .


Wenn Sie eine praktischere Einrichtung des Kernel + 1-User-Space-Prozesses wünschen, ist dies möglich.

Linux hat eine Kernel-Befehlszeilenoption namens init=- dies ist, was der Kernel startet, wenn er geladen ist. Das Programm muss sich auf dem Root-Gerät befinden, das mit root=oder in der initrd angegeben ist (von Ihrem Bootloader geladen).

Wenn dieses Programm beendet wird, gerät Linux in Panik. Stellen Sie daher sicher, dass es niemals beendet wird.

Viele moderne Linux-Distributionen haben es so eingerichtet, dass ein initProgramm in der initrd vor dem Start /sbin/initoder eine zusätzliche Initialisierung des Benutzerraums durchführt /sbin/systemd. Sie müssen hier herausfinden, was Ihre Distribution tut (Informationen zu Debian finden Sie hier ) und herausfinden, wo Sie das endgültige "Handoff" -Programm angeben können. Von dort aus können Sie es anweisen, Ihre Anwendung anstelle von initoder zu starten systemd.

systemdverwaltet viele grundlegende Funktionen wie /devdas Erstellen, Festlegen des Hostnamens und andere Dinge. Wenn Sie also flexibel sind, sollten Sie sich stattdessen mit der Konfiguration befassen systemd, um einen einzelnen Prozess zu erzeugen, und ihn optional neu starten, wenn er fehlschlägt. Wenn ich mich nicht irre, wird dies im Grunde genommen für den Einzelbenutzer- oder Wiederherstellungsmodus ausgeführt - es wird eine Shell gestartet.

Es werden 2 Prozesse ausgeführt ( systemdund Ihr Programm), aber das System gerät nicht in Panik, wenn Ihr Programm beendet wird oder abstürzt.

Betrachten Sie auch einfach eine einfache Installation von Debian - eine "netinst" -Installation hat außer dem Kernel, einer Shell und einigen Diensten nicht viel zu tun - oder OpenWRT / LEDE - es gibt einen Webserver für Luci, der standardmäßig ausgeführt wird, und a paar andere Dienste, ist aber leicht deaktiviert.

LawrenceC
quelle