domingo, 12 de junho de 2011

O Processo de Boot

         O processo de booting ou boot, que é derivado do termo bootstrapping, inicia-se ao ligar o computador
sendo concluído quando o sistema operacional executar todos os programas configurados para serem iniciados. As
etapas do processo de boot são muitos similares em várias plataformas, como no PC, PowerPC (Mac) ou Sparc. O
boot de uma plataforma PC (x86) será tido como base embora os conceitos sejam válidos em outras arquiteturas.
         O POST (Power-On Self-Test) é o procedimento inicial da plataforma PC. Verifica a integridade do hardware,
em que problemas em memória RAM ou placa de video, são emitidos sinais sonoros de alarme. A CMOS
(Complementary Metal Oxide Semiconductor) é um circuito de baixo consumo de energia em que ficam
armazenados parâmetros utilizados com a execução do BIOS (Basic Input-Output System), como a data do sistema,
configurações de dispositivos on-boards e os dispositivos de boot (IPL devices).
         Assim que o POST estiver concluído, o código do BIOS armazenado na EEPROM (Electronically Erasable
Programmable Read-Only Memory) são carregados em um endereço inicial da memória RAM e executado. O BIOS é
o sistema inicial do computador, sendo responsável pela inicialização do equipamento, além de prover uma interface de
comunicação com o hardware para o sistema operacional. O BIOS é executado recebendo os parâmetros armazenados
na CMOS, como dispositivo configurado como dispositivo de boot primário . Assim, o BIOS irá carregar (INT19) para
a memória RAM (0:7C00h) e executar as instruções contidas no primeiro bloco deste dispositivo (Hard-disc, CD-ROM,
etc), o conteúdo do cylinder 0, head 0, sector 1, setor chamado de MBR (Master Boot Record), também conhecido
como Master Boot Block.
Master Boot Record
A MBR contém o primeiro executável proveniente de um dispositivo de armazenamento, como um HD ou CD-ROM. A
MBR deve possuir um gerenciador de boot, como o LILO (Linux Loader) ou o GRUB (GRand Unified Bootloader),
(alguns sistemas inferiores usam algo que chamarei de WinLoader), que são gravados na MBR durante a instalação do
sistema operacional.
Podemos utilizar o seguinte comando para obter uma cópia da MBR atual, considerando que nosso dispositivo primário
de boot é o HD Master da IDE0: /dev/hda. É importante entender a funcionalidade dos arquivos de dispositivos de bloco,
neste caso, /dev/hda é um ponteiro para o início do disco.
dd if=/dev/hda of=mbr.bin bs=512 count=1
Utilizando um editor hexadecimal:
hexedit mbr.bin
Contador                               Valor Hexadecimal
Tradução ASCII
00000000     FA EB 21 01 B5 01 4C 49 4C 4F 16 06 AC A0 57 43 00 00 00 00 C5 ED 6C 41
..!...LILO....WC......lA
00000018     98 A3 B8 2B 81 00 80 60 76 EC 14 00 B8 C0 07 8E D0 BC 00 08 FB 52 53 06
...+...`v............RS.
00000030     56 FC 8E D8 31 ED 60 B8 00 12 B3 36 CD 10 61 B0 0D E8 67 01 B0 0A E8 62
V...1.`....6..a...g....b
00000048     01 B0 4C E8 5D 01 60 1E 07 80 FA FE 75 02 88 F2 BB 00 02 8A 76 1E 89 D0
..L.].`.....u.......v...
00000060     80 E4 80 30 E0 78 0A 3C 10 73 06 F6 46 1C 40 75 2E 88 F2 66 8B 76 18 66
...0.x.<.s..F.@u...f.v.f
00000078     09 F6 74 23 52 B4 08 B2 80 53 CD 13 5B 72 55 0F B6 CA BA 7F 00 42 66 31
..t#R....S..[rU......Bf1
00000090     C0 40 E8 70 00 66 3B B7 B8 01 74 03 E2 EF 5A 53 8A 76 1F BE 20 00 E8 4A
.@.p.f;...t...ZS.v.. ..J
000000A8     00 B4 99 66 81 7F FC 4C 49 4C 4F 75 27 5E 68 80 08 07 31 DB E8 34 00 75
...f...LILOu'^h...1..4.u
000000C0     FB BE 06 00 89 F7 B9 0A 00 F3 A6 75 0D B0 02 AE 75 08 06 55 B0 49 E8 D2
...........u....u..U.I..
000000D8     00 CB B4 9A B0 20 E8 CA 00 E8 B7 00 FE 4E 00 74 07 BC E8 07 61 E9 5E FF
..... .......N.t....a.^.
000000F0     F4 EB FD 66 AD 66 09 C0 74 0A 66 03 46 10 E8 04 00 80 C7 02 C3 60 55 55
...f.f..t.f.F........`UU
00000108     66 50 06 53 6A 01 6A 10 89 E6 53 F6 C6 60 74 58 F6 C6 20 74 14 BB AA 55
fP.Sj.j...S..`tX.. t...U
00000120     B4 41 CD 13 72 0B 81 FB 55 AA 75 05 F6 C1 01 75 4A 52 06 B4 08 CD 13 07
.A..r...U.u....uJR......
00000138     72 59 51 C0 E9 06 86 E9 89 CF 59 C1 EA 08 92 40 83 E1 3F F7 E1 93 8B 44
rYQ.......Y....@..?....D
00000150     08 8B 54 0A 39 DA 73 39 F7 F3 39 F8 77 33 C0 E4 06 86 E0 92 F6 F1 08 E2
..T.9.s9..9.w3..........
00000168     89 D1 41 5A 88 C6 EB 06 66 50 59 58 88 E6 B8 01 02 EB 02 B4 42 5B BD 05
..AZ....fPYX........B[..
00000180     00 60 CD 13 73 10 4D 74 0A 31 C0 CD 13 61 4D EB F0 B4 40 E9 46 FF 8D 64
.`..s.Mt.1...aM...@.F..d
00000198     10 61 C3 C1 C0 04 E8 03 00 C1 C0 04 24 0F 27 04 F0 14 40 60 BB 07 00 B4
.a..........$.'...@`....
000001B0     0E CD 10 61 C3 00 00 00 98 A3 B8 2B 00 00 00 01 01 00 82 FE 3F 1E 3F 00
...a.......+........?.?.
000001C8     00 00 20 99 07 00 80 00 01 1F 83 FE FF 34 5F 99 07 00 96 A7 C1 00 00 00
.. ..........4_.........
000001E0     C1 35 83 FE FF FF F5 40 C9 00 0D 66 8B 01 00 00 00 00 00 00 00 00 00 00
.5.....@...f............
000001F8     00 00 00 00 00 00 55 AA
......U.
Curiosidade: são necessários 4 bits para representar um hexadecimal, ou seja, cada par de
hexadecimal ocupa 1 byte. A MBR esta localizada nos primeiros 512 bytes do disco, logo,
possui 1024 hexadecimais ou 4096 bits.
Com o aplicativo /bin/dd é possível o acesso direto a qualquer região do disco.
     Na tradução ASCII, o ponto (.) significa que o valor hexadecimal não possui um
