Por Dentro do Processo de Inicialização do Linux

Faça uma visita monitorada, do Master Boot Record até o primeiro aplicativo de espaço do usuário

O processo de inicialização de um sistema Linux® consiste de diversos estágios. Mas quando se efetua boot em um desktop x86 padrão ou um destino do PowerPC fortemente embarcado®, muito de seu fluxo tem uma semelhança surpreendente. Este artigo abrange o processo de boot do Linux, desde a primeira autoinicialização até o início do primeiro aplicativo de espaço do usuário. Nesse artigo, serão vistos vários outros tópicos relacionados ao boot, como os loaders de boot, a descompactação de kernels, o disco RAM inicial e outros elementos de boot do Linux.

M. Tim Jones, Consultant Engineer, Emulex Corp.

M. Tim JonesM. Tim Jones é um arquiteto de firmwares embarcados e autor de Inteligência Artificial: Sistemas de Abordagem, GNU/Linux, Programação de Aplicativos AI (atualmente em sua segunda edição), Programação de Aplicativos AI (em sua segunda edição) e BSD Sockets Programming from a Multilanguage Perspective. Sua formação em engenharia vai desde o desenvolvimento de kernels para nave espacial geossincrônica até a arquitetura de sistema embarcado e o desenvolvimento de protocolos de interligação de redes. Tim é um Engenheiro Consultor para a Emulex Corp. em Longmont, Colorado.



16/Mai/2014

Antigamente, para autoinicializar um computador, era preciso alimentar uma fita de papel que continha um programa de boot ou carregar manualmente um programa de boot utilizando os controles de endereço do painel frontal/dados/controle. Os computadores atuais são equipados com recursos que simplificam o processo de boot, embora não necessariamente o deixem mais simples.

Vamos começar com uma visualização de alto nível de boot do Linux para que se tenha uma visão geral. Em seguida, revisaremos o que ocorre separadamente em cada uma das etapas. As referências de origem durante esse processo o ajudarão a navegar pela árvore de kernel e a entender melhor esse processo.

Visão Geral

A Figura 1 mostra uma visualização estratégica.

Figura 1. Visualização Estratégica do Processo de Inicialização do Linux

Quando um sistema efetua boot pela primeira vez, o processador executa um código em um local conhecido. Em um Computador Pessoal (PC), esse local é o Sistema Básico de Entrada/Saída (BIOS), que está armazenado na memória flash, na placa-mãe. A Unidade Central de Processamento (CPU) em um sistema embarcado solicita ao vetor de reconfiguração que inicie um programa em um endereço conhecido em flash/ROM. Nos dois casos, o resultado é o mesmo. Como os PCs oferecem bastante flexibilidade, o BIOS precisa determinar quais dispositivos são candidatos ao boot. Examinaremos isso posteriormente com mais detalhes.

Quando um dispositivo de boot é encontrado, o loader de boot de primeiro estágio é carregado na RAM e executado. Esse loader de boot tem menos de 512 bytes (um único setor), e sua tarefa é carregar o loader de boot de segundo estágio.

Quando o loader de boot de segundo estágio está na RAM e em execução, uma tela inicial é geralmente exibida e o Linux e o disco RAM inicial opcional (sistema de arquivo raiz temporário) são carregados na memória. Quando as imagens são carregadas, o loader de boot de segundo estágio passa o controle para a imagem do kernel e o kernel é descompactado e inicializado. Neste estágio, o loader de boot de segundo estágio verifica o hardware do sistema, enumera os dispositivos de hardware anexados, monta o dispositivo raiz e, em seguida, carrega os módulos de kernel necessários. Ao ser concluído, o primeiro programa de espaço de usuário (init) inicia e a inicialização do sistema de alto nível é executada.

Em resumo, é assim que funciona o boot do Linux. Agora vamos prosseguir e explorar alguns dos detalhes do processo de boot do Linux.


Inicialização do Sistema

O estágio de inicialização do sistema depende do hardware no qual o Linux está efetuando boot. Em uma plataforma integrada, um ambiente de autoinicialização é utilizado quando o sistema é ligado ou reconfigurado. Como exemplos, temos U-Boot, RedBoot e MicroMonitor da Lucent. As plataformas integradas normalmente vêm de fábrica com um monitor de boot. Esses programas residem em uma região especial da memória flash no hardware de destino e fornecem os meios para fazer download de uma imagem do kernel Linux na memória flash e, em seguida, executá-la. Além da capacidade de armazenar e executar boot em uma imagem do Linux, esses monitores de inicialização executam alguns níveis de teste do sistema e a inicialização do hardware. Em um destino embarcado, esses monitores de inicialização costumam abranger os loaders de boot de primeiro e de segundo estágios.

