É uma pergunta sobre aplicativos de espaço do usuário, mas ouça!
Três "aplicativos", por assim dizer, são necessários para inicializar uma distribuição funcional do Linux:
Carregador de Inicialização - Para embutido, tipicamente isso é U-Boot, embora não seja um requisito difícil.
Kernel - Isso é bem direto.
Sistema de arquivos raiz - Não é possível inicializar em um shell sem ele. Contém o sistema de arquivos no qual o kernel inicializa e onde
init
é chamado de formulário.
Minha pergunta é em relação ao item 3. Se alguém quisesse criar um rootfs extremamente mínimo (para esta pergunta, digamos que não haja GUI, apenas shell), quais arquivos / programas são necessários para inicializar em um shell?
linux
embedded
startup
architecture
root-filesystem
MDMoore313
fonte
fonte
Respostas:
Isso depende inteiramente de quais serviços você deseja ter no seu dispositivo.
Programas
Você pode fazer o Linux inicializar diretamente em um shell . Não é muito útil na produção - quem apenas gostaria de ter um shell - mas é útil como mecanismo de intervenção quando você tem um gerenciador de inicialização interativo: passe
init=/bin/sh
para a linha de comando do kernel. Todos os sistemas Linux (e todos os sistemas unix) possuem um shell no estilo Bourne / POSIX/bin/sh
.Você precisará de um conjunto de utilitários de shell . BusyBox é uma escolha muito comum; ele contém um shell e utilitários comuns de arquivo e manipulação de texto (
cp
,grep
...), configuração de rede (ping
,ifconfig
...), manipulação de processo (ps
,nice
...), e várias outras ferramentas de sistema (fdisk
,mount
,syslogd
, ...). O BusyBox é extremamente configurável: você pode selecionar quais ferramentas deseja e até recursos individuais em tempo de compilação, para obter o tamanho / funcionalidade certos para o seu aplicativo. Além desh
, o mínimo que você realmente não pode fazer nada sem émount
,umount
ehalt
, mas seria atípico para não ter tambémcat
,cp
,mv
,rm
,mkdir
,rmdir
,ps
,sync
E um pouco mais. O BusyBox é instalado como um único binário chamadobusybox
, com um link simbólico para cada utilitário.O primeiro processo em um sistema unix normal é chamado
init
. Seu trabalho é iniciar outros serviços. BusyBox contém um sistema init. Além doinit
binário (geralmente localizado em/sbin
), você precisará de seus arquivos de configuração (geralmente chamados/etc/inittab
- algumas substituições init modernas eliminam esse arquivo, mas você não os encontrará em um pequeno sistema embutido) que indicam quais serviços iniciar e quando. Para o BusyBox,/etc/inittab
é opcional; se estiver ausente, você obtém um shell raiz no console e o script/etc/init.d/rcS
(local padrão) é executado no momento da inicialização.É tudo o que você precisa, além dos programas que tornam seu dispositivo útil. Por exemplo, no meu roteador doméstico executando uma variante OpenWrt , os únicos programas são o BusyBox
nvram
(para ler e alterar as configurações na NVRAM) e os utilitários de rede.A menos que todos os seus executáveis estejam vinculados estaticamente, você precisará do carregador dinâmico (
ld.so
que pode ser chamado por nomes diferentes, dependendo da escolha da libc e das arquiteturas do processador) e de todas as bibliotecas dinâmicas (/lib/lib*.so
talvez algumas delas/usr/lib
) exigidas por esses executáveis.Estrutura de diretórios
O padrão de hierarquia de sistemas de arquivos descreve a estrutura de diretórios comum dos sistemas Linux. Ele é voltado para instalações de desktop e servidor: muitas delas podem ser omitidas em um sistema incorporado. Aqui está um mínimo típico.
/bin
: programas executáveis (alguns podem estar no/usr/bin
lugar)./dev
: nós do dispositivo (veja abaixo)/etc
: arquivos de configuração/lib
: bibliotecas compartilhadas, incluindo o carregador dinâmico (a menos que todos os executáveis estejam vinculados estaticamente)/proc
: ponto de montagem para o sistema de arquivos proc/sbin
: programas executáveis. A diferença/bin
é que/sbin
é para programas que são úteis apenas ao administrador do sistema, mas essa distinção não é significativa em dispositivos incorporados. Você pode criar/sbin
um link simbólico para/bin
./mnt
: prático para ter em sistemas de arquivos raiz somente leitura como um ponto de montagem inicial durante a manutenção/sys
: ponto de montagem para o sistema de arquivos sysfs/tmp
: local para arquivos temporários (geralmente umatmpfs
montagem)/usr
: Contém subdiretóriosbin
,lib
esbin
./usr
existe para arquivos extras que não estão no sistema de arquivos raiz. Se você não tiver isso, poderá criar/usr
um link simbólico para o diretório raiz.Arquivos de dispositivo
Aqui estão algumas entradas típicas em um mínimo
/dev
:console
full
(escrever nele sempre informa "não resta espaço no dispositivo")log
(um soquete que os programas usam para enviar entradas de log), se você tiver umsyslogd
daemon (como o do BusyBox) lendonull
(age como um arquivo sempre vazio)ptmx
e umpts
diretório , se você quiser usar pseudo-terminais (ou seja, qualquer outro terminal que não seja o console) - por exemplo, se o dispositivo estiver em rede e você desejar telnet ou sshrandom
(retorna bytes aleatórios, corre o risco de bloquear)tty
(sempre designa o terminal do programa)urandom
(retorna bytes aleatórios, nunca bloqueia, mas pode ser não aleatório em um dispositivo recém-inicializado)zero
(contém uma sequência infinita de bytes nulos)Além disso, você precisará de entradas para o seu hardware (exceto interfaces de rede, elas não recebem entradas
/dev
): portas seriais, armazenamento etc.Para dispositivos incorporados, você normalmente criaria as entradas do dispositivo diretamente no sistema de arquivos raiz. Os sistemas high-end têm um script chamado
MAKEDEV
para criar/dev
entradas, mas em um sistema incorporado o script geralmente não é empacotado na imagem. Se algum hardware puder ser conectado a quente (por exemplo, se o dispositivo tiver uma porta host USB), ele/dev
deverá ser gerenciado pelo udev (você ainda pode ter um conjunto mínimo no sistema de arquivos raiz).Ações de inicialização
Além do sistema de arquivos raiz, você precisa montar um pouco mais para a operação normal:
/proc
(praticamente indispensável)/sys
(praticamente indispensável)tmpfs
sistema de arquivos ativado/tmp
(para permitir que os programas criem arquivos temporários que estarão na RAM, em vez de no sistema de arquivos raiz que pode estar em flash ou somente leitura)/dev
se dinâmico (consulte udev em “Arquivos de dispositivo” acima)/dev/pts
se você quiser usar pseudo-terminais [(ver a observação sobrepts
acima)Você pode criar um
/etc/fstab
arquivo e ligarmount -a
ou executarmount
manualmente.Inicie um daemon syslog (assim como
klogd
para logs do kernel, se osyslogd
programa não cuidar disso), se você tiver algum lugar para gravar os logs.Depois disso, o dispositivo está pronto para iniciar serviços específicos do aplicativo.
Como criar um sistema de arquivos raiz
Esta é uma história longa e diversificada, então tudo o que farei aqui é dar algumas dicas.
O sistema de arquivos raiz pode ser mantido na RAM (carregada de uma imagem (geralmente compactada) em ROM ou flash) ou em um sistema de arquivos baseado em disco (armazenado em ROM ou flash) ou carregado na rede (geralmente através de TFTP ), se aplicável . Se o sistema de arquivos raiz estiver na RAM, torne-o initramfs - um sistema de arquivos RAM cujo conteúdo é criado no momento da inicialização.
Existem muitas estruturas para montar imagens raiz para sistemas incorporados. Existem algumas dicas na FAQ do BusyBox . O Buildroot é popular, permitindo criar uma imagem raiz inteira com uma configuração semelhante ao kernel do Linux e ao BusyBox. OpenEmbedded é outra dessas estruturas.
A Wikipedia possui uma lista (incompleta) de distribuições Linux embarcadas populares . Um exemplo de Linux incorporado que você pode ter perto de você é a família de sistemas operacionais OpenWrt para dispositivos de rede (popular nos roteadores domésticos dos consertadores). Se você quer aprender por experiência, pode experimentar o Linux a partir do Scratch , mas é voltado para sistemas de desktop para entusiastas do que para dispositivos embarcados.
Uma observação sobre o kernel Linux vs Linux
O único comportamento inserido no kernel do Linux é o primeiro programa lançado no momento da inicialização. (Não abordarei as sutilezas do initrd e initramfs aqui.) Este programa, tradicionalmente chamado de init , possui o ID do processo 1 e possui certos privilégios (imunidade a sinais KILL ) e responsabilidades (colher órfãos ). Você pode executar um sistema com um kernel Linux e iniciar o que quiser como primeiro processo, mas o que você tem é um sistema operacional baseado no kernel Linux, e não o que normalmente é chamado de "Linux" - Linux , no senso comum do termo, é um sistema operacional semelhante ao Unix cujo kernel é o kernel Linux. Por exemplo, o Android é um sistema operacional que não é semelhante ao Unix, mas baseado no kernel do Linux.
fonte
Tudo o que você precisa é de um executável vinculado estaticamente, colocado no sistema de arquivos, isoladamente. Você não precisa de outros arquivos. Esse executável é o processo de inicialização. Pode ser ocupado. Isso fornece um shell e uma série de outros utilitários, por si só. Você pode acessar um sistema totalmente funcional apenas executando comandos manualmente no busybox para montar a leitura / gravação do sistema de arquivos raiz, criar nós / dev, exec real init etc.
fonte
Se você não precisar de nenhum utilitário de shell, um
mksh
binário vinculado estaticamente (por exemplo, contra o klibc - 130K no Linux / i386) será necessário. Você precisa de um/linuxrc
ou/init
ou/sbin/init
script que apenas chamemksh -l -T!/dev/tty1
em um loop:A
-T!$tty
opção é uma adição recente aomksh
que diz para gerar um novo shell no terminal fornecido e aguardar por ele. (Antes disso, havia apenas-T-
a dæmonise um programm e-T$tty
para desovar em um terminal, mas não espere por isso. Isso não era tão bom.) A-l
opção simplesmente diz-lhe para executar um shell de login (que lê/etc/profile
,~/.profile
e~/.mkshrc
).Isso pressupõe que seu terminal seja
/dev/tty1
substituto. (Com mais magia, o terminal pode ser descoberto automaticamente./dev/console
Não oferece controle total do trabalho.)Você precisa de alguns arquivos
/dev
para que isso funcione:A inicialização com a opção kernel
devtmpfs.mount=1
elimina a necessidade de um preenchimento/dev
, apenas seja um diretório vazio (adequado para uso como ponto de montagem).Você normalmente deseja ter alguns utilitários (do klibc, busybox, beastiebox, toybox ou toolbox), mas eles não são realmente necessários.
Você pode querer adicionar um
~/.mkshrc
arquivo, que configure $ PS1 e alguns aliases e funções básicos do shell.Certa vez, criei um initrd compactado de 171K (371K não compactado) para Linux / m68k usando mksh (e seu arquivo mkshrc de amostra) e apenas o klibc-utils. (Isso foi antes de -T! Ser adicionado ao shell, no entanto, ele gerou o shell de login
/dev/tty2
e ecoou uma mensagem no console informando ao usuário para alternar terminais.) Funciona bem.Esta é uma configuração mínima realmente simples . As outras respostas fornecem conselhos excelentes para sistemas um pouco mais destacados. Isso é realmente um caso especial.
Disclaimer: Eu sou o desenvolvedor mksh.
fonte
mksh
.Programa mínimo init hello world passo a passo
Compile um olá mundo sem dependências que terminem em um loop infinito.
init.S
:Não podemos usar
sys_exit
, senão o kernel entra em pânico.Então:
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 arquivosd/
e eles seriam acessíveis a partir do/init
programa quando o kernel for executado.Em seguida,
cd
na árvore do kernel do Linux, build é como de costume e execute-o no QEMU:E você deve ver uma linha:
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:
com:
Você pode executar em hardware real com um USB ligado
/dev/sdX
e:Ó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: https://github.com/cirosantilli/runlinux
Testado no Ubuntu 16.10, QEMU 2.6.1.
fonte