caracter associado, assim como,apesar do hexadecimal possuir um caracter associado, esse
hexadecimal pode ser um dado que não deve ser
interpretado como um caracter ASCII. Por este motivo nem sempre a tradução hexadecimal =>
ascii tem um sentido em palavras.
     Pode-se notar que única tradução hexadecimal => ascii útil é de "4C 49 4C 4F" =>
"LILO". Com isso podemos inferir que o LILO está instalado nesta MBR.
          O código acima, a MBR, contém duas seções. A seção do 1o (0h) ao 446o (1BDh) byte possui o código
responsável pela inicialização do sistema operacional (LILO ou 1o estágio do GRUB), este código pode conter
referências diretas ou indiretas ao kernel do sistema. O 447o (1BEh) ao 510o (1FDh) byte contém a tabela de partições
do disco (Master Partition Table). E os bytes 511o e 512o possuem a assinatura indicando final da MBR: 55 AA.
                • MBR: referência de boot indireta
          O código de MBR do tipo indireto, não inicia diretamente o kernel do sistema operacional, mas sim carrega e
executa outros códigos de boot. Enquanto o código da MBR do GRUB carrega o estágio 1.5 do GRUB, (que é
localizado nos 30 primeiros Kb do disco imediatamente após o MBR), o WinLoader lê a tabela de partições do disco
(447o byte ao 512o byte) em busca da partição marcada como ativa (Active - vide fdisk), carregando e executando o
primeiro bloco desta partição, chamado de Partition Boot Sector também conhecido como PBR - Partition Boot
Record, comportamento semelhante realizado pelo boot loader dos BSDs, que acessam a PBR de sua partição wd0a.
          O código contido no primeiro bloco da partição ativa nos sistemas MS-DOS, é apenas um JMP para a