Extraindo o MBR

Para ver o conteúdo de seu MBR, utilize o comando:

# dd if=/dev/hda of=mbr.bin bs=512 count=1
# od -xa mbr.bin

O comando dd, que precisa ser executado a partir da raiz, lê os primeiros 512 bytes de /dev/hda (a primeira unidade Integrated Drive Electronics ou IDE) e os grava no arquivo mbr.bin. O comando od imprime o arquivo binário nos formatos hex e ASCII.

Em um PC, o processo de inicialização do Linux começa no BIOS, em 0xFFFF0. A primeira etapa do BIOS é Power-On Self Test (POST). A tarefa do POST é executar uma verificação do hardware. A segunda etapa do BIOS é enumerar e inicializar o dispositivo local.

Dados os diferentes usos das funções do BIOS, temos duas partes: o código POST e os serviços de tempo de execução. Depois de concluído, o POST é apagado da memória, mas os serviços de tempo de execução do BIOS permanecem e ficam disponíveis ao sistema operacional de destino.

Para inicializar um sistema operacional, o tempo de execução do BIOS procura por dispositivos ativos e inicializáveis na ordem de preferência definida pelas configurações de Complementary Metal Oxide Semiconductor (CMOS). Um dispositivo de boot pode ser um disco flexível, um CD-ROM, uma partição de um disco rígido, um dispositivo na rede ou até mesmo um memory stick flash USB.

Normalmente, o Linux tem boot executado a partir de um disco rígido, onde Master Boot Record (MBR) contém o loader de boot primário. O MBR é um setor de 512 bytes, localizado no primeiro setor do disco (setor 1 do cilindro 0, cabeçote 0). Depois que o MBR é carregado na RAM, os campos do BIOS o controlam.


Loader de Boot de Estágio 1

O loader de boot primário, que reside no MBR, é uma imagem de 512 bytes contendo o código do programa e uma pequena tabela de partição (consulte a Figura 2). Os primeiros 446 bytes são o loader de boot primário, que contém o código executável e um texto de mensagem de erro. Os 64 bytes seguintes formam a tabela de partição, que contém um registro para cada uma das quatro partições (cada uma com 16 bytes). O MBR termina com dois bytes, que são definidos como o número mágico (0xAA55). O número mágico funciona como verificação de validação do MBR.

Figura 2. Anatomia do MBR

A função do loader de boot primário é encontrar e carregar o loader de boot secundário (estágio 2). Isso é feito consultando a tabela particionada de uma partição ativa. Ao localizar uma partição ativa, ele faz uma varredura das partições restantes na tabela, a fim de certificar-se de que todas estão inativas. Quando isso é verificado, o registro de boot da partição ativa é lido a partir do dispositivo para a RAM e executado.


Loader de Boot de Estágio 2

O loader de boot secundário, ou de segundo estágio, pode ser chamado de loader de kernel. Neste estágio, sua tarefa é carregar o kernel Linux e o disco RAM inicial opcional.

Loaders de Boot de Estágio GRUB

O diretório /boot/grub contém os loaders de boot stage1, stage1.5, e stage2, bem como diversos loaders alternativos (por exemplo, os CR-ROMs usam iso9660_stage_1_5).

Os loaders de boot de primeiro e segundo estágios combinados são chamados de Linux Loader (LILO) ou GRand Unified Bootloader (GRUB) no ambiente x86 do PC. Como o LILO apresenta algumas desvantagens que foram corrigidas no GRUB, vejamos o GRUB. (Consulte muitos recursos adicionais sobre GRUB, LILO e tópicos relacionados na seção Recursos, mais adiante neste artigo.)

O ponto alto do GRUB é que ele inclui o conhecimento dos sistemas de arquivo Linux. Em vez de utilizar setores brutos no disco, como o LILO faz, o GRUB pode carregar um kernel Linux a partir de um sistema de arquivos ext2 ou ext3. Isso é feito transformando o loader de boot de dois estágios em um de três estágios. O estágio 1 executa boot em um loader de boot de estágio intermediário (1,5), que compreende o sistema de arquivos específico, contendo a imagem do kernel Linux. Como exemplos, temos reiserfs_stage1_5 (para carregar a partir de um sistema de arquivos com registro de mudanças Reiser) ou e2fs_stage1_5 (para carregar a partir de um sistema de arquivos ext2 ou ext3). Quando o loader de boot do estágio intermediário estiver carregado e em execução, o loader de boot do estágio 2 poderá ser carregado.

