Como um kernel monta a partição raiz?

29

Minha pergunta é com relação à inicialização de um sistema Linux a partir de uma partição / inicialização separada. Se a maioria dos arquivos de configuração está localizada em uma partição / separada, como o kernel o monta corretamente no momento da inicialização?

Qualquer elaboração sobre isso seria ótimo. Sinto como se estivesse perdendo algo básico. Estou principalmente preocupado com o processo e a ordem das operações.

Obrigado!

Edição: Eu acho que o que eu precisava perguntar era mais ao longo das linhas do arquivo dev que é usado no parâmetro raiz do kernel. Por exemplo, digamos que eu forneça meu parâmetro raiz como root = / dev / sda2. Como o kernel possui um mapeamento do arquivo / dev / sda2?

Mr. Shickadance
fonte
Embora as pessoas abaixo cubram o initrd, há pouca discussão sobre por que o initrd é usado. Minha impressão é que isso ocorre porque distribuições como o Debian querem usar um kernel em muitas máquinas diferentes da mesma arquitetura, mas possivelmente em hardware muito diferente. Isso é possível através da modularização do suporte de hardware via módulos do kernel. O initrd não requer muito suporte de hardware para inicializar e, uma vez necessário, carrega os módulos de hardware necessários para prosseguir. Elaborações / correções para isso são apreciadas.
Faheem Mitha 26/03
Você não pode montar / boot sem ter / montado primeiro, pois não há diretório / boot sem /.
Psusi

Respostas:

20

Inicialmente, o Linux inicializa com um ramdisk (chamado initrdde "INITial RamDisk") como /. Este disco possui apenas o suficiente para encontrar a partição raiz real (incluindo os módulos de driver e sistema de arquivos necessários). Ele monta a partição raiz em um ponto de montagem temporário no e initrd, em seguida, chama pivot_root(8)para trocar os pontos de montagem raiz e temporário, deixando a initrdposição em que será umounteditada e o sistema de arquivos raiz real /.

geekosaur
fonte
2
E se você não tiver um initrd como o LFS (linuxfromscratch.org)?
Sr. Shickadance 23/03
@Sr. Shickadance: Não tendo analisado como o LFS faz as coisas, eu acho que eles garantem que o kernel tenha todos os módulos necessários compilados (ou carregados via GRUB 2, que possibilidade é nova o suficiente para que muitas distribuições ainda não o tenham notado). pode iniciar na partição raiz real.
Geekosaur #
4
@Sr. Shickadance. Não é apenas o LFS que não possui um initrd. Qualquer um que compila seu próprio kernel tem a opção de não usar o initrd, que é o que faço no Gentoo.
22611 jonescb
1
@ Faaem: Os módulos grub2 não são iguais aos módulos do kernel. Eu vejo alguma capacidade do grub2 carregar módulos do kernel, mas uma coisa que eu não sei é se isso funcionará para o kernel Linux ou apenas para * BSD (onde o carregador de inicialização que carrega os módulos do kernel é normal). Eu suspeito que o kernel precisa ser ensinado onde encontrar o mapa de endereços para os módulos carregados e todos precisam mudar para o grub2 (o grub1 ainda é padrão em algumas distribuições).
Geekosaur #
1
O initrd foi substituído pelo initramfs, pois o pivot_root foi considerado um hack sujo.
Psusi
41

Nos tempos antigos, o kernel era codificado para conhecer o número principal / menor do dispositivo, os fs raiz e o montou depois de inicializar todos os drivers de dispositivo que foram incorporados ao kernel. O rdevutilitário pode ser usado para modificar o número do dispositivo raiz na imagem do kernel sem precisar recompilar.

