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

12

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

    
por dschatz 08.08.2011 / 19:27

6 respostas

8

Iniciativa mínima CPIO Olá mundo programa passo-a-passo

Compileummundohellosemnenhumadependênciaquetermineemumloopinfinito.init.S:

.global_start_start:mov$1,%raxmov$1,%rdimov$message,%rsimov$message_len,%rdxsyscalljmp.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 pane.

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 em /init , que é o primeiro programa de userland que o kernel executará. Poderíamos também ter adicionado mais arquivos a d/ e eles seriam acessíveis a partir do programa /init quando o kernel fosse executado.

Então cd na árvore do kernel Linux, a compilação é como sempre, e execute 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ê tem que olhar um pouco mais para cima.

Você também pode usar programas em 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 em /dev/sdX e:

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

Grande fonte sobre este assunto: link Também explica como usar gen_initramfs_list.sh , que é um script da árvore de código-fonte do kernel do Linux para ajudar a automatizar o processo.

Próxima etapa: configure o BusyBox para que você possa interagir com o sistema: link

Testado no Ubuntu 16.10, QEMU 2.6.1.

    
por 25.10.2015 / 23:22
3

Parece que você está tentando configurar um quiosque . A maioria dos guias da Internet se concentra em um navegador da Web como o Firefox como o aplicativo único que é executado. Dê uma olhada em este guia para ideias.

    
por 08.08.2011 / 19:36
3

você pode iniciar o kernel com o parâmetro init=/path/to/myapp definido no seu bootloader.

    
por 08.08.2011 / 23:11
2

Você certamente pode executar apenas um aplicativo de usuário após inicializar o kernel. Mas ele não terá 100% da CPU, porque haverá alguns outros processos relacionados ao kernel que devem existir. Isso é comumente 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 multi-threaded.

Quando o kernel inicializar, um script de inicialização ou inicialização é executado. Leia sobre o runlevels do Linux e sobre o processo de inicialização. 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 ter um servidor GDB remoto rodando, você precisará de algum tipo de console de depuração (seja o console do PC ou uma porta serial) para o seu aplicativo. Isso permitirá que você seja notificado sobre falhas de segmento, erros de barramento e falhas de asserção. Então planeje ter algum tipo de "periférico" além de "networking".

    
por 08.08.2011 / 22:21
2

Se você realmente deseja apenas o kernel do Linux, a rede e o aplicativo, a única maneira de fazer isso é:

  • Você precisará fazer do seu aplicativo um módulo do kernel - certifique-se de que ele esteja depurado e bem testado. Este módulo do kernel teria que inicializar as coisas normalmente feitas via userspace, como definir endereços IP da interface e todas essas coisas boas.
  • Você precisará fazer o download e configurar ( make menuconfig ) seu próprio kernel personalizado e remover todos os recursos que não estejam relacionados à execução do sistema e da rede. Você vai querer desativar para bloquear a camada, eu não sei como fazer isso em kernels recentes através de make menuconfig .
  • Você então 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 do kernel, isso deve ser fácil para você.
  • Você precisa modificar qualquer parte do kernel que entre em pânico se init falhar em não fazer isso, ou esteja preparado para viver com um processo extra de espaço do usuário.

Eu sei que é possível que os módulos do kernel criem processos - um simples ps aux mostraria muitos em um sistema típico (eles estão todos entre colchetes). Você provavelmente quer 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 encadeamentos [ kthreadd ], o gerenciamento de energia [ pm ], a camada de eventos [ events ] e outros.

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

O Linux tem uma opção de linha de comando do kernel chamada init= - isto é o que o kernel irá iniciar quando terminar de carregar. O programa deve estar no dispositivo raiz especificado com root= ou no initrd (carregado pelo seu bootloader).

Se este programa sair, o Linux entrará em pânico, portanto, certifique-se de que ele nunca saia.

Muitas distribuições modernas do Linux têm sua configuração, portanto, um programa init no initrd faz uma inicialização adicional no espaço do usuário, antes de iniciar o /sbin/init ou /sbin/systemd . Você terá que descobrir o que sua distro faz aqui (a informação para o Debian é aqui ) e encontrar onde você pode especificar o final " handoff ", e de lá você pode dizer para iniciar seu aplicativo em vez de init ou systemd .

systemd gerencia muitas funcionalidades básicas, como a criação de /dev , a definição do nome do host e outras coisas, portanto, se você for flexível, convém configurar systemd para gerar um único processo e, opcionalmente, reinicie se falhar. Se não me engano, basicamente faz isso para um usuário ou modo de recuperação - ele inicia um shell.

Você terá 2 processos em execução ( systemd e seu programa), mas o sistema não entrará em pane se o programa sair ou falhar.

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

    
por 06.12.2011 / 04:15
1

Existem alguns aplicativos do sistema que devem 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 distribuições Linux realmente pequenas, como o TinyCore Linux, etc.

Também dependeria da própria aplicação, quais serviços são necessários além da rede, etc.

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

Como o tipo de aplicativo, etc.

    
por 08.08.2011 / 19:33

Tags