Introdução ao Processo de boot e startup do Linux
Já falamos resumidamente sobre como ocorre a inicialização em outro artigo: Boot – Como o Linux é Iniciado
Também falamos sobre sistema de arquivos nesse outro artigo: FAT32, Ext, Ext2, Ext3, Ext4, btrfs.. Qual Sistema de Arquivos Escolher?
Há duas sequências de eventos requeridos para iniciar o Sistema Operacional Linux: boot e startup.
boot
O boot começa quando a gente liga o computador e tem sua etapa finalizada quando o kernel é iniciado e o systemd carregado.
startup
O processo de startup se inicia após o kernel e o systemd serem iniciados na etapa de boot e termina quando o sistema estiver totalmente pronto.
Sequência Completa de Inicialização
É bom observar que a BIOS foi substituída pelo UEFI e o MBR pelo GPT. Mas, para aprendizado usaremos a BIOS e MBR para exemplos.
Segue abaixo sequência ilustrada
A imagem acima é um pouco antiquada, segue ilustração mais atual
Praticamente as imagens são parecidas só que, na segunda, ao invés de init, temos o systemd e targets. Clique aqui e veja nosso artigo a respeito.
Vamos falar sobre cada uma das etapas acima:
BIOS
“Qualquer usuário pode acessar a BIOS e configurá-la. Geralmente teclamos F2 ou Del assim que apertamos o botão “power on” para ligarmos o computador”.
Essa etapa na verdade não tem nada a ver com o Linux; está relacionada com o hardware e é uma etapa idêntica para qualquer sistema operacional, seja ele linux, windows.
Quando apertamos o botão “ligar” a BIOS(Basic I/O System ou Sistema Básico de Entrada/Saída) entra em ação com um evento chamado POST(Power On Self Test ou Auto-teste de Inicialização) que faz um checagem no hardware. Se algum hardware estiver com problema irá ocorrer uma falha do POST e o sistema operacional(Linux, widnows…) será impedido de iniciar.
Após a checagem do POST a BIOS localiza e carrega o MBR.
A principal função da BIOS é carregar o MBR.
MBR
MBR significa Master Boot Record ou registro mestre de Inicialização.
Está localizado nos primeiros 512 bytes do disco e possui 3 partes: Bootloader, tabela de partição e magic number.
- Boot Loader: dos 512 bytes 446 estão ocupados pelo boot loader. Ele tem a função de dizer ao computador como iniciar(boot). O bootloader é um pequeno programa que identifica a partição inicializável e redireciona o processo de boot para essa localização.
- Tabela de partição: Um dispositivo(HD, por exemplo) pode ser divido em várias partes e a essas partes damos o nome de partições. As informações sobre as partições do disco ficam dentro da tabela de partição do MBR. Essas informações são do tipo: tamanho, tipo, status. Um MBR pode ter até 4 partições primárias; no entanto, sem a tabela de partição seria possível criar apenas uma partição e, assim, não conseguiríamos instalar mais de dois Sistemas Operacionais(windows e linux em dual boot, por exemplo), ou termos mais de um sistema de arquivos(Ext4, ntfs, zfs…) instalado.
- Magic Number: Esse “número mágico” fica no final do MBR e ocupa apenas 2 bytes. O Magic Number serve para indicar se o MBR está válido(OK) ou com falha. Ele só armazena valor em Hexadecimal; o valor AA55 classifica o MBR como válido. Um valor inválido indica a falta de MBR ou que ele está corrompido. Esses valores são críticos e indica se o sistema irá inicializar ou não. Uma observação importante é que o valor hexadecimal, conforme dito acima, é representado pelo valor 0xAA55 ou AA55h, mas quando visto por meio de um programa de edição esse valor irá ser exibido como: “55 AA”
A função principal do MBR é localizar e carregar o bootloader(nesse caso, o GRUB)
GRUB
GRUB é o boot loader usado em sistemas Linux e semelhantes.
GRUB significa “grande gerenciador de inicialização unificado(Grand Unified Boot Loader)”. Antigamente existia o bootloader chamado Lilo para Linux.
No windows se usava o NTLDR e agora é usado o BOOTMGR. O Arquivo de configuração do NTLDR era o boot.ini. O arquivo de configuração do BOOTMGR é o binário BCD. Como BCD é um binário ele não pode ser editado diretamente como texto, assim existem alguns programas para alterá-lo, como: bcdedit.exe e EasyBCD.
GRUB substituiu o Lilo. Em 2002 o GRUB2 veio como versão melhorada do GRUB, então o GRUB foi renomeado oficialmente para “GRUB Legacy” e o GRUB2 passou a ser chamado de epenas GRUB.
O GRUB é tão poderoso que ele aparenta ser muito mais um mini Sistema Operacional do que simplesmente um bootloader.
A função do bootloader é deixar o computador capaz de encontrar o Kernel e carregá-lo na memória ram.
Essa é a tela do GRUB que aparece logo ao ligar meu computador com Ubuntu
Abaixo tela do GRUB no CentOS. Nesse caso há mais de um kernel instalado. Isso é bom, pois se durante alguma atualização de kernel ou instalação de módulos o sistema for comprometido poderemos acessar uma versão mais antiga.
Na parte de baixo de das telas acima há alguns comandos para acesso e edição do GRUB.
Após iniciado o Sistema Operacional, podemos ter acesso ao arquivo de configuração do GRUB que fica em:
/boot/grub/grub.cfg
ou em
/boot/grub2/grub.cfg
O GRUB tem 3 estágios ou etapas: a 1, 1.5 e 3.
Etapa 1 do GRUB
Logo após a BIOS executar o POST(checagem de integridade das peças) ele percorre os discos/dispositivos conectados à procura de um Registro de Inicialização(boot record), o primeiro encontrado é carregado para dentro da memória.
Logo no início desse post anexamos uma imagem ilustrando o MBR e podemos ver que ele está localizado nos primeiros 512 bytes de um dispositivo. Dentro dos 446 bytes iniciais dos 512 está o bootloader que em nosso caso é o GRUB; após os 446 bytes temos a tabela de partição com 64 bytes e, finalizando, temos 2 bytes finais que guarda o “Magic Number”.
Dentro da parte do bootloader há um código chamado de bootstrap(em inglês bootstrap code). A função do bootstrap é apenas localizar a partição que contém em seu início um “registro inicializável”.
No Windows a partição que contém esse setor de boot é chamada de “partição ativa” e é dentro dessa partição que está o windows que será iniciado. Apenas uma partição pode ser marcada como ativa por vez.
O registro inicializável(boot record) é tão pequeno que ele não entende sobre sistema de arquivos.
O espaço reservado no MBR para o código bootstrap são os primeiros 446 bytes e é representado pelo arquivo boot.img
elder@ubuntu2:~$ locate boot.img /boot/grub/i386-pc/boot.img
Como dito acima, o boot record não entende sobre sistemas de arquivos, então o estágio 1.5 toma controle da situação.
Etapa 1.5 do GRUB
Se a etapa 1 acima é representada pelo arquivo boot.img, a etapa 2 possui o arquivo core.img
elder@ti:~$ locate core.img /boot/grub/i386-pc/core.img
core.img tem 25.389 bytes.
Quando falamos de setores no disco nós consideramos que cada setor tem 512 bytes. O MBR está localizado apenas no setor 0 do disco, por isso ele ocupa somente 512 bytes. A primeira partição começa apenas no setor 63, ou seja, temos “livres” o intervalo do setor 1 até o setor 62; um espaço com 31.744 bytes, como fiz esse cálculo? simples, multipliquei 62×512=31744 bytes.
o arquivo core.img está localizado nesse espaço e ocupa apenas 25.389 desses 31.744 bytes. Ainda sobram 6.355 bytes. Então há um bom espaço disponível até chegarmos no início da primeira partição.
Nesse espaço à mais do estágio/etapa 1.5 do GRUB há alguns drivers de sistemas de arquivos(ext4, ntfs, fat….) armazenados. Se a etapa 1 não entende Sistemas de Arquivos, a etapa 1.5 toma controle e já é capaz de lidar com isso.
A função do estágio 1.5 é começar a executar os drivers de sistemas de arquivos necessários para localizar os arquivos do estágio 2.
Etapa 2 do GRUB
Todos os arquivos da etapa 2 estão localizados dentro do diretório e subdiretórios em /boot/grub/
A etapa 2 não possui arquivo de imagem(boot.img e core.img) como as outras etapas anteriores. Pois a etapa 2 consiste de módulos do kernel que são carregamos conforme a necessidade. Esses módulos ficam em /boot/grub/i386-pc/
A função da etapa 2 é carregar o kernel na memória ram e passar o controle do computador para ele.
O kernel e seus arquivos relacionados estão dentro da pasta /boot. Podemos identificar os kernel facilmente já que todos começam com a palava vmlinuz
elder@ubuntu:~$ ls -1 /boot config-4.15.0-112-generic config-4.15.0-47-generic grub initrd.img-4.15.0-112-generic initrd.img-4.15.0-47-generic System.map-4.15.0-112-generic System.map-4.15.0-47-generic vmlinuz-4.15.0-112-generic vmlinuz-4.15.0-47-generic
Vimos anteriormente que ao ligar o computador, o GRUB exibe em um menu a os kernels disponíveis
Bom… resumindo, a função do GRUB é carregar o kernel na memória ram.
KERNEL
Os kernels estão dentro da pasta /boot em um formato compactado e auto-extraível.
Quando um kernel é carregado na memória ele se auto-extrai, saindo da sua forma compactada, e começa a trabalhar. Assim que o kernel é carregado ele inicia o processo systemd. O systemd é o pai de todos os processos.
Acima mencionamos que toda a inicialização do Linux é dividida em duas partes: boot e startup. Aqui se encerra o processo de boot e é começado o de startup.
O Startup
O processo de startup faz com que o Linux fique pronto para uso do usuário.
Systemd
O systemd é o principal agente nessa fase, ele é o pai de todos os processos e tem muito mais funções que o antigo init. Dentre essas funções: pode montar sistemas de arquivos, iniciar e parar serviços do sistema etc…
O systemd age da seguinte forma após o kernel iniciá-lo:
- Monta os sistemas de arquivos conforme especificado em /etc/fstab
- acessa arquivos de configurações dentro de /etc
- Ele analisa o arquivo /etc/systemd/system/default.target para saber em qual estado/target ele deve iniciar o sistema operacional. Algumas dessas targets são multi-user.target que faz o computador iniciar com tudo menos a interface gráfica, rescue.target onde o sistema inicia apenas uma linha de comando para recuperação, graphical.target onde todo o sistema é carregado, inclusive a interface gráfica. Há também a target emergency.target que inicia apenas os serviços necessários para reparação de algum problema.
- Cada target possui suas dependências. systemd inicia essas dependências.
- Systemd também analisa pastas do antigo init do SystemV(chamado também de SysV), se houver algum arquivo para ser inicializado dentro dessas pastas o systemd usa esses arquivos também.
Comparação entre SystemV e Systemd
Abaixo temos uma comparação do antigo SystemV(ou sysv) com o atual Systemd.
SystemV Runlevel | systemd target | systemd target aliases | Descrição |
halt.target | Interrompe o sistema, sem desligá-lo. | ||
0 | poweroff.target | runlevel0.target | Interrompe o sistema, desligando-o |
S | emergency.target | Modo de manutenção ou single. Nenhum serviço é executado; Sistemas de arquivos não são montados. Este é o mais básico nível de operação com apenas um shell de emergência, para interpretação de comandos, sendo executado no console principal para o usuário interagir com o sistema. | |
1 | rescue.target | runlevel1.target | Um sistema básico que monta o sistema de arquivos com os serviços mais básicos e um shell(interpretador de comandos) de recuperação no console principal. |
2 | runlevel2.target | Multiusuário, sem NFS mas com todos os outros serviços sem interface rodando. | |
3 | multi-user.target | runlevel3.target | Todos os serviços sendo executados mas sem interface gráfica. |
4 | runlevel4.target | Não usado. | |
5 | graphical.target | runlevel5.target | multi-usuário com interface gráfica. |
6 | reboot.target | runlevel6.target | Reinicia o sistema |
default.target | Este target é sempre um alias(apelido) com um link simbólico para multi-user.target or graphical.target. systemd sempre usa default.targetpara iniciar o sistema. O default.target nunca deve ter um alias(apelido) para halt.target, poweroff.target, ou reboot.target. |
Eventos que o Systemd Executa até a Finalização do Processo de Startup
O Systemd trabalha com targets ao invés dos runlevels do antigo SystemV.
Segue abaixo um gráfico retirado do site man7.org.
cryptsetup-pre.target | (diversas montagens de API VFS v de baixo nível: (vários dispositivos cryptsetup...) mqueue, configfs, | | debugfs, ...) v | | cryptsetup.target | | (vários swap | | remote-fs-pre.target | devices...) | | | | | | | | | v | v local-fs-pre.target | | | (Sistema de Arquivos de rede) | swap.target | | v v | | | v | remote-cryptsetup.target | | | (vários serviços de (várias montagens e | | | | | baixo nível: udevd, erviços fsck...) | | remote-fs.target | | tmpfiles, random | | | / | | seed, sysctl, ...) v | | / | | | local-fs.target | | / | | | | | | / \____|______|_______________ ______|___________/ | / \ / | / v | / sysinit.target | / | | / ______________________/|\_____________________ | / / | | | \ | / | | | | | | / v v | v | | / (vários (vários | (vários | |/ timers...) paths...) | sockets...) | | | | | | | | v v | v | | timers.target paths.target | sockets.target | | | | | | v | v \_______ | _____/ rescue.service | \|/ | | v v | basic.target rescue.target | | | ________v____________________ | / | \ | | | | | v v v | display- (vários sistema (vários sistema | manager.service de serviços de serviços) | | requeridos para | | | UIs gráficos) v v | | multi-user.target emergency.service | | | | \_____________ | _____________/ v \|/ emergency.target v graphical.target
O systemd tem como função iniciar serviços(programas) em paralelo, um serviço ao lado do outro. Os termos “paralelo e série” são muito empregados em informática. por exemplo, programas em paralelo rodam ao mesmo tempo e serviços em série rodam em sequência, isto é, um processo só é executado quando o que está à sua frente termina.
Observe acima as targets sysinit.target e basic.target. Praticamente todos os serviços passam por eles. Eles funcional como ponto de checagem. Ainda que o systemd tenha como prioridade e meta executar serviços em modo paralelo ainda há certos serviços e targets que devem ser executados antes de outros, dependem de outros. Toda essa dependência é gerida pelo systemd.
Voltando às targets sysinit e basic, elas funcionam como ponto de checagem e os serviços acima delas não podem passar até estarem completas e aprovadas por esses pontos de checagem.
Dentro de sysinit.target todos os serviços são executados em paralelo: dispositivos criptografado, swap, udev, random seed… e só passam por sysinit.target quando completados.
dentro de basic.target, também, todos os serviços são executados em paralelo: timers, paths, sockets….., só passam por basic.target quando completados.
Após passar por sysinit.target e basic.target, perceba que o multi-user.target é sempre carregado para poder se chegar no graphical.target.
Conclusão
Discos são mais que apenas partições e conteúdos guardados. Há uma pequena parte do disco que é muito importante, o MBR ou master boot record que em português significa registro metre de inicialização. O está sendo substituído pelo GPT. Mas nos limitamos a falar sobre MBR nesse artigo.
O boot loader está dentro do MBR e é iniciado pela BIOS quando ligamos o computador.
O boot loader inicia o kernel do linux e o kernel. O kernel inicia o systemd e esse se encarrega dos demais serviços.
Todo o processo de inicialização é dividida em duas etapas: boot e startup. O startup começa quando o systemd é iniciado.
Fontes: wikipedia, thegeekstuff, opensource.com, mbrwizard.com, neosmart.net, man7.org,
One Comment to “Estudo Linux 001: Inicialização do Linux e Bootloaders”