localização dos arquivos IO.SYS/MSDOS.SYS/COMMAND.COM, enquanto nos sistemas linux, este código é gerado
pelos gerenciadores de boot (LILO/GRUB). Diferentemente dos sistema like-DOS, onde arquivos do sistema são
utilizados, na maioria dos sistemas, o gerenciador de boot possui mais recursos, sendo um programa que faz parte do
primeiro bloco da partição, assim, o código gerado pelo LILO/GRUB é instalado antes do início do sistema de arquivos.
Nos casos em que a MBR necessita carregar a PBR, a referência ao kernel do sistema operacional não esta na MBR,
mas sim na PBR.
          Uma antiga limitação do LILO é a dependência do BIOS. O suporte fornecido pela interface de comunicação
com o disco do BIOS é limitado até o setor 1023o do disco, isto resulta que o LILO também fosse restrito a isto. De uma
forma geral, todas as implementações de acesso ao hardware tentam utilizar a interface da BIOS, mas isso não é
obrigatório. Uma solução para contornar este problema era criar uma pequena partição, que chegue no máximo ao setor
1023 do disco, com intuito de garantir que o kernel estivesse neste espaço acessível do disco. Esta é a razão para que
antigamente fosse necessário colocarmos os arquivos de boot no diretório /boot, e este, em um sistema de arquivos
separado no inicio do disco.
          O LILO implementou o "Logical Block Addresses" (LBA), com isso, a "Boot Loader" simula a existência de
menos setores no disco. O "Boot Loader" é responsável por este suporte, lendo a real localização do kernel no arquivo
/boot/map. Como o uso do "Logical Block Addresses" (LBA) tornou-se padrão, a utilização de uma partição para os
arquivos de boot (/boot) ficou obsoleto.
          O comando abaixo, ms-fdisk, instala na MBR uma referência de boot indireta para a PBR da partição ativa.
Note que este código não é configurável como ocorre com o LILO, este simplesmente sobrescreve o conteúdo atual da
MBR.
fdisk /mbr
          Da mesma forma, ao utilizar o LILO, a configuração abaixo do lilo.conf exemplifica como o LILO atua como
gerenciador de boot direto para o kernel linux, e indireto (induz a execução do código bootável da partição) para um
eventual "sistema do lado negro da força":
# Gerenciador de Boot Direto
image=/boot/vmlinuz-2.6.8-2-386
            label=Linux_2.6.8
            root=/dev/hda2
            read-only
            initrd=/boot/initrd.img-2.6.8-2-386
# Gerenciador de Boot Indireto
other=/dev/hda4
         label=dark_side_of_the_Force
          No GRUB A opção chainloader +1 indica que o o código bootável esta na PBR da partição indicada: (hd0,0), ou
seja, /dev/hda1.
# Gerenciador de Boot Indireto
title Windows boot menu
rootnoverify (hd0,0)
makeactive
chainloader +1
                • MBR: referência de boot direta
         O código da MBR do tipo direto, o gerenciador de boot instalado na MBR, possui a localização física (head,
sector, cylinder) do kernel que esta disponível para boot do sistema. O acesso ao kernel e a initrd é realizado pelo
código do LILO residente na MBR. Este acesso não depende do tipo de sistema de arquivos da partição, simplesmente
os dados do kernel são carregados para a memória e executado-os.
         Da mesma forma que o LILO, também pode-se instalar o GRUB na MBR, a diferença entre eles, é o modo de
