Liberando o initramfs ram depois de alternar a raiz ao usar o overlayfs?

6

Estou criando uma imagem de inicialização personalizada do Live Linux com base no Arch Linux. Eu modifiquei o initrd de ações para conter um script personalizado que faz o seguinte:

  • Após a inicialização, apenas o initramfs existe. Primeiro localizo e monto a própria mídia de inicialização em /image .
  • Em seguida, montei meu sistema de arquivos raiz do squashfs em /ro .
  • Em seguida, montei um tmpfs em /rw e crie os diretórios data e work nesse diretório.
  • Por fim, monto um overlayfs usando /ro como camada inferior, /rw/data como camada superior e /rw/work como o diretório de trabalho. Eu monto este overlayfs em /new_root .
  • Agora uso switch_root para alternar para /new_root e continuar a inicialização.

O problema com essa abordagem é que o conteúdo do initramfs permanece na RAM depois que o sistema é inicializado.

Existe alguma maneira de refazer o processo de tal forma que, depois de mudar para a raiz real, o initramfs possa ser removido da memória? A razão pela qual isso é importante é que eu estou tentando inicializar meu live Linux em uma pequena máquina de memória (192MB) e o tamanho do initrd (eu o baseei em initramfs-fallback) significa que depois que tudo foi inicializado, eu tenho apenas 30MB de RAM livre. Em contraste, um Arch Linux instalado típico utilizará apenas 18MB de RAM. Isso indica para mim que o initramfs descompactado (cerca de 66MB) definitivamente ainda está na RAM, junto com outros 66MB ou mais de RAM, dos quais não consigo descobrir o uso. (Talvez por algum motivo o initramfs esteja realmente duplicado na RAM?)

Eu poderia obviamente diminuir meu initramfs (estou trabalhando para descobrir como especificar módulos específicos para incluir no pacote), mas mesmo assim, um grande pedaço de RAM permanecerá usado após a inicialização em sistemas de pouca memória.

EDIT: Tentei retrabalhar meus initramfs para simplesmente montar um tmpfs em /image e, em seguida, o script cria os diretórios rw , ro e work dentro de /image . Em seguida, o script faz as montagens e monta o overlayfs em /new_root . O resultado é exatamente o mesmo - o uso de RAM é aproximadamente o dobro do tamanho do initramfs mais os executáveis reais na RAM.

Eu solicitei uma quebra de pré-montagem e, nesse estágio, apenas o tamanho do initramfs é usado na RAM - isso faz sentido. Em seguida, solicitei uma pausa pós-montagem e descobri que o uso de RAM era o dobro do que observei no sistema inicializado. Então parece que algo nas várias montagens está causando o uso da RAM. Vou tentar rastrear o processo adicionando os comandos free e sleep aos scripts initrd para ver se consigo isolar qual comando está causando o uso da memória ...

EDITAR NOVAMENTE: Então, o culpado pelo uso da "dupla" RAM foi o SquashFS. Então, parece que eu devo recomprimir o sistema de arquivos usando o gzip em vez de usar o lzma. Ok, parte do mistério resolvido.

Mas isso ainda não lida com o initramfs que continua a usar RAM depois que a raiz é trocada. Então, isso ainda é um mistério.

Eu estou querendo saber se talvez o kernel tente desmontar o initramfs internamente, mas não pode fazê-lo porque há coisas montadas nele? Mas isso não faria sentido porque você sempre tem algo montado fora do initramfs antes de você mudar o root de qualquer maneira ...

    
por fdmillion 10.05.2017 / 21:09

2 respostas

2

Estou assumindo que você está se referindo ao "rootfs". E não, não há como se livrar disso. A documentação do kernel menciona especificamente isso: link

Rootfs is a special instance of ramfs (or tmpfs, if that's enabled), which is always present in 2.6 systems. You can't unmount rootfs for approximately the same reason you can't kill the init process; rather than having special code to check for and handle an empty list, it's smaller and simpler for the kernel to just make sure certain lists can't become empty.

Most systems just mount another filesystem over rootfs and ignore it. The amount of space an empty instance of ramfs takes up is tiny.

Você também não precisa se preocupar com a limpeza de rootfs . Consulte a documentação do switch_root : link

WARNING: switch_root removes recursively all files and directories on the current root filesystem.

Além disso, voltando à documentação do kernel, um pouco abaixo da documentação referenciada "rootfs" está outra sinopse que reitera os 2 pontos acima:

  • When switching another root device, initrd would pivot_root and then umount the ramdisk. But initramfs is rootfs: you can neither pivot_root rootfs, nor unmount it. Instead delete everything out of rootfs to free up the space (find -xdev / -exec rm '{}' ';'), overmount rootfs with the new root (cd /newmount; mount --move . /; chroot .), attach stdin/stdout/stderr to the new /dev/console, and exec the new init.

    Since this is a remarkably persnickety process (and involves deleting commands before you can run them), the klibc package introduced a helper program (utils/run_init.c) to do all this for you. Most other packages (such as busybox) have named this command "switch_root".

    
por 11.05.2017 / 06:42
0

Assim, por qualquer motivo, o problema parece ser que, se você montar qualquer coisa no initramfs diferente de /new_root ou qualquer outra coisa que tenha sido pré-montada, o initramfs não é apagado da memória . Não faço ideia do porquê.

Então eu olhei os scripts no ISO de inicialização do Arch Linux e descobri que ele basicamente faz algo parecido com a minha ideia, mas está criando todos os diretórios de montagem temporária em /run . Como /run é um tmpfs para começar, isso acaba salvando alguns passos de qualquer maneira.

Adaptando meus scripts para fazer o mesmo, finalmente consegui criar um ISO que inicializa em 128MB de RAM e deixa 80MB de RAM livre para aplicativos. Não é ruim.

Portanto, o truque é montar tudo o que você precisa para montar em / run , e então switch_root deve limpar corretamente o sistema de arquivos raiz.

    
por 12.05.2017 / 04:57