Come creare un sistema Linux che esegue una singola applicazione?


17

Sto cercando di eseguire un'applicazione Linux e tutto ciò che voglio eseguire è questa applicazione non avviata. Ho bisogno di rete e tutto qui (niente display, periferiche, ecc.). Non voglio eseguire altre applicazioni in modo che l'applicazione che eseguo abbia il 100% della CPU. È possibile?


Non sarà in grado di catturare il 100% della CPU visto che il tuo sistema operativo necessita ancora di alcune risorse.
n0pe

@MaxMackie Ovviamente, ma vorrei che il sistema operativo prendesse il controllo solo per conto dell'applicazione (ad esempio per scopi di rete).
dschatz,

1
Ti rendi conto che anche con un ambiente desktop caricato, ma seduto lì inattivo, non sta usando alcun tempo della CPU giusto? E la ram che sta usando è soggetta a sostituzione se altre applicazioni lo richiedono.
psusi

@dschatz Sarebbe utile se includessi ulteriori dettagli nella tua domanda. Ad esempio, raccontaci di più su quale applicazione vuoi eseguire, su come vuoi che funzioni e che tipo di hardware stai usando.
NN,

Se possibile, vorrei sapere perché lo desideri. Da quello che ho capito, vuoi rimuovere tutto dal sistema operativo (console inclusa) solo per eseguire la tua app. I guadagni in termini di prestazioni saranno marginali, quindi che senso ha avere tutto quel lavoro?
nmat

Risposte:


13

Programma CPIO ciao minimo di initrd passo dopo passo

inserisci qui la descrizione dell'immagine

Compila un mondo ciao senza dipendenze che termina in un ciclo infinito. 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

Non possiamo usare sys_exit, altrimenti i panici del kernel.

Poi:

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"

Questo crea un filesystem con il nostro ciao mondo su /init, che è il primo programma userland che verrà eseguito dal kernel. Avremmo anche potuto aggiungere più file d/e sarebbero accessibili dal /initprogramma quando il kernel è in esecuzione.

Quindi cdnella struttura del kernel Linux, build è come al solito ed eseguirlo 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"

E dovresti vedere una linea:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

sullo schermo dell'emulatore! Nota che non è l'ultima riga, quindi devi cercare un po 'più in alto.

Puoi anche usare i programmi C se li colleghi staticamente:

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

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

con:

gcc -static init.c -o init

È possibile eseguire su hardware reale con un USB acceso /dev/sdXe:

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

Grande fonte su questo argomento: http://landley.net/writing/rootfs-howto.html Spiega anche come usare gen_initramfs_list.sh, che è uno script dall'albero dei sorgenti del kernel Linux per automatizzare il processo.

Passaggio successivo: imposta BusyBox in modo da poter interagire con il sistema: /unix/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Testato su Ubuntu 16.10, QEMU 2.6.1.


3

puoi avviare il kernel con il init=/path/to/myappparametro definito nel tuo bootloader.


2
Questa è una soluzione piuttosto estrema. Sostituendo lo script di avvio con l'applicazione utente, l'applicazione funzionerà senza rete, senza file system diversi dai rootfs montati (senza sysfs o proc o tmpfs) e probabilmente alcuni nodi di dispositivo non verranno creati.
segatura

2
@sawdust: totalmente d'accordo. Ma la domanda era anche un po 'estrema ... :-)
Michał Šrajer il

2

Sembra che tu stia cercando di installare un chiosco . La maggior parte delle guide su Internet si concentrano su un browser Web come Firefox come singola applicazione in esecuzione. Dai un'occhiata a questa guida per idee.


2
Hmm, sto davvero solo cercando di eseguire una singola applicazione con la rete. Non voglio alcuna X e il minor numero possibile di altre applicazioni in esecuzione. Non vedo come ciò limiti la corsa di tutti i demoni non necessari.
dschatz,

è possibile eseguire l'applicazione senza X?
Journeyman Geek

2

Puoi sicuramente eseguire una sola applicazione utente dopo aver avviato il kernel. Ma non avrà il 100% della CPU perché ci saranno altri processi relativi al kernel che devono esistere. Questo è comunemente fatto in dispositivi Linux embedded, ad esempio router wireless. Ho anche un'esperienza di prima mano nel fare questo per un'applicazione multi-thread.

Una volta avviato il kernel, viene eseguito uno script di inizializzazione o di avvio. Leggi su runlevel Linux e il processo di init. Esistono vari schemi di avvio in uso, quindi non è possibile essere specifici. Ma Linux ti permetterà di configurare esattamente quali applicazioni e demoni eseguiranno per la tua situazione. Oltre a un file di avvio alla radice, i file che devono essere modificati sono in / etc , e in particolare /etc/init.d

A meno che tu non sia un tipo di superprogrammatore o prima di avere un server GDB remoto in esecuzione, avrai bisogno di un qualche tipo di console di debug (o la console del PC o una porta seriale) per la tua applicazione. Ciò consentirà di ricevere notifiche relative a errori di seg, errori del bus e errori di asserzione. Quindi pianifica di avere un qualche tipo di "periferica" ​​oltre a "rete".