Quando o estágio 2 estiver carregado, o GRUB poderá, mediante solicitação, exibir uma lista dos kernels disponíveis (definidos em /etc/grub.conf, com soft links de /etc/grub/menu.lst e /etc/grub.conf). É possível selecionar um kernel e até aditá-lo com parâmetros adicionais de kernel. Opcionalmente, é possível utilizar shell de linha de comandos para obter um maior controle manual sobre o processo de boot.

Com o loader de boot de segundo estágio na memória, o sistema de arquivos é consultado e a imagem de kernel padrão e a imagem initrd são carregadas na memória. Com as imagens prontas, o loader de boot de estágio 2 chama a imagem de kernel.


Kernel

Boot Manual no GRUB

A partir da linha de comandos do GRUB, é possível executar boot em um kernel específico com uma imagem initrd nomeada, como a seguir:

grub> kernel /bzImage-2.6.14.2
   [Linux-bzImage, setup=0x1400, size=0x29672e]

grub> initrd /initrd-2.6.14.2.img
   [Linux-initrd @ 0x5f13000, 0xcc199 bytes]

grub> boot

Descompactando Linux... Ok, executando boot no kernel.

Se não souber o nome do kernel que será executado o boot, aperte a barra (/) e pressione a tecla Tab. O GRUB exibirá a lista de kernels e imagens initrd.

Com a imagem de kernel na memória e o controle fornecido no loader de boot de estágio 2, o estágio do kernel começa. A imagem do kernel não é bem um kernel executável, mas uma imagem de kernel compactada. Em geral é uma zImage (imagem compactada, com menos de 512KB) ou uma bzImage (imagem compactada grande, com mais de 512KB), previamente compactada com zlib. No início dessa imagem de kernel há uma rotina que executa uma quantidade mínima de configurações de hardware e, em seguida, descompacta o kernel contido na imagem de kernel, deixando-o com bastante memória. Se houver uma imagem de disco RAM inicial, essa rotina vai para a memória e a usa futuramente. A rotina chama então o kernel e a execução de seu boot é iniciada.

Quando bzImage (para uma imagem i386) é chamada, você inicia em ./arch/i386/boot/head.S na rotina de montagem start (consulte a Figura 3 para o fluxo principal). Essa rotina efetua algumas configurações básicas de hardware e chama a rotina startup_32 em ./arch/i386/boot/compressed/head.S. Essa rotina configura um ambiente básico (pilha, etc.) e limpa o Block Started by Symbol (BSS). Em seguida, o kernel é descompactado por meio de uma chamada à uma função C, denominada decompress_kernel (localizada em ./arch/i386/boot/compressed/misc.c). Quando o kernel é descompactado na memória, ele é chamado. Esta é ainda outra função startup_32, mas essa função está em ./arch/i386/kernel/head.S.

Na nova função startup_32 (também denominada swapper ou processo 0), as tabelas de páginas são inicializadas e a paginação de memória é ativada. É detectado o tipo de CPU, junto com qualquer Unidade Opcional de Ponto Flutuante (FPU), e são armazenados para uso futuro. A função start_kernel é então chamada (init/main.c), o levando ao kernel Linux que especificamente não faz parte da arquitetura. Isto é, basicamente, a função main do kernel Linux.

Figura 3. As Funções Principais Fluem para o Boot do Kernel i386 Linux

Ao chamar start_kernel, uma lista grande de funções de inicialização é chamada para configurar interrupções, executar configuração de memória adicional e carregar o disco RAM inicial. Ao final, faz-se uma chamada para kernel_thread (em arch/i386/kernel/process.c) para iniciar a função init, que é o primeiro processo de espaço do usuário. Por fim, a tarefa ociosa é iniciada e o planejador agora pode assumir o controle (depois da chamada para cpu_idle). Com as interrupções ativadas, o planejador antecipado assume periodicamente o controle para fornecer várias tarefas.

Durante a inicialização do kernel, o disco RAM inicial (initrd) que havia sido carregado na memória no loader de boot de estágio 2 é copiado na RAM e montado. Essa série initrd atua como um sistema de arquivos raiz temporário na RAM e permite que o kernel execute boot totalmente, sem precisar montar nenhum disco físico. Como os módulos necessários para fazer interface com os periféricos podem fazer parte de initrd, o kernel pode ser muito pequeno, mas ainda oferecer suporte a um grande número de configurações possível de hardware. Depois que o kernel executa boot, o sistema de arquivos raiz é dinamizado (por meio de pivot_root), no qual o sistema de arquivos raiz initrd é desmontado e o sistema de arquivos raiz real é montado.

Saída decompress_kernel

A função decompress_kernel é onde você vê as mensagens de descompactação usuais emitidas para o monitor:

Descompactando Linux... Ok, executando boot no kernel.