acesso ao kernel. Enquanto o LILO localiza o kernel através localização física, que também foi referenciada na MBR, o
GRUB localiza o kernel através de informações do sistema de arquivos. Intuitivamente podemos concluir que
precisamos gravar LILO sempre que mudarmos o localização física1 do kernel, enquanto que o GRUB depende de um
driver de acesso ao sistema de arquivos. Assim como, a utilização do gerenciador de boot do tipo direto, não necessita
de uma partição ativa, essa informação não é utilizada para continuar o boot do sistema.
1 O simples ato de mover um kernel (vmlinuz*) para outro diretório e retorná-lo ao /boot
tem grande
chance de mudar a localização física deste kernel.
         É possível configurar o LILO/GRUB com uma grande variedade de opções, podendo inicializar vários sistemas
operacionais, assim como, inicializar um mesmo sistema (a mesma partição raiz) com diferentes versões do kernel.
         LILO: As configurações contidas no arquivo /etc/lilo.conf são utilizadas pelo programa lilo para gerar um código
de máquina, como se fosse um montador ou compilador, que contém um menu de seleção, e as referências da
localização do kernel (boot direto) ou da uma partição (boot indireto). Este código será gravado no dispositivo indicado
pela opção boot= do lilo.conf. Cada arquitetura possui diferentes registadores, sendo necessário que seja gerado um
código dependente da arquitetura.
      Curiosidade: Para entendermos o funcionamento do boot direto e boot indireto, é
possível
fazer o GRUB instalado na MBR executar o LILO de uma PBR. É meio inútil, mas é bom para o
entendimento.
      Considerando que nosso disco primário é IDE0/Master, configure o GRUB adequadamente e
instale-o na MBR
(grub-install /dev/hda), caso o GRUB já esteja sendo utilizado, basta inserir a seguinte
configuração:
      title LILO da hda1
      rootnoverify (hd0,0)
      makeactive
      chainloader +1
      O próximo passo é configurar o /etc/lilo.conf de forma convencional, contendo as
especificação do
kernel. Entretando informaremos que o lilo deve ser instalado na hda1 com a opção
boot=/dev/hda1.
Usando o comando lilo o código binário será gerado e instalado na PBR da partição hda1.
      Assim, o BIOS executará o GRUB da MBR, que executará o LILO da PBR, que executará o
Kernel que esta
armazenado no disco, que é carregado sem uso de drivers de sistemas de arquivos, já que o
LILO realiza
acesso ao disco de forma direta.
      Ps: XFS não tem suporte a PBR, logo, não suporta bootloaders na partição. Não faça
este teste
      com XFS, caso contrário você corromperá o XFS. Isto acontece pois o superblock dele
fica no block Zero
      da partição, aonde o LILO seria instalado, por compatibilidade discos IRIX.
Interagindo com o conteúdo da MBR [informação didática]
                • Realizando uma cópia da MBR:
dd if=/dev/hda of=/boot/mbr.bin bs=512 count=1
                • Restaurando a MBR1:
dd if=/boot/mbr.bin of=/dev/hda bs=512 count=1
          Cuidado ao restaurar a MBR, caso esteja utlizando o LILO, pois o kernel pode não estar na mesma localização
física. Isso ocorrerá caso seu kernel tenha sido atualizado. Neste caso seu sistema não dará boot. Normalmente não se
restaura o conteudo da MBR, simplesmente grava-se novamente através do LILO/GRUB.
                • Realizando uma cópia da MBR sem a tabela de partições, ou seja, somente do gerenciador de boot
                     (Inutil?):
dd if=/dev/hda of=/boot/mbr-bl.bin bs=446 count=1
                • Restaurando a MBR sem a tabela de partições, ou seja, somente do gerenciador de boot (Novamente
                     este procedimento não é utilizado, basta gravar novamente o boot loader.):
dd if=/boot/mbr-bl.bin of=/dev/hda bs=446 count=1
                • Realizando uma cópia somente da tabela de partições (pode ser útil em alguns casos):
dd if=/dev/hda of=/boot/partitions.bin bs=1 count=66 skip=446 seek=446
                • Restaurando somente a tabela de partições (pode ser útil em alguns casos):
dd if=/boot/partitions.bin of=/dev/hda bs=1 count=66 skip=446 seek=446
Kernel
          O Boot Loader carrega o kernel (/boot/vmlinuz*), e executa-o. As imagens dos kerneis disponíveis na
