Partida e parada |
No início deste manual, mostramos uma "visão de passarinho" do processo de carga do Linux. Vamos explorar esse assunto com mais detalhes, incluindo procedimentos extraordinários que se fazem necessários quando o sistema não carrega.
Durante o bootstrap, logo que a máquina é ligada (ou após um reset), o BIOS procura no primeiro setor do disco selecionado para carga (que pode ser modificado na edição das tabelas do BIOS, independentemente), um programa a executar, que será o nosso carregador (bootstrap loader). O mais usado com o Linux é o LILO, mas podemos até mesmo gravar um kernel em um disquete e usá-lo direto, sem carregador, o que não é recomendável,pois não poderíamos modificar os seus parâmetros de carga. Em um disco rígido, existe um setor de carga para cada partição criada, além do primeiro setor de toda a unidade, chamado master boot record.
O LILO pode ser configurado (como será visto mais adiante, neste mesmo
capítulo) para carregar mais de um sistema operacional ou várias
versões do mesmo sistema. É comum colocarmos várias
imagens de kernels com configurações diferentes, por exemplo, e
usar o LILO para escolher qual delas carregar. Para isso, devemos segurar uma
das teclas Alt, Ctrl ou
Shift, logo quando a mensagem LILO
aparece na tela, ou
ele carregará o primeiro kernel configurado.
Depois de carregado o kernel, normalmente comprimido, ele se expande antes de
iniciar a sua execução (através de um pequeno programa
colocado no início da imagem). Nesse momento, dependendo da forma que
voce configurou o kernel, ele pode perguntar pelo modo de vídeo que
será usado. Caso voce queira evitar essa pergunta, poderá
configurar o kernel com rdev
[29]
para já entrar em um modo pré-determinado.
Em seguida, você verá uma série de mensages, emitidas pelo kernel, durante a detecção e configuração do seu hardware. Na minha máquina, por exemplo, surge o seguinte:
Console: 16 point font, 400 scans Console: colour VGA+ 80x25, 1 virtual console (max 63) pcibios_init : BIOS32 Service Directory structure at 0x000fdae0 pcibios_init : BIOS32 Service Directory entry at 0xfdaf0 pcibios_init : PCI BIOS revision 2.10 entry at 0xfdb11 Probing PCI hardware. Calibrating delay loop.. ok - 59.80 BogoMIPS Memory: 31068k/32768k available (600k kernel code, 384k reserved, 716k data) Swansea University Computer Society NET3.035 for Linux 2.0 NET3: Unix domain sockets 0.13 for Linux NET3.035. Swansea University Computer Society TCP/IP for NET3.034 IP Protocols: ICMP, UDP, TCP Checking 386/387 coupling... Ok, fpu using exception 16 error reporting. Checking 'hlt' instruction... Ok. Linux version 2.0.30 (root@percproj) (gcc version 2.7.2) #6 Tue Apr 28 15:19:15 EST 1998 |
Este conteúdo certamente será diferente na sua máquina, mas isso não importa. Note que a verão do meu kernel (2.0.30) parece um pouco antiga, mas voce não precisa correr para trocar de kernel a cada nova versão que surge. Evite especialmente as versões com o segundo número ímpar, pois são versões em desenvolvimento. O kernel estável atualmente está na versão 2.0.36, mas existem possibilidades do 2.2.0 surgir a qualquer instante. O pessoal trabalha duro para isso acontecer.
O próximo passo é o kernel montar o root filesystem
(diretório /). Este pode ser modificado com rdev
, ou como
parâmetro fornecido ao LILO (root=/dev/<device>
) durante
a carga. Então o kernel inicia os processos swapper
(processo 0) e init
(processo 1), carregando o programa
/sbin/init
.
O processo init
troca o estado do kernel para multi-tarefas, e
lê o arquivo /etc/inittab
, que conterá os
sub-processos que ele deverá criar para tratar as linhas de terminal,
locais ou via modem. Dessa forma, são inicializados pelo
init
, processos getty
ou programa semelhante, e as
linhas estão prontas para receberem conexões. Quando uma
conexão é bem sucedida, voce verá no terminal a mensagem
de login. O processo init pode também iniciar alguns daemons,
dependendo do que contém os scripts que ele executa.
O init tem estados chamados níveis (levels), que definem a configuração do sistema. Os níveis são 0 a 6, s e S. Os processos a executar (criados como filhos de init) estão definidos em /etc/inittab, com o seguinte formato:
id:nível:ação:processo
onde o id é uma sequência de 1 a 4 caracteres para dar nome a
esta linha; o nível é um dos valor que discutimos logo acima; a
ação é um dos valores: respawn, wait, once, boot,
bootwait, off, ondemand, initdefault, sysinit, powerwait, powerfail,
powerokwait, ctrlaltdel, kbrequest
; finalmente processo
é o processo a ser executado, normalmente um getty
ou
script de inicialização, mas outros comandos podem ser usados
aqui.
Os scripts de inicialização são usualmente colocados no diretório /etc/rc.d, mas existe uma variação muito grande destes em cada distribuição Linux existente. Examinando atentamente /etc/inittab, podemos encontrar toda a sequência de scripts executada. Os níveis 0, 1 e 6 são reservados para parada do sistema (halt, nível 0), para a entrada em modo mono-usuário (single, nível 1), e para recarga do sistema (reboot, nível 6).
Veja a minha inittab, como exemplo:
id:4:initdefault: si:S:sysinit:/etc/rc.d/rc.S su:1S:wait:/etc/rc.d/rc.K rc:23456:wait:/etc/rc.d/rc.M ca::ctrlaltdel:/sbin/shutdown -t5 -rfn now l0:0:wait:/etc/rc.d/rc.0 l6:6:wait:/etc/rc.d/rc.6 pf::powerfail:/sbin/shutdown -f +5 "A ENERGIA ESTÁ ACABANDO" pg:0123456:powerokwait:/sbin/shutdown -c "ENERGIA DE VOLTA: FORÇA TOTAL" ps:S:powerokwait:/sbin/init 5 c1:1235:respawn:/sbin/agetty 38400 tty1 linux c2:1235:respawn:/sbin/agetty 38400 tty2 linux c3:1235:respawn:/sbin/agetty 38400 tty3 linux c4:12345:respawn:/sbin/agetty 38400 tty4 linux c5:12345:respawn:/sbin/agetty 38400 tty5 linux c6:12345:respawn:/sbin/agetty 38400 tty6 linux # Minha linha discada, atendendo no modem (/dev/cua3) d3:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS2 vt100 x1:4:wait:/etc/rc.d/rc.4 |
No meu caso específico, o nível inicial (determinado pela linha
com ação initdefault
) é 4, e este
nível por convenção ( no meu sistema ) é a entrada
automática em X. Assim, o script rc.4
(última linha
da listagem acima) será executado, e será sua responsabilidade
inicializar o xdm
, ou outra forma de entrar no X. Veja
também que uso outra versão do agetty
. Isto
é muito questão de gosto. Existem uma meia dúzia de
gettys diferentes, escolha o seu também!
criando um disquete de boot
Algumas vezes voce pode precisar de um boot de emergência, caso alguma
coisa aconteça com a o LILO no seu disco rígido, se bem que isto
com o uso normal dificilmente deve acontecer. Um procedimento simples é
criar um disquete com boot direto no kernel (sem o LILO). No exemplo ao lado,
no lugar de |
~$ su
Password: ***** ~# dd if=/zImage of=/dev/fd0 ~# rdev /dev/fd0 /dev/hda1 |
A configuração do LILO é feita editando um arquivo.
/etc/lilo.conf
, e rodando o seu instalador (map
installer), chamado (adivinhem?) lilo
. O próprio LILO
jamais será executado diretamente, a não ser na carga do
sistema, afinal é para isso que ele existe. O map installer
fica em /sbin/lilo
, e utiliza-se do arquivo
/etc/lilo.conf
, além de vários arquivos do
diretório /boot
, o seu mapa de opções em
/boot/map
, e principalmente do /boot/boot.b
, que
é o segundo estágio do carregador, criado juntamente com o
kernel.
Vejamos um exemplo do /etc/lilo.conf para carregar linux ou
windows, escolhidos com Alt, Shift ou
Ctrl na execução do LILO. Este exemplo usa o MBR (master boot record) do primeiro disco rígido para armazenar o LILO, e é dado um time-out (retardo), parâmetro delay , de 3 segundos (30 décimos de
segundo) para o usuário escolher o sistema a carregar.
|
boot = /dev/hda
delay=30 |
O parâmetro vga é passado ao kernel, informando qual o tipo da
configuração de vídeo desejada. As opções
são: normal (80x25), extended (80x50),
ask (para pergeuntar ao usuário o modo desejado), ou um
número com o modo de vídeo. O parâmetro
ramdisk também é tratado pelo kernel. O parâmetro message informa um arquivo onde se encontra a mesnagem (informativa) que deve ser enviada quando o usuário pressionar Shift após o aparecimento de " LILO " na
tela.
|
vga = normal
|
O parâmetro image indica o arquivo com a imagem do kernel;
root informa o dispositivo que deve ser montado na raiz;
label é um nome dado a esta imagem, e será usado na
escolha manual do sistema a carregar.
|
image = /zImage
|
Mais uma imagem (opção) com a mesma raiz. Poderíamos
também introduzir opções adicionais para o kernel
adicionando a linha de comando: append=<string> . Para carregar
um ramdisk, podemos fazer ramdisk=<size> e
initrd=<arquivo com a imagem do ramdisk> .
|
image = /zImage-exp
|
O LILO pode ser usado também para carregar outros sistemas
operacionais, colocando other=<partição com o outro
OS> e table=<disco com a tabela de
partição> . Aqui, msdog é o nome
"carinhoso" do MsDos!
|
other = /dev/hda1
|
Já mostramos que o processo init
executa scripts definidos
no arquivo /etc/inittab
. Mas onde estão esses scripts?
Depende da distribuição que voce esteja usando. O
diretório padrão para a localização desses scripts
é o /etc/rc.d
, mas a organização daí
por diante depende muito de cada implementação. No RedHat e
outras distribuições derivadas do mesmo, existe um arquivo
"principal" /etc/rc.d/rc
que recebe o nível do init como
parâmetro e escolhe uma série de subdiretórios de arquivo
com este nível (run-level).
No Slakware e no Plug-and-Play Linux (da Yggdrasil), por exemplo, todos os
scripts estão no mesmo diretório /etc/rc.d
e a
terminação (rc.0, rc.1
, etc.) determina o
nível ou run-level do sistema. Este tipo de setup,
entretanto, não é único, e voce deve procurar
informações sobre isto na documentação da sua
distribuição. Esta localidade (/etc/rc.d
) é
usada quando temos inicializaçãó compatível com o
System-V, o que nem sempre é verdade, e existem outros esquemas (como o
r2d2, por exemplo, que cria novos conceitos de
configuração bem mais interessantes) não oficialmente
suportados por nenhuma distribuição.
Instalação de novos device drivers, devem estar
preferencialmente no arquivo /etc/rc.d/rc.local
, que é
carregado somente no final do processo de boot, quando praticamente
todos os outros dispositivos estão já definidos.
A maior diferença entre o inittab
dado acima e o
padrão do RedHat, é na execução dos scripts de
níveis: o que está l0:0:wait:/etc/rc.d/rc.0
aqui,
no RedHat seria l0:0:wait:/etc/rc.d/rc 0
, pois todos os scripts
neste último são iniciados a partir de rc
<nível>
, enquanto que no Slakware existe um script separado
para cada nível (run-level).
nível | RedHat | Slakware |
As várias distribuições do Linux têm pequenas
diferenças nos run-levels (níveis) que definem o estado
do processo init . Os níveis reservados, evidentemente,
são iguais, pois estes são determinados na
implementação do programa /sbin/init , que é
o mesmo. Existem uma tendência a padronizar esses scripts, mas no
momento eles possuem estas pequenas discrepâncias. |
2 | multi-usuário sem file-sharing | multi-usuário | |
3 | multi-usuário com file-sharing e daemons | multi-usuário | |
4 | estado definido pelo usuário |
partida com X11 (xdm )
|
|
5 |
partida com X11 (xdm )
|
multi-usuário |
Para manutenção, algumas vezes o administrador precisa ter
certeza que nenhum outro usuário está utilizando o sistema.
Nestes casos é interessante ir para o nível 1 (single
user) ou já carregar o sistema neste estado. Para carregar o
sistema assim, forenecemos como parâmetro para o LILO a
opção single
ou emergency
, mas se
você já está com o sistema no ar, no modo
multi-usuário, execute telinit 1
e o sistema irá
para o nível 1. Esta situação de emergência
é necessária, por exemploc, quando você irá executa
fsck
(filesystem check, já visto) manualmente,
para corrigir problemas com os sistemas de arquivos. Dificilmente esta
alternativa será necessária, contudo, pois durante a carga
normal do sistema, fsck já é executado e corrige quase 100% dos
problemas. Essa situação é mais provável
acontecer quando estamos testando um novo kernel, experiental, ou na
hipótese de uma falha de hardware no disco rígido.
Finalmente, observe que não é possível entrar no sistema
no modo single
sem a senha do root (superusuário). Isso
seria uma quebra de segurança, portanto jamais esqueça a
senha do root! Ou, pelo menos, deixe um disquete preparado para boot
com outra partição root (ou mesmo com um ramdisk com
uma imagem alternativa do diretório raiz), nos casos em que o arquivo
/etc/passwd
for danificado.
Não é boa prática desligar o sistema de qualquer maneira,
pois muitos arquivos poderão estar abertos para escrita e terminais com
alguns usuário logados no sistema. Existe o comando shutdown
exatamente para isso. Ele executa uma parada programada do sistema, que
pode ser: (1) imediatamente (opção now
), (2) na
hora programada (introduzindo hh:ss
), (3) daqui a n minutos
(+minutos
), com opção para efetuar um
reboot
ou halt
(parada total).
Alguns exemplos:
shutdown -h now
shutdown -r +5
shutdown -k now
shutdown -h +15 "O sistema sairá do ar daqui a 15
minutos.\
Obrigado pela compreensão."
shutdown -c