Eventualmente, os carregadores de inicialização apareceram e poderiam passar uma linha de comando para o kernel. Se o root=argumento foi passado, isso informava ao kernel onde estava o root fs, em vez do valor incorporado. Os drivers precisavam acessar o que ainda precisava ser incorporado ao kernel. Embora o argumento pareça um nó de dispositivo normal no /devdiretório, obviamente não existe um /devdiretório antes da montagem do root fs, portanto o kernel não pode procurar um nó de desenvolvimento lá. Em vez disso, certos nomes de dispositivos conhecidos são codificados no kernel para que a string possa ser traduzida para o número do dispositivo. Por causa disso, o kernel pode reconhecer coisas como /dev/sda1, mas não coisas mais exóticas, como /dev/mapper/vg0-rootum UUID de volume.

Mais tarde, o initrdentrou em cena. Junto com o kernel, o carregador de inicialização carregava a initrdimagem, que era algum tipo de imagem do sistema de arquivos compactada (imagem ext2 compactada com gzip, imagem romfs compactada com gzip, squashfs finalmente se tornou dominante). O kernel descompactaria essa imagem em um ramdisk e montaria o ramdisk como o root fs. Esta imagem continha alguns drivers adicionais e scripts de inicialização, em vez de reais init. Esses scripts de inicialização executavam várias tarefas para reconhecer hardware, ativar coisas como matrizes de ataque e LVM, detectar UUIDs e analisar a linha de comando do kernel para encontrar a raiz real, que agora poderia ser especificada por UUID, rótulo de volume e outras coisas avançadas. Em seguida, montou o fs raiz real /initrde executou a pivot_rootchamada do sistema para trocar o kernel /e/initrd, em seguida, exec /sbin/initna raiz real, que desmontaria /initrde liberaria o ramdisk.

Finalmente, hoje temos o initramfs. Isso é semelhante ao initrd, mas em vez de ser uma imagem do sistema de arquivos compactada carregada em um ramdisk, é um arquivo cpio compactado. Um tmpfs é montado como raiz e o arquivo é extraído lá. Em vez de usar pivot_root, que era considerado um hack sujo, os initramfsscripts de inicialização montam a raiz real /root, excluem todos os arquivos na raiz tmpfs, depois chrootno /roote exec /sbin/init.

psusi
fonte
1
Após o chroot, os tmpfs são desmontados automaticamente? Isso simplesmente desaparece?
precisa saber é o seguinte
@jiggunjer, no, it is still there, it is just empty ( aside from containing the /root directory ), and no longer used.
psusi
Aprendi algo novo sobre cada iteração de root fs que você mencionou. Ótima resposta!
jpaugh
3

Parece que você está perguntando como o kernel "sabe" qual partição é a partição raiz, sem acesso aos arquivos de configuração em / etc.

O kernel pode aceitar argumentos de linha de comando como qualquer outro programa. O GRUB ou a maioria dos outros gerenciadores de inicialização podem aceitar argumentos de linha de comando como entrada do usuário ou armazená-los e disponibilizar várias combinações de argumentos de linha de comando por meio de um menu. O carregador de inicialização passa os argumentos da linha de comando para o kernel quando o carrega (não sei o nome ou a mecânica desta convenção, mas provavelmente é semelhante à maneira como um aplicativo recebe argumentos da linha de comando de um processo de chamada em um kernel em execução).

Uma dessas opções de linha de comando é rootonde você pode especificar o sistema de arquivos raiz, ou seja root=/dev/sda1.

Se o kernel usa um initrd, o gerenciador de inicialização é responsável por informar ao kernel onde está ou colocar o initrd em um local de memória padrão (eu acho) - é pelo menos assim que funciona no meu Guruplug.

É perfeitamente possível não especificar um e, em seguida, deixar o kernel em pânico imediatamente após começar a reclamar que não consegue encontrar um sistema de arquivos raiz.

Pode haver outras maneiras de passar essa opção para o kernel.