máquina, são armazenados no /boot, por exemplo:
-rw-r--r--        1 root root 1097419 2005-05-19 06:25 /boot/vmlinuz-2.6.8-2-386
-rw-r--r--        1 root root 2225745 2005-09-02 14:49 /boot/vmlinuz-2.6.12.5
-rw-r--r--        1 root root 2177220 2005-10-11 14:27 /boot/vmlinuz-2.6.13.4
          Um breve retrospecto. Ao ligar o equipamento, a CMOS (um circuito alimentado pela pequena bateria),
carregou a BIOS (armazenada na EEPROM) e as configurações que serão utilizadas como parâmetros para a
execução, para uma área inicial da memória RAM1 e executou-o. O BIOS carregou a MBR do dispositivo de boot
primário, e se necessário a PBR para uma área subseqüente da memória RAM. Agora, o kernel é carregado em uma
área de memória subseqüente e executado.
1 Antigamente, nos tempos do 8086/8088, não tenho certeza se também nos 286, era
armazenado em memória RAM, antes do BIOS, um micro-programa que transformava a "linguagem
de máquina", para o formato real do processador, normalmente em 8bits de endereçamento.
Atualmente este micro-programa é em hardware residente internamente aos processadores (os
mainframes da IBM carregam este código através de um disquetão, que possibilita a fácil
atualização da micro-arquitetura, mas da um trabalho quando o disquete tem que ser
utilizado anos depois no próximo boot).
- Ainda dizem que assembly é baixo nível, na prática, os processadores não entendem o
nível ISA (os OpCodes aceitos pela máquina), implementado sob assembly de 16bits dos
8086/8088, assembly de 32bits da família Pentium ou o assembly de 64bits do AMD64, todas
as intruções dos programas são tratados pelo programa da micro-arquitetura. O processador
só trabalha com 8 bits, tanto que em assembly a menor quantidade de bits que pode ser
acessada é 8 bits (referente a uma parte de um registrador, por exemplo, essas partes de
8 bits do registrador EAX chamam-se HA e LA.)
Bem, já viajei muito sobre micro-arquitetura, voltemos aos boot loaders.
          Neste momento os algoritmos básicos de um kernel são ativados: gerenciamento de processos, memória e de
dispositivos. Com isso, o kernel assume o controle do hardware, e passa para a próxima etapa: carregar os drivers de
dispositivos, sendo estes compilados 'build-in' (os drivers de dispositivos que foram compilados como módulo serão
carregados depois que o sistema de arquivos tenha sido montado). Após isto, o kernel necessita acessar uma partição
raiz que foi fornecida como parametro de execução do kernel pelo gerenciador de boot. Esta partição é chamada de raiz
(ou partição root) pois contém os arquivos necessários (executáveis, bibliotecas, ...) para que a inicialização do sistema
possa continuar.
          A priori, a partição raiz é um parâmetro de execução do kernel, mas caso omitida, pode ser obtida pelo Boot
Loader no /boot/map, assim como, pode ser inserida na própria imagem do kernel (vmlinuz*) através de um hack
somente para arquitetura x86, que pode ser feito pelo comando rdev.
O kernel montará esta partição somente leitura (read-only) e posteriormente um script executado pelo init remontará
para leitura-escrita (read-write). Esta partição deve conter uma estrutura básica necessária para a execução do
processo init; podemos utilizar o comando "ldd" recursivamente para descobrir todas as bibliotecas que o init depende:
ldd /sbin/init
libc.so.6 => /lib/tls/libc.so.6 (0xb7e80000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7fc1000)
ldd /lib/tls/libc.so.6
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0xb7fbd000)
ldd /lib/ld-linux.so.2
statically linked
          Isto também deve ser realizado para todos os comandos executados a partir do init. Esse é o procedimento
básico para criarmos um sistema embarcado com o kernel do Linux. Este procedimento pode ser feito sob uma
distribuição como o Debian.
          Neste momento, o kernel executará o primeiro código a nível de usuário (userlevel) o /sbin/init. Entenda que
todos os processos de controle do hardware são chamados de a nível de kernel, e são apresentados entre colchetes
como o [ksoftirqd/0] ou o [kjournald] através do comando ps. O init é executado com o usuário (como o root) e
existem algumas evoluções ao tradicional System-V like init como o init-ng ou o upstart que visam executar a
inicialização dos programas iniciais em paralelo.
Init
         Como primeiro processo a ser executado, o /sbin/init receberá o identificador (PID) igual á 1. E o primeiro
