Como criar um sistema Linux que executa um único aplicativo?

17

Estou tentando executar um aplicativo Linux e tudo o que quero executar é esse aplicativo fora de inicialização. Preciso de rede e é tudo (sem tela, periféricos, etc.). Não quero outros aplicativos em execução para que o aplicativo que eu corro tenha 100% da CPU. Isso é possível?

dschatz
fonte
Não será capaz de pegar 100% da CPU, pois seu sistema operacional ainda precisa de alguns recursos.
n0pe
@MaxMackie Obviamente, mas eu gostaria que o sistema operacional assumisse apenas o nome do aplicativo (para fins de rede, por exemplo).
dschatz
1
Você percebe que, mesmo com um ambiente de desktop carregado, mas parado lá, ele não está usando nenhum tempo de CPU, certo? E a ram que está usando está sujeita a ser trocada se outras aplicações exigirem.
Psusi 8/08
@dschatz Ajudaria se você incluísse mais detalhes em sua pergunta. Como nos dizer mais sobre qual aplicativo você deseja executar, como deseja que ele execute e que tipo de hardware você está usando.
NN
Se possível, eu gostaria de saber por que você quer isso. Pelo que entendi, você deseja remover tudo do sistema operacional (console incluído) apenas para executar seu aplicativo. Os ganhos de desempenho serão marginais; então, qual é o sentido de ter todo esse trabalho?
N /

Respostas:

13

Passo a passo do programa Olá mundo mundial do CPIO initrd mínimo

insira a descrição da imagem aqui

Compile um mundo olá sem dependências que termine em um loop 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

Não podemos usar sys_exit, senão o kernel entra em pânico.

Então:

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"

Isso cria um sistema de arquivos com o nosso hello world at /init, que é o primeiro programa da terra do usuário em que o kernel será executado. Também poderíamos ter adicionado mais arquivos d/e eles seriam acessíveis a partir do /initprograma quando o kernel for executado.

Em seguida, cdna árvore do kernel do Linux, build é como de costume e execute-o no 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 você deve ver uma linha:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

na tela do emulador! Note que não é a última linha, então você precisa olhar um pouco mais adiante.

Você também pode usar programas C se os vincular estaticamente:

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

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

com:

gcc -static init.c -o init

Você pode executar em hardware real com um USB ativado /dev/sdXe:

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

Ótima fonte sobre este assunto: http://landley.net/writing/rootfs-howto.html Também explica como usar gen_initramfs_list.sh, que é um script da árvore de fontes do kernel Linux para ajudar a automatizar o processo.

Próxima etapa: configure o BusyBox para que você possa interagir com o sistema: /unix/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Testado no Ubuntu 16.10, QEMU 2.6.1.

Ciro Santilli adicionou uma nova foto
fonte
3

você pode iniciar o kernel com o init=/path/to/myappparâmetro definido no seu gerenciador de inicialização.

Michał Šrajer
fonte
2
Esta é uma solução bastante extrema. A substituição do script de inicialização pelo aplicativo do usuário fará com que o aplicativo seja executado sem rede, sem nenhum sistema de arquivos que não seja o rootfs montado (nenhum sysfs ou proc ou tmpfs) e, possivelmente, alguns nós do dispositivo não serão criados.
serragem
2
@sawdust: concordo totalmente. Mas a questão também foi pouco exagerado ... :-)
Michał Šrajer
2

Parece que você está tentando configurar um quiosque . A maioria dos guias da Internet concentra-se em um navegador da web como o Firefox como o único aplicativo que é executado. Dê uma olhada neste guia para obter idéias.

William Jackson
fonte
2
Hmm, estou realmente apenas tentando executar um único aplicativo com rede. Eu não quero nenhum X e o menor número possível de aplicativos em execução. Não vejo como isso restringe a execução de todos os daemons desnecessários.
dschatz
o aplicativo pode ser executado sem o X?
Journeyman Geek
2

Certamente você pode executar apenas um aplicativo de usuário após inicializar o kernel. Mas ele não terá 100% da CPU porque haverá outros processos relacionados ao kernel que devem existir. Isso geralmente é feito em dispositivos Linux embarcados, por exemplo, roteadores sem fio. Eu também tenho experiência em primeira mão fazendo isso para um aplicativo multiencadeado.

Após a inicialização do kernel, um script de inicialização ou inicialização é executado. Leia sobre os níveis de execução do Linux e o processo init. Existem vários esquemas de inicialização em uso, portanto, não é possível ser específico. Mas o Linux permitirá que você configure exatamente quais aplicativos e daemons serão executados para sua situação. Além de um arquivo de inicialização na raiz, os arquivos que precisam ser modificados estão em / etc e, em particular, /etc/init.d