1

Ci sono alcune applicazioni di sistema che devono essere eseguite, oltre a loro, certo, puoi dedicare il resto delle risorse del computer a quell'applicazione. Per avere il minimo puoi dare un'occhiata a distro Linux molto piccole come TinyCore Linux ecc.

Inoltre dipenderà anche dall'applicazione stessa, dai servizi richiesti oltre alla rete, ecc.

Penso che se puoi fornire informazioni più specifiche otterrai una risposta più dettagliata.

Ti piace che tipo di app ecc.


La mia applicazione utilizza la libreria pthread per eseguire un carico di lavoro multithread (operazioni aritmetiche) e può essere incaricato di eseguire calcoli diversi in base all'input da tcp / ip. Guardando TinyCore Linux, si avvia in un ambiente desktop completo, che non voglio.
dschatz,

TinyCore ha un fratello minore chiamato MicroCore. Nessuna GUI, dai un'occhiata.
n0pe

1
@MaxMackie In realtà non voglio alcuna interfaccia sulla macchina stessa al di fuori dello stack tcp / ip. L'applicazione può bloccare su una porta e può essere controllata tramite pacchetti tcp inviati a quella porta.
dschatz,

1
Consiglierei un ambiente con pochi servizi in esecuzione (dai un'occhiata a linuxhelp.blogspot.com/2006/04/… ) e quasi niente altro che la tua applicazione e le sue dipendenze installate.
n0pe

1
@dschatz bene, allora devi hackerare il kernel, rimuovere tutto il resto e compilare la tua app al suo interno. no bash nient'altro. solo la tua app..lol.
Bakytn

1

Se non vuoi altro che il kernel Linux, la rete e la tua applicazione, l'unico modo per farlo è questo:

  • Dovrai rendere la tua applicazione un modulo del kernel - assicurati che sia sottoposta a debug e ben testata. Questo modulo del kernel dovrebbe inizializzare le cose in genere fatte tramite userspace come impostare gli indirizzi IP dell'interfaccia e tutto ciò che è buono.
  • Sarà necessario scaricare e configurare ( make menuconfig) il proprio kernel personalizzato e rimuovere tutte le funzionalità non correlate all'esecuzione del sistema e della rete. Dovrai disabilitare il blocco del livello, non so come farlo sui kernel recenti attraverso make menuconfig.
  • È quindi necessario includere il modulo nel kernel in modo che sia incluso come parte del kernel e non come modulo caricabile. Probabilmente disabiliterai i moduli caricabili nel passaggio precedente. Se conosci abbastanza C / C ++ per creare un modulo kernel questo dovrebbe essere facile per te.
  • È necessario modificare qualsiasi parte del kernel che vada in panico se initnon riesce a farlo, oppure essere pronti a vivere con 1 ulteriore processo di spazio utente.

So che è possibile per i moduli del kernel creare processi - un semplice ps auxne mostrerebbe molti su un sistema tipico (sono tutti tra parentesi). Probabilmente vuoi che il tuo modulo crei un processo del kernel. Per sbarazzarsi di tutti i processi creati dal kernel oltre al tuo, dovrai disabilitare i thread [ kthreadd], la gestione dell'alimentazione [ pm], il livello evento [ events] e altri.


Se vuoi una configurazione più pratica del processo dello spazio utente del kernel + 1, è possibile.

Linux ha un'opzione della riga di comando del kernel chiamata init=- questo è ciò che il kernel inizierà al termine del caricamento. Il programma deve trovarsi sul dispositivo root specificato con root=o in initrd (caricato dal bootloader).

Se questo programma termina, Linux andrà in panico, quindi assicurati che non esca mai.

Molte moderne distribuzioni di Linux lo hanno configurato, quindi un initprogramma in initrd esegue un'inizializzazione aggiuntiva dello spazio utente, prima di avviare /sbin/inito /sbin/systemd. Dovrai scoprire cosa fa la tua distribuzione qui (informazioni su Debian sono qui ) e scoprire dove puoi specificare il programma finale di "handoff", e da lì puoi dirgli di avviare la tua applicazione invece di inito systemd.

systemdgestisce molte funzionalità di base, come la costruzione /dev, l'impostazione del nome host e altre cose, quindi se sei flessibile potresti voler invece cercare la configurazione systemdper generare un singolo processo e, facoltativamente, riavviarlo se fallisce. Se non sbaglio, fondamentalmente lo fa per la modalità utente singolo o di recupero - avvia una shell.

Avrai 2 processi in esecuzione ( systemde il tuo programma) ma il sistema non andrà in panico se il tuo programma si chiude o si blocca.

Considera anche semplicemente un'installazione leggera di Debian - un'installazione "netinst" non ha molto altro che il kernel, una shell e un paio di servizi - o considera OpenWRT / LEDE - ha un server web per Luci funzionante di default e un abbina altri servizi ma è facilmente disabilitato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.