passo deste executável é obter a configuração "si::sysinit:" do arquivo /etc/inittab:
si::sysinit:/etc/init.d/rcS
         Esta configuração indica o primeiro shell-script a ser executado no sistema, /etc/init.d/rcS, sendo responsável
por executar tarefas administrativas do diretório /etc/rcS.d. A programação a nível de interpretador de comandos como
o bash, ksh, csh, é amplamente utilizada pelos scripts de inicialização, chama-se Shell-Script, e recomendo o livro do
Júlio Cezar Neves.
lrwxrwxrwx 1 root root 21               2005-06-23 11:02 S02mountvirtfs -> ../init.d/mountvirtfs
lrwxrwxrwx 1 root root 18               2005-06-23 11:02 S05bootlogd -> ../init.d/bootlogd
lrwxrwxrwx 1 root root 25               2005-06-23 11:04 S05initrd-tools.sh -> ../init.d/initrd-
tools.sh
lrwxrwxrwx 1 root root 19               2005-06-23     11:04   S05keymap.sh -> ../init.d/keymap.sh
lrwxrwxrwx 1 root root 16               2005-06-23     15:28   S07hdparm -> ../init.d/hdparm
lrwxrwxrwx 1 root root 22               2005-06-23     11:02   S10checkroot.sh -> ../init.d/checkroot.sh
lrwxrwxrwx 1 root root 25               2005-11-22     16:04   S18hwclockfirst.sh ->
../init.d/hwclockfirst.sh
lrwxrwxrwx 1 root root 24               2005-06-23 11:03 S18ifupdown-clean -> ../init.d/ifupdown-
clean
lrwxrwxrwx 1 root root 27               2005-06-23 11:04 S20module-init-tools -> ../init.d/module-
init-tools
lrwxrwxrwx 1 root root 18               2005-06-23 11:02 S20modutils -> ../init.d/modutils
lrwxrwxrwx 1 root root 26               2005-06-23 11:07 S25libdevmapper1.01 ->
../init.d/libdevmapper1.01
lrwxrwxrwx 1 root root 20               2005-06-23     11:02   S30checkfs.sh -> ../init.d/checkfs.sh
lrwxrwxrwx 1 root root 19               2005-06-23     11:02   S30procps.sh -> ../init.d/procps.sh
lrwxrwxrwx 1 root root 21               2005-06-23     11:02   S35mountall.sh -> ../init.d/mountall.sh
lrwxrwxrwx 1 root root 20               2005-10-18     09:18   S36lm-sensors -> ../init.d/lm-sensors
lrwxrwxrwx 1 root root 21               2005-06-23     11:02   S36mountvirtfs -> ../init.d/mountvirtfs
lrwxrwxrwx 1 root root 18               2005-06-23     11:03   S38pppd-dns -> ../init.d/pppd-dns
lrwxrwxrwx 1 root root 19               2005-06-23     11:03   S39dns-clean -> ../init.d/dns-clean
lrwxrwxrwx 1 root root 18               2005-06-23     11:03   S39ifupdown -> ../init.d/ifupdown
lrwxrwxrwx 1 root root 21               2005-06-23     11:02   S40hostname.sh -> ../init.d/hostname.sh
lrwxrwxrwx 1 root root 20               2005-06-23     11:03   S40networking -> ../init.d/networking
lrwxrwxrwx 1 root root 21               2005-06-23     11:04   S41hotplug-net -> ../init.d/hotplug-net
lrwxrwxrwx 1 root root 17               2005-09-02     15:20   S43portmap -> ../init.d/portmap
lrwxrwxrwx 1 root root 21               2005-06-23     11:02   S45mountnfs.sh -> ../init.d/mountnfs.sh
lrwxrwxrwx 1 root root 27               2005-06-23     11:03   S48console-screen.sh -> ../init.d/console-
screen.sh
lrwxrwxrwx 1 root root 20               2005-11-22     16:04   S50hwclock.sh -> ../init.d/hwclock.sh
lrwxrwxrwx 1 root root 17               2005-07-13     11:07   S51ntpdate -> ../init.d/ntpdate
lrwxrwxrwx 1 root root 21               2005-06-23     11:02   S55bootmisc.sh -> ../init.d/bootmisc.sh
lrwxrwxrwx 1 root root 17               2005-06-23     11:02   S55urandom -> ../init.d/urandom
lrwxrwxrwx 1 root root 17               2005-06-23     11:03   S70nviboot -> ../init.d/nviboot
lrwxrwxrwx 1 root root 24               2005-06-23     14:25   S70xfree86-common -> ../init.d/xfree86-
common
As principais funções destes scripts são:
                  Configurar o mapa do teclado.
                •
                  Configurar definições especificas de dispositivos IDE (/etc/hdparm.conf).
                •
                  Verificar se a partição raiz foi desmontada corretamente, e se necessário, iniciar a execução do fsck.
                •
                  Montar as partições especificadas no arquivo /etc/fstab, incluindo remontar a partição raiz como
                •
                    'leitura-escrita'.
                  Configurar o relógio do sistema, a partir do relógio da BIOS (hwclock --hctosys).
                •
                  Configurar as interfaces de rede.
                •
                  Ativar o hotplug e o discover para carregar os módulos necessários.
                •
                  Atualizar o relógio do sistema via NTP.
                •
          Os scripts indicados foram obtidos de um sistema Debian, entretanto todas as distribuições possuem scripts