BTW, a menos que você seja um superprogramador ou antes de executar um servidor GDB remoto, precisará de um tipo de console de depuração (o console do PC ou uma porta serial) para seu aplicativo. Isso permitirá que você seja notificado sobre falhas de seg, erros de barramento e falhas de asserção. Portanto, planeje ter uma espécie de "periférico" além de "networking".

serragem
fonte
1

Existem alguns aplicativos de sistema que precisam ser executados, além deles, com certeza, você pode dedicar o restante dos recursos do computador a esse aplicativo. Para ter o mínimo, você pode dar uma olhada em pequenas distribuições Linux como o TinyCore Linux etc.

Também dependeria da própria aplicação, de quais serviços ela requer além da rede etc.

Acho que se você puder fornecer informações mais específicas, obterá uma resposta mais detalhada.

Como que tipo de aplicativo etc.

bakytn
fonte
Meu aplicativo usa a biblioteca pthread para executar alguma carga de trabalho multithread (operações aritméticas) e pode ser instruído a fazer cálculos diferentes com base na entrada do tcp / ip. Olhando para o TinyCore Linux, ele inicializa em um ambiente de desktop completo, o que eu não quero.
dschatz
TinyCore tem um irmão menor chamado MicroCore. Sem GUI, confira.
n0pe
1
@ MaxMackie Na verdade, não quero interface na máquina fora da pilha TCP / IP. O aplicativo pode bloquear em uma porta e pode ser controlado por pacotes TCP enviados para essa porta.
dschatz
1
Eu recomendaria um ambiente com poucos serviços em execução (consulte linuxhelp.blogspot.com/2006/04/… ) e quase nada além de seu aplicativo e de suas dependências instaladas.
n0pe
1
@dschatz, então você precisa hackear o kernel, remover tudo o mais e compilar seu aplicativo nele. sem festança, sem mais nada. apenas o seu app..lol.
bakytn
1

Se você realmente deseja nada além do kernel Linux, da rede e do seu aplicativo, a única maneira de fazer isso é:

  • Você precisará tornar seu aplicativo um módulo do kernel - verifique se ele está depurado e bem testado. Esse módulo do kernel teria que inicializar coisas normalmente feitas através do espaço do usuário, como definir endereços IP de interface e todas essas coisas boas.
  • Você precisará baixar e configurar ( make menuconfig) seu próprio kernel personalizado e remover todos os recursos que não estão relacionados à execução do sistema e da rede. Você desejará desativar o bloqueio da camada, não sei como fazer isso nos kernels recentes make menuconfig.
  • Você precisa incluir seu módulo no kernel para que ele seja incluído como parte do kernel e não como um módulo carregável. Você provavelmente desativaria os módulos carregáveis ​​na etapa acima. Se você conhece C / C ++ suficiente para criar um módulo de kernel, isso deve ser fácil para você.
  • Você precisa modificar qualquer parte do kernel que entre em pânico se initnão conseguir fazer isso ou estar preparado para viver com 1 processo extra de espaço do usuário.

Eu sei que é possível que os módulos do kernel criem processos - um simples ps auxmostraria muitos em um sistema típico (todos eles estão entre colchetes). Você provavelmente deseja que seu módulo crie um processo de kernel. Para se livrar de todos os processos criados pelo kernel além do seu, você precisará desativar os threads [ kthreadd], o gerenciamento de energia [ pm], a camada de eventos [ events] e outros.


Se você deseja uma configuração mais prática do processo de espaço do usuário do kernel + 1, isso é possível.

O Linux possui uma opção de linha de comando do kernel chamada init=- é assim que o kernel inicia quando o carregamento terminar. O programa deve estar no dispositivo raiz especificado com root=ou no initrd (carregado pelo seu carregador de inicialização).

Se esse programa sair, o Linux entrará em pânico, portanto, verifique se ele nunca sai.

Muitas distribuições modernas de Linux o configuram para que um initprograma no initrd faça alguma inicialização adicional no espaço do usuário, antes de iniciar /sbin/initou /sbin/systemd. Você terá que descobrir o que sua distribuição faz aqui (as informações para o Debian estão aqui ) e descobrir onde você pode especificar o programa final "handoff" e, a partir daí, você pode dizer para ele iniciar seu aplicativo em vez de initou systemd.

systemdgerencia muitas funcionalidades básicas, como construção /dev, configuração de nome de host e outras coisas; portanto, se você é flexível, pode optar por configurar systemdpara gerar um único processo e, opcionalmente, reiniciá-lo se falhar. Se não me engano, basicamente isso é feito no modo de usuário único ou modo de recuperação - ele inicia um shell.

Você terá 2 processos em execução ( systemde seu programa), mas o sistema não entrará em pânico se o programa sair ou travar.

Considere também simplesmente uma instalação leve do Debian - uma instalação "netinst" não tem muito em execução além do kernel, um shell e alguns serviços - ou considere o OpenWRT / LEDE - ele possui um servidor web para Luci executando por padrão e um outros serviços, mas é facilmente desativado.

LawrenceC
fonte