LawrenceC
fonte
3
Esta é a explicação correta quando não há initrd / initramfs, mas está faltando uma peça do quebra-cabeça. Normalmente, o kernel identifica um dispositivo, como /dev/sda1porque é uma entrada em um sistema de arquivos. Você poderia fazer cp -p /dev/sda1 /tmp/fooe /tmp/foorepresentaria o mesmo dispositivo. Na linha de comando do kernel, o kernel usa um analisador interno que segue a convenção usual de nomenclatura de dispositivos: sda1significa a primeira partição do primeiro disco do tipo SCSI.
Gilles 'SO- stop be evil' (
@ Gilles kernels tão modernos ainda não conseguem lidar com a montagem de um volume baseado em UUID? sem initrdou initramfsquero dizer. Tem que ser uma partição "simples" no /dev/sdxformulário?
Jggunjer
1
@jiggunjer Os kernels modernos suportam a pesquisa de um volume pelo UUID. Veja init/do_mounts.c.
Gilles 'SO- stop be evil'
1

O Grub monta a /bootpartição e depois executa o kernel. Na configuração do Grub, ele diz ao kernel o que usar como dispositivo raiz.

Por exemplo, no Grub menu.lst:

kernel /boot/linux root=/dev/sda2
jonescb
fonte
1

Vamos lá, o GRUB não "monta" / inicializa, apenas lê 'menu.lst' e alguns módulos, também não faz parte do kernel do LINUX. Quando você chama o kernel, passa um argumento "root" com a partição raiz. Na pior das hipóteses, o kernel sabe que just / boot foi montado (LOL).

Próximo: geekosaur está certo, o Linux usa um ramdisk inicial no formato de imagem compactada e monta o sistema de arquivos raiz real chamando pivot_root. Portanto, o Linux começa a executar a partir de uma imagem e, em seguida, a partir da sua unidade de disco local.

D4RIO
fonte
1
Definitivamente, o Grub tem a capacidade de 'montar' um sistema de arquivos, especialmente no grub2. Obviamente, tudo o que é capaz de fazer / com isso é procurar kernels inicializáveis ​​de uma faixa ou outra, mas isso ainda está aumentando. Além disso, o linux não requer um initrd, a menos que o seu kernel compile drivers cruciais para o seu disco rígido como módulos.
Shadur 23/03
5
ibm.com/developerworks/linux/library/l-linuxboot Este é um resumo bastante conciso do que o Kernel Linux faz ao inicializar.
Jsbillings
2
@Shadur, na página de manual de montagem : Todos os arquivos acessíveis em um sistema Unix são organizados em uma grande árvore, a hierarquia de arquivos, com raiz em /. Esses arquivos podem ser espalhados por vários dispositivos. O comando mount serve para anexar o sistema de arquivos encontrado em algum dispositivo à grande árvore de arquivos. - Como os sistemas de arquivos usados ​​pelo GRUB não estão anexados à hierarquia de arquivos, NÃO está montando .
D4RIO
1
@Shadur, BTW: É óbvio que o initrd não é necessário, pois é apenas outro sistema de arquivos raiz, mas geralmente é usado como raiz pequena no momento da inicialização, pois o kernel carrega o necessário para inicializar, depois inicializa e finalmente carrega todo o resto.
D4RIO
1
@ d4rio Eles são montados pelo GRUB, não pelo linux - fica mais fácil entender quando você considera o grub como um SO de microkernel próprio, em vez de apenas um gerenciador de inicialização.
Shadur
1

O gerenciador de inicialização, seja grub ou lilo ou qualquer outra coisa, informa ao kernel onde procurar com a root=flag e, opcionalmente, carrega um ramdisk inicial na memória initrdantes de inicializar o kernel.

O kernel é carregado, testa seus drivers de hardware e dispositivo e procura no sistema o que pode ver (você pode revisar essas informações de diagnóstico digitando dmesg; hoje em dia provavelmente rola muito rápido para ver) e tenta montar a partição mencionada em o root=parâmetro

Se um initrd estiver presente, ele será montado primeiro e quaisquer módulos / drivers de dispositivo nele serão carregados e testados antes da montagem do sistema de arquivos raiz. Dessa forma, você pode compilar os drivers para seus discos rígidos como módulos e ainda poder inicializar.

Shadur
fonte