semelhantes a esses, para executar estas tarefas, e outras que forem necessárias.
          A próxima etapa do init é verificar no arquivo /etc/inittab a configuração id:2:initdefault:. Esta configuração
indica qual perfil (runlevel) o sistema iniciará. O linux possui perfís de execução como descrito a seguir.
Runlevel 0:       Desligamento do sistema. Todos os serviços serão parados e a máquina será
desligada.
Runlevel 1:       Inicialização para manutenção de sistema. Somente processos administrativos.
Runlevel 2:       Inicialização em modo console. Todos os serviços serão inicializados.
Runlevel 6:       Reinicialização do sistema. Todos os serviços serão parados e a máquina será
reiniciada.
          Em sistemas Debian GNU/Linux, não existe diferença entre os runlevels 2, 3, 4 e 5, sendo que o gerenciador
de login gráfico (kdm, gdm ou xdm) é executado em todos. Nos sistemas baseados em Redhat os runlevels 2, 3 e 4 não
executam o gerenciador de login gráfico.
Cada "runlevel" refere-se a um conjunto de scripts contidos em um determinado diretório.
Runlevel     0  =  /etc/rc0.d/      (halt)
Runlevel     1  =  /etc/rc1.d/      (mono-usuário)
Runlevel     2  =  /etc/rc2.d/      (normal - perfil        1)
Runlevel     3  =  /etc/rc3.d/      (normal - perfil        2)
Runlevel     4  =  /etc/rc4.d/      (normal - perfil        3)
Runlevel     5  =  /etc/rc5.d/      (normal - perfil        4)
Runlevel     6  =  /etc/rc6.d/      (reboot)
          Quando o sistema inicializa um runlevel, os scripts contidos dos referidos diretórios são executados. Os scripts
que iniciam e param serviços são armazenados no diretório /etc/init.d/, e os diretórios dos runlevels (to cansado de
repetir essa palavra!) (/etc/rc?.d) possuem apenas links para scripts armazenados no diretório /etc/init.d/. No Slackware,
estes scripts ficam no diretório /etc/rc.d/
          Os links de cada runlevel, seguem uma nomeclatura obrigatória, onde são nomeados dependendo de sua
prioridade. Utilizarei como exemplo a inicialização dos scripts: /etc/init.d/firewall, /etc/init.d/postfix e
/etc/init.d/proftpd.
          Necessitamos que o /etc/init.d/firewall seja ativado antes dos serviços. Considerando que não há prioridade
entre os outros scripts (postfix e proftpd).
Usando como exemplo do "runlevel 2", nossos links seriam nomeados da seguinte forma:
/etc/rc2.d/S10firewall                 ->    /etc/init.d/firewall
/etc/rc2.d/S20postfix                  ->    /etc/init.d/postfix
/etc/rc2.d/S20proftpd                  ->    /etc/init.d/proftpd
          Neste caso, o init executará primeiramente o firewall, depois o postfix, e posteriormente o proftpd. Assim como,
