O processo de inicialização pode ser um script de shell no Linux?

10

Eu estava passando por um tutorial sobre sobre a configuração de um initramfs personalizado , onde ele afirma:

The only thing that is missing is /init, the executable in the root of the initramfs that is executed by the kernel once it is loaded. Because sys-apps/busybox includes a fully functional shell, this means you can write your /init binary as a simple shell script (instead of making it a complicated application written in Assembler or C that you have to compile).

e dá um exemplo de init como um script de shell que começa com #!/bin/busybox sh

Até agora, fiquei com a impressão de que o init é o processo principal que é lançado e que todos os outros processos do espaço do usuário são, por fim, filhos do init. No entanto, no exemplo dado, o primeiro processo é, na verdade, bin/busybox/ sh do qual o init posterior é gerado.

Esta é uma interpretação correta? Se eu estivesse, por exemplo, com um intérprete disponível disponível naquele momento, eu poderia escrever o init como um script Python, etc.?

    
por TheMeaningfulEngineer 13.12.2014 / 14:56

2 respostas

11

o init não é "gerado" (como um processo filho), mas sim exec como:

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

exec substitui todo o processo. O init final ainda é o primeiro processo (pid 1), embora tenha sido precedido por aqueles no Initramfs.

O Initramfs /init , que é um script de shell do Busybox com o pid 1, exec s para o Busybox switch_root (então, agora switch_root é pid 1); este programa altera seus pontos de montagem, então /mnt/root será o novo / .

switch_root , em seguida, novamente exec s para /sbin/init do seu sistema de arquivos raiz real; assim, torna o seu sistema init real o primeiro processo com o pid 1, que por sua vez pode gerar qualquer número de processos filhos.

Certamente, também poderia ser feito com um script Python, se você de alguma forma conseguisse assar Python em seu Initramfs. Embora se você não planeja incluir o busybox de qualquer maneira, você teria que reimplementar meticulosamente algumas de suas funcionalidades (como switch_root e tudo mais que você usaria normalmente com um simples comando).

No entanto, ele não funciona em kernels que não permitem binários de script ( CONFIG_BINFMT_SCRIPT=y ), ou melhor, nesse caso, você teria que iniciar o interpretador diretamente e fazê-lo carregar seu script de alguma forma.

    
por 13.12.2014 / 15:16
4

O syscall exec do kernel do Linux subestima as diferenças nativas

Quando o arquivo executado começa com os bytes mágicos #! , eles dizem ao kernel para usar #!/bin/sh as:

  • faça e exec chamada do sistema
  • com executável /bin/sh
  • e com o argumento da CLI: caminho para o script atual

Isso é exatamente o mesmo que acontece quando você executa um script de shell de usuário comum com:

./myscript.sh

Se o arquivo tivesse começado com os bytes mágicos .ELF em vez de #! , o kernel escolheria o carregador ELF para executá-lo.

Mais detalhes em:

Uma vez que você tenha isso em mente, é fácil aceitar que /init pode ser qualquer coisa que o kernel possa executar, incluindo um shell script, e também porque /bin/sh será o primeiro executável nesse caso.

Aqui está um exemplo mínimo executável para aqueles que querem experimentá-lo: link

    
por 30.09.2017 / 21:55