Comment créer un système Linux qui exécute une seule application?

17

J'essaie d'exécuter une application Linux et tout ce que je veux exécuter est cette seule application hors démarrage. J'ai besoin de réseautage et c'est tout (pas d'affichage, de périphériques, etc.). Je ne veux aucune autre application en cours d'exécution afin que l'application que j'exécute ait 100% du CPU. Est-ce possible?

dschatz
la source
Il ne pourra pas récupérer 100% du CPU car votre système d'exploitation a encore besoin de ressources.
n0pe
@MaxMackie Évidemment, mais j'aimerais que le système d'exploitation ne prenne le relais qu'au nom de l'application (à des fins de mise en réseau par exemple).
dschatz
1
Vous vous rendez compte que même avec un environnement de bureau chargé, mais assis inactif, il n'utilise pas de temps processeur, non? Et le bélier qu'il utilise est susceptible d'être échangé si d'autres applications l'exigent.
psusi
@dschatz Il serait utile que vous incluiez plus de détails dans votre question. Comme nous en dire plus sur l'application que vous souhaitez exécuter, la façon dont vous souhaitez qu'elle fonctionne et le type de matériel que vous utilisez.
NN
Si possible, je voudrais savoir pourquoi voulez-vous cela. D'après ce que je comprends, vous souhaitez tout supprimer du système d'exploitation (console incluse) juste pour exécuter votre application. Les gains de performance seront marginaux, alors à quoi bon avoir tout ce travail?
nmat

Réponses:

13

Étape par étape du programme minimal initrd CPIO hello world

entrez la description de l'image ici

Compilez un monde bonjour sans aucune dépendance qui se termine par une boucle infinie. 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

On ne peut pas utiliser sys_exit, sinon la panique du noyau.

Alors:

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"

Cela crée un système de fichiers avec notre monde bonjour /init, qui est le premier programme de l'espace utilisateur sur lequel le noyau s'exécutera. Nous aurions également pu ajouter plus de fichiers d/et ils seraient accessibles depuis le /initprogramme lors de l'exécution du noyau.

Ensuite, cddans l'arborescence du noyau Linux, la construction est comme d'habitude et exécutez-la dans 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"

Et vous devriez voir une ligne:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

sur l'écran de l'émulateur! Notez que ce n'est pas la dernière ligne, vous devez donc regarder un peu plus haut.

Vous pouvez également utiliser des programmes C si vous les liez statiquement:

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

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

avec:

gcc -static init.c -o init

Vous pouvez exécuter sur du vrai matériel avec une clé USB /dev/sdXet:

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

Excellente source sur ce sujet: http://landley.net/writing/rootfs-howto.html Il explique également comment utiliser gen_initramfs_list.sh, qui est un script de l'arborescence des sources du noyau Linux pour aider à automatiser le processus.

Étape suivante: configurez BusyBox pour pouvoir interagir avec le système: /unix/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Testé sur Ubuntu 16.10, QEMU 2.6.1.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
la source
3

vous pouvez démarrer le noyau avec un init=/path/to/myappparamètre défini dans votre chargeur de démarrage.

Michał Šrajer
la source
2
C'est une solution plutôt extrême. En remplaçant le script de démarrage par l'application utilisateur, l'application s'exécutera sans mise en réseau, sans aucun système de fichiers autre que les rootfs montés (pas de sysfs ou proc ou tmpfs), et éventuellement certains nœuds de périphérique ne seront pas créés.
sciure de bois
2
@sawdust: Tout à fait d'accord. Mais la question était aussi un peu extrême ... :-)
Michał Šrajer
2

On dirait que vous essayez de mettre en place un kiosque . La plupart des guides sur Internet se concentrent sur un navigateur Web comme Firefox comme seule application qui s'exécute. Jetez un oeil à ce guide pour des idées.

William Jackson
la source
2
Hmm, j'essaie vraiment d'exécuter une seule application avec un réseau. Je ne veux pas de X et aussi peu d'applications que possible. Je ne vois pas comment cela empêche tous les démons inutiles de s'exécuter.
dschatz
l'application peut-elle fonctionner sans X?
Journeyman Geek
2

Vous pouvez certainement exécuter une seule application utilisateur après le démarrage du noyau. Mais il n'aura pas 100% du CPU car il y aura d'autres processus liés au noyau qui devront exister. Cela se fait généralement dans les périphériques Linux embarqués, par exemple les routeurs sans fil. J'ai également une expérience de première main dans ce domaine pour une application multithread.

Une fois le noyau démarré, un script d'initialisation ou de démarrage est exécuté. Renseignez-vous sur les niveaux d'exécution Linux et le processus d'initialisation. Il existe différents schémas de démarrage utilisés, il n'est donc pas possible d'être précis. Mais Linux vous permettra de configurer exactement les applications et les démons à exécuter pour votre situation. Outre un fichier de démarrage à la racine, les fichiers à modifier se trouvent dans / etc , et notamment /etc/init.d

BTW à moins que vous ne soyez un superprogrammeur ou avant de lancer un serveur GDB distant, vous aurez besoin d'une sorte de console de débogage (la console PC ou un port série) pour votre application. Cela vous permettra d'être averti des défauts de segmentation, des erreurs de bus et des échecs d'assertion. Prévoyez donc d'avoir une sorte de "périphérique" en plus du "réseautage".

sciure
la source
1

Il existe certaines applications système qui doivent être exécutées, à part elles, bien sûr, vous pouvez consacrer le reste des ressources informatiques à cette application. Pour avoir le minimum, vous pouvez jeter un œil à de très petites distributions Linux comme TinyCore Linux, etc.

Cela dépendrait également de l'application elle-même, des services dont elle a besoin en plus du réseau, etc.

Je pense que si vous pouvez fournir des informations plus spécifiques, vous obtiendrez une réponse plus détaillée.

Comme quel type d'application, etc.

Bakytn
la source
Mon application utilise la bibliothèque pthread pour exécuter une charge de travail multithread (opérations arithmétiques) et peut être chargée de faire différents calculs en fonction des entrées de tcp / ip. En regardant TinyCore Linux, il démarre dans un environnement de bureau complet, ce que je ne veux pas.
dschatz
TinyCore a un petit frère appelé MicroCore. Pas d'interface graphique, vérifiez-le.
n0pe
1
@MaxMackie Je ne veux en fait aucune interface sur la machine elle-même en dehors de la pile TCP / IP. L'application peut bloquer sur un port et peut être contrôlée via des paquets TCP envoyés à ce port.
dschatz
1
Je recommanderais un environnement avec peu de services en cours d'exécution (consultez ceci linuxhelp.blogspot.com/2006/04/… ) et pratiquement rien d'autre que votre application et ses dépendances installées.
n0pe
1
@dschatz bien, alors vous devez pirater le noyau, supprimer tout le reste et y compiler votre application. aucun bash rien d'autre. juste votre app..lol.
bakytn
1

Si vous ne voulez vraiment que le noyau Linux, la mise en réseau et votre application, la seule façon de le faire est la suivante:

  • Vous devrez faire de votre application un module du noyau - assurez-vous qu'il est débogué et bien testé. Ce module du noyau devrait initialiser des choses généralement effectuées via l'espace utilisateur, telles que définir des adresses IP d'interface et toutes ces bonnes choses.
  • Vous devrez télécharger et configurer ( make menuconfig) votre propre noyau personnalisé et supprimer toutes les fonctionnalités qui ne sont pas liées à l'exécution du système et à la mise en réseau. Vous voudrez désactiver pour bloquer la couche, je ne sais pas comment faire sur les noyaux récents make menuconfig.
  • Vous devez ensuite inclure votre module dans le noyau afin qu'il soit inclus dans le noyau et non dans un module chargeable. Vous désactiveriez probablement les modules chargeables à l'étape ci-dessus. Si vous connaissez suffisamment C / C ++ pour créer un module noyau, cela devrait être facile pour vous.
  • Vous devez modifier n'importe quelle partie du noyau qui panique en cas d' initéchec, ou être prêt à vivre avec 1 processus d'espace utilisateur supplémentaire.

Je sais qu'il est possible pour les modules du noyau de créer des processus - un simple en ps auxafficherait beaucoup sur un système typique (ils sont tous entre parenthèses). Vous voulez probablement que votre module crée un processus noyau. Pour vous débarrasser de tous les processus créés par le noyau en plus du vôtre, vous devrez désactiver les threads [ kthreadd], la gestion de l'alimentation [ pm], la couche d'événements [ events] et autres.


Si vous voulez une configuration plus pratique du processus espace utilisateur noyau + 1, c'est possible.

Linux a une option de ligne de commande du noyau appelée init=- c'est ce que le noyau démarrera quand il aura fini de se charger. Le programme doit se trouver sur le périphérique racine spécifié avec root=ou dans l'initrd (chargé par votre chargeur de démarrage).

Si ce programme se ferme, Linux paniquera, alors assurez-vous qu'il ne se ferme jamais.

De nombreuses distributions modernes de Linux l'ont configuré de sorte qu'un initprogramme dans l'initrd effectue une initialisation supplémentaire de l'espace utilisateur, avant de démarrer /sbin/initou /sbin/systemd. Vous devrez découvrir ce que fait votre distribution ici (les informations pour Debian sont ici ) et trouver où vous pouvez spécifier le programme final de "transfert", et à partir de là, vous pouvez lui dire de démarrer votre application au lieu de initou systemd.

systemdgère de nombreuses fonctionnalités de base, telles que la construction /dev, la définition du nom d'hôte, systemdetc. Si je ne me trompe pas, il le fait essentiellement pour le mode mono-utilisateur ou de récupération - il démarre un shell.

Vous aurez 2 processus en cours d'exécution ( systemdet votre programme) mais le système ne paniquera pas si votre programme se ferme ou se bloque.

Considérez également simplement une installation légère de Debian - une installation "netinst" n'a pas beaucoup de fonctionnement autre que le noyau, un shell et quelques services - ou considérez OpenWRT / LEDE - elle a un serveur web pour Luci fonctionnant par défaut et un coupler d'autres services mais est facilement désactivé.

LawrenceC
la source