A função initrd permite criar um pequeno kernel de Linux com drivers compilados como módulos carregáveis. Esses módulos carregáveis possibilitam que o kernel tenha meios de acesso aos discos e aos sistemas de arquivos desses discos, bem como aos drivers de outros recursos de hardware. Como o sistema de arquivos raiz é um sistema de arquivos em um disco, a função initrd fornece um meio de efetuar a autoinicialização para obter acesso ao disco e montar o sistema de arquivos raiz real. Em um destino embarcado sem um disco rígido, initrd pode ser o sistema de arquivos raiz final ou esse sistema de arquivos raiz final pode ser montado por meio do Network File System (NFS).


Init

Após executar boot e inicializado, o kernel inicia o aplicativo do primeiro espaço do usuário. Ele é o primeiro programa chamado, compilado com a biblioteca C padrão. Até este momento no processo, nenhum aplicativo C padrão foi executado.

Em um sistema Linux de desktop, o primeiro aplicativo iniciado geralmente é /sbin/init. Mas isso não precisa ser assim. Os sistemas embarcados raramente exigem a inicialização extensiva fornecida por init (como configurado por /etc/inittab). Em muitos casos, é possível chamar um simples script de shell que inicie os aplicativos embarcados necessários.


Resumo

Assim como o próprio Linux, o processo de inicialização do Linux é bastante flexível, suportando um grande número de processadores e plataformas de hardware. No início, o loader de boot loadlin oferecia uma maneira simples de inicializar o Linux, de forma simples. O loader de boot LILO expandia as capacidades de inicialização, mas não percebia que nenhum sistema de arquivos estava faltando. A mais recente geração de loaders de boot, como o GRUB, permite que o Linux inicialize a partir de uma variedade de sistemas de arquivos (do Minix ao Reiser).

Recursos

Aprender

  • Boot Records Revealed é um grande recurso nos MBRs e nos diversos loaders de boot. Ele não apenas desmonta os MBRs, como também discute o GRUB, o LILO e os vários loaders de boot® do Windows.
  • Verifique a página Geometria do Disco para entender os discos e suas geometrias. Será encontrado um resumo interessante das atribuições de discos.
  • Um Live CD é um sistema operacional que pode ser inicializado a partir de um CD ou DVD sem precisar de um disco rígido.
  • "Boot loader showdown: Getting to know LILO and GRUB" (developerWorks, agosto de 2005) oferece um exame detalhado nos loaders de boot LILO e GRUB.
  • Na série de tutoriais do developerWorks, Linux Professional Institute (LPI) exam prep, obtenha uma introdução completa sobre como executar boot em um sistema Linux e muitas outras tarefas fundamentais do Linux, enquanto você se prepara para a certificação de administrador do sistema.
  • LILO foi o precursor do GRUB, mas ainda é possível encontrá-lo ao executar boot no Linux.
  • O comando mkintrd é utilizado para criar uma imagem de disco RAM inicial. Esse comando é útil ao criar um sistema inicial de arquivos raiz para executar boot na configuração, permitindo o pré-carregamento dos dispositivos de blocos necessários para acessar o sistema de arquivos raiz real.
  • No Debian Linux Kernel Project, obtenha mais informações sobre o kernel, boot e desenvolvimento embarcado do Linux.
  • Na zona Linux do developerWorks, encontre mais recursos para desenvolvedores Linux.
  • Fique atualizado com eventos técnicos e Webcasts do developerWorks.

Obter produtos e tecnologias

  • O programa MicroMonitor oferece um ambiente de boot para vários dispositivos de destino pequenos. É possível utilizar esse monitor para executar boot no Linux em um ambiente embarcado. Ele tem portas para ARM, XScale, MIPS, PowerPC, Coldfire e Super-H da Hitachi.
  • GNU GRUB é um shell de boot repleto de opções e flexibilidade.
  • LinuxBIOS é uma substituição do BIOS. Não somente executa boot no Linux e no próprio LinuxBIOS, como é um kernel compactado do Linux.
  • OpenBIOS é outro projeto portátil de BIOS que funciona em diversas arquiteturas como x86, Alpha e AMD64.
  • No kernel.org, obtenha a árvore mais recente do kernel.
  • Solicite o SEK para Linux, um conjunto de dois DVDs que contém o software de período experimental IBM mais recente para Linux a partir do DB2®, Lotus®, Rational®, Tivoli®e WebSphere®.
  • Com o Software de período experimental IBM, disponível para download diretamente do developerWorks, construa seu próximo projeto de desenvolvimento em Linux.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux
ArticleID=382598
ArticleTitle=Por Dentro do Processo de Inicialização do Linux
publish-date=05162014