poderíamos colocar o servidor de FTP iniciando antes do servidor de Email:
/etc/rc2.d/S10firewall                 ->    /etc/init.d/firewall
/etc/rc2.d/S20proftpd                  ->    /etc/init.d/proftpd
/etc/rc2.d/S30postfix                  ->    /etc/init.d/postfix
          Neste caso, o firewall continuaria sendo executado primeiro, seguido do proftpd, e posteriormente o postfix. O
funcionamento dos demais runlevels é semelhante. Usando como exemplo "runlevel 0", onde o sistema é reiniciado,
continuaremos com os mesmos scripts, entretando, agora o último script a ser executado deve ser o firewall:
/etc/rc0.d/K10proftpd                  ->    /etc/init.d/proftpd
/etc/rc0.d/K20postfix                  ->    /etc/init.d/postfix
/etc/rc0.d/K90firewall                 ->    /etc/init.d/firewall
          O nome link é importante para indicar como o script deve ser executado, além de informar a prioridade do
mesmo. O /sbin/init executa os links do /etc/rc2.d/, assim como de qualquer outro "runlevel", seguindo o seguinte
padrão:
                • Nome do Link :: Comando executado
/etc/rc2.d/S10firewall          ::     /etc/init.d/firewall start
/etc/rc2.d/S10proftpd           ::     /etc/init.d/proftpd start
/etc/rc0.d/K10proftpd           ::     /etc/init.d/proftpd stop
/etc/rc0.d/K90firewall          ::     /etc/init.d/firewall stop
Nomeclatura do link para iniciar um serviço:
"S+prioridade+nome"
Nomeclatura do link para parar um serviço:
"K+prioridade+nome"
          Os links dos "runlevels" são automaticamente instalados no momento da instalação do pacote, caso este
pacote possua um executável que necessite ser iniciado no Boot. No Debian, o comando update-rc.d ou o rcconf
podem ser utilizados para a inserção e remoção de links nos diretórios rc?.d, no Redhat, existe o comando ntsysv.
          Após todos os scripts do "runlevel" selecionado no "Boot" terem sido executados, o processo "/sbin/init" ativa os
terminais, também chamados de "consoles", devido a seguinte configuração do /etc/inittab:
1:2345:respawn:/sbin/getty 38400 tty1                     # Alt+F1    =  1o  console   (device    /dev/tty1)
2:23:respawn:/sbin/getty 38400 tty2                       # Alt+F2    =  2o  console   (device    /dev/tty2)
3:23:respawn:/sbin/getty 38400 tty3                       # Alt+F3    =  3o  console   (device    /dev/tty3)
4:23:respawn:/sbin/getty 38400 tty4                       # Alt+F4    =  4o  console   (device    /dev/tty4)
5:23:respawn:/sbin/getty 38400 tty5                       # Alt+F5    =  5o  console   (device    /dev/tty5)
6:23:respawn:/sbin/getty 38400 tty6                       # Alt+F6    =  6o  console   (device    /dev/tty6)
          Neste ponto é finalizado o processo de boot e o sistema esta em produção. O processo init também possui
uma função de verificação de execução de um determinado processo. Essa verificação garante que um determinado
processado será iniciado novamente, caso termine sua execução. Este é o exemplo dos consoles tty*. Após a
realização do login, um shell é executado, normalmente o bash, após ao termino do bash, o console é finalizado, sendo
o init responsável por executá-lo novamente, tornando o prompt disponível para um novo login.
Grafo conceitual
Runlevels
Toda a inicialização do sistema é baseada em runlevels, ou seja, níveis de execução. Os
sistemas Linux possuem 6 runlevels:
0 - conhecido como halt, é o runlevel que desliga o sistema;
1 - monousuário, inicializa o sistema sem opções de segurança, no modo monousuário sem
rede;
2 - multiusuário, inicializa o sistema com todas as opções de multiusuários e segurança;
3 - multiusuário com rede, o mesmo do runlevel 2, mas com opções de rede ativas, o runlevel
mais comum;
4 - não utilizado;
5 - multiusuário em modo gráfico, igual ao runlevel 3, mas inicia o servidor X
automaticamente;
6 - reboot, reinicializa o sistema.

Nenhum comentário:

Postar um comentário