Como um kernel monta a partição raiz?

24

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

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

Obrigado!

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

    
por Mr. Shickadance 23.03.2011 / 13:26

6 respostas

17

Inicialmente o Linux é inicializado com um ramdisk (chamado initrd , para "INITial RamDisk") como / . Este disco tem apenas o suficiente para poder 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 initrd e invoca pivot_root(8) para trocar os pontos de montagem raiz e temporários, deixando o initrd em uma posição para ser umount ed e o sistema de arquivos raiz real / .

    
por 23.03.2011 / 13:31
38

Nos tempos antigos, o kernel era codificado para saber o número principal / secundário do dispositivo do root fs e montá-lo depois de inicializar todos os drivers de dispositivo, que foram embutidos no kernel. O utilitário rdev poderia ser usado para modificar o número do dispositivo raiz na imagem do kernel sem ter que recompilá-lo.

Eventualmente, os carregadores de boot apareceram e puderam passar uma linha de comando para o kernel. Se o argumento root= foi passado, isso disse ao kernel onde a raiz fs estava em vez do valor interno. Os drivers necessários para o acesso ainda precisavam ser incorporados ao kernel. Embora o argumento pareça um nó de dispositivo normal no diretório /dev , obviamente não há diretório /dev antes de a raiz fs ser montada, portanto, o kernel não pode procurar um nó dev lá. Em vez disso, determinados nomes de dispositivos conhecidos são codificados para o kernel, de modo 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-root ou um volume UUID.

Mais tarde, o initrd entrou na foto. Juntamente com o kernel, o gerenciador de partida carregaria a imagem initrd , que era algum tipo de imagem do sistema de arquivos compactado (imagem ext2 gzipada, imagem romfs gzipada, squashfs finalmente se tornou dominante). O kernel iria descompactar esta imagem em um ramdisk e montar o ramdisk como root fs. Esta imagem continha alguns drivers adicionais e scripts de inicialização em vez de um init real. Esses scripts de inicialização executaram várias tarefas para reconhecer hardware, ativar itens como raid arrays e LVM, detectar UUIDs e analisar a linha de comando do kernel para encontrar a raiz real, que agora poderia ser especificada pelo UUID, rótulo de volume e outros itens avançados. Em seguida, montou a raiz real fs em /initrd e, em seguida, executou a chamada de sistema pivot_root para que o kernel trocasse / e /initrd , depois exec /sbin/init na raiz real, o que desmontaria /initrd e libere o ramdisk.

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

    
por 04.08.2011 / 16:58
3

Parece que você está perguntando como o kernel "sabe" qual partição é a partição raiz, sem acesso a 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, pode aceitar argumentos de linha de comando como entrada do usuário ou armazená-los e fazer várias combinações de argumentos de linha de comando disponíveis por meio de um menu. O bootloader passa os argumentos da linha de comando para o kernel quando o carrega (não sei o nome ou a mecânica dessa convenção, mas é provavelmente semelhante a como um aplicativo recebe argumentos de linha de comando de um processo de chamada em um kernel em execução). / p>

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

Se o kernel usa um initrd, o bootloader é responsável por dizer ao kernel onde ele está, ou colocar o initrd em um local de memória padrão (eu acho) - é pelo menos do jeito que funciona no meu Guruplug.

É inteiramente possível não especificar um e depois ter o kernel em pânico imediatamente depois de começar a reclamar que não é possível encontrar um sistema de arquivos raiz.

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

    
por 23.03.2011 / 16:19
1

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

Por exemplo, em menu.lst :

do Grub
kernel /boot/linux root=/dev/sda2
    
por 23.03.2011 / 13:29
1

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

A seguir: geekosaur está certo, o Linux usa um ramdisk inicial em formato de imagem compactado e monta o sistema de arquivos raiz real chamando pivot_root . Então o Linux começa a correr a partir de uma imagem e depois a partir da sua unidade de disco local.

    
por 23.03.2011 / 13:46
1

O gerenciador de partida, seja grub ou lilo ou qualquer outra coisa, diz ao kernel onde procurar com o root= , e opcionalmente carrega um ramdisk inicial na memória via initrd antes de inicializar o kernel.

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

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

    
por 23.03.2011 / 13:54