Construindo um Linux Parte 2 Disk Root Objetivo: Entender que o Linux é como um LEGO (Pode ser montado).
Disk Root Este disquete conterá o interpretador de comandos bash, juntamente com alguns dispositivos e programas. Faremos também alguns scripts que serão úteis na inicialização e finalização do sistema. Veremos que para que tudo isso funcione e caiba em um disquete, será preciso fazer três coisas. Uma é o uso de bibliotecas compartilhadas, a outra é fazer strip nos arquivos binários e a ultima é fazer uso de um sistema de arquivos comprimido. Assim conseguiremos espaço suficiente no nosso disquete de root. Como você já percebeu, o nosso real esforço será destinado à construção do disquete de root, pois o mesmo apresenta uma complexidade muito superior ao disquete de boot.
Criando RAMdisk Linux em disquete O nosso primeiro passo é a criação do RAMdisk. Um RAMdisk nada mais é o que a simulação do dispositivo de disco na memória. dd if=/dev/zero of=/dev/ram7 bs=1k count=4096 mke2fs m0 /dev/ram7 mount /dev/ram7 /mnt Explicações: dd if=/dev/zero of=/dev/ram7 bs=1k count=4096: Esse comando preenche o dispositivo de RAMdiak com zeros; a razão para isso é que o sistema de arquivos será comprimido mais tarde, então todas as porções não preenchidas dos dispositivos devem ser preenchidas com zero para maximizar a compreensão.
Compilando o Bash tar xvfj bash-2.05a.tar.bz2 cd bash-2.05a./configure --enable-minimal-config --host=i386-pc-linux-gnu make Uma vez compilando o bash, precisamos agora descobrir quais são as bibliotecas necessárias para o seu uso. Para isso temos um utilitário chamado Idd. ldd bash A saída deste comando deve ser algo como mostrado a seguir. Não se preocupe caso a saída a seguir não seja exatamente igual. Algumas distribuições põem as mesmas bibliotecas em lugares diferentes. O importante aqui é você ter as seguintes bibliotecas: libdl.so.2 => /lib/libdl.so.2 (0x4001d000) ( 0x40020000 ) libc.so.6 => /lib/tls/libc.so.6 ( 0x40000000 ) /lib/ld-linux.so.2 => /lib/ld-linux.so.2
Agora que sabemos quais são as bibliotecas, vamos copiá-las todas. Para isso faça o seguinte: mkdir /mnt/bin cp bash /mnt/bin ln s bash /mnt/bin/sh mkdir /mnt/lib cp /lib{libdl.so. 2, ld linux.so.2} /mnt/lib cp /lib/tls/libc.so.6 /mnt/lib O nosso próximo passo é usar o programa strip. Este programa elimina os símbolos debugs existentes nos arquivos executáveis e nas bibliotecas. Esses símbolos são usados por programadores para realizar análises à procura de erros nos respectivos arquivos. Os símbolos podem ser completamente eliminados com segurança que o sistema não irá apresentar problemas, pelo contrário, irá ganhar em desempenho. strip --strip-debug /mnt/{bin, lib}/*
Explicações: Linux em disquete --enable-minimal-conf: Esta opção nos garante um shell com o minimo de características possíveis, tornando-se assim menor. --host=i386-pc-linux-gnu: Esta opção nos permite compilar o programa para ser otimizado num processador 386. Isso garante o uso do sistema em processadores mais novos. strip --strip-debug: Este comando elimina os símbolos usados para debugging que estão presentes no formato binário.
Acrescentando pacotes adicionais Nosso passo a seguir (e o maior) é a compilação de vários pacotes necessários para o disquete. tar xvfj textutils 2.1.tar.bz2 cd textutils 2.1./configure --host=i386 pc-linux gnu make cp src/cat /mnt/bin
tar xvfj fileutils 4.1.tar.bz2 cd fileutils 4.1./configure --host=i386 pc linux gnu make cp src/{chgrp,chmod,chown,cp,dd,df,ln,ls} /mnt/bin strip --strip debug /mnt/bin/* cp src/{mkdir,mkfifo,mkbnod,mv,rm,rmdir,sync} /mnt/bin strip --strip debug /mnt/bin/* ldd /mnt/bin /ls ( 0x4001d000 ) librt.so.1 => /lib/librt.so.1 ( 0x40020000 ) libc.so.6 => /lib/tls/libc.so.6 ( 0x40162000 ) libpthread.so.0 => /lib/libpthread.so.0 /lib/1d-linux.so.2 => /lib/ld linux.so.2 (0x40000000)
Copiaremos apenas a 1ª e 3ª bibliotecas, pois as outras duas já temos. cp /lib/{librt.so.1, libpthread.so.0} /mnt/lib tar xvfj sh utils 2.0.tar.bz2 cd sh utils 2.0./configure --host= i386 pc linux gnu make cp src/{date, hostname, stty, uname} /mnt/bin
Vamos ganhar um pouco mais de espaço strip --strip debug /mnt/bin/* tar xvfj e2fsprogs 1.32.tar.bz2 mkdir build tmp cd build tmp../e2fsprogs 1.32/configure --host = i386 pc linux gnu make mkdir /mnt/sbin cp e2fsck/e2fsck.shared /mnt/sbin/e2fsck ln -s e2fsck /mnt/sbin/ fsck.ext2 strip --strip debug /mnt/sbin/* cp misc/{fsck, mke2fs} /mnt/sbin ln -s mke2fs /mnt/sbin/mkfs.ext2 strip --strip debug /mnt/sbin/*
Explicações Linux em disquete mkdir build-tmp & cd build-tmp: O próprio arquivo INSTALL do pacote recomenda que se construa o e2fsprogs em um diretório separado da fonte. tar xvfj sysvinit 2.84.tar.bz2 cd sysvinit 2.84/src make clobber make CC= gcc -mcpu=i386 cp halt init shutdown /mnt/sbin ln -s halt /mnt/sbin/reboot ln -s init /mnt/sbin /telinit strip --strip debug /mnt/sbin/*
Use um editor de texto para fazer as seguintes mudanças no arquivo MCONFING: Mude CPU=$(Shell uname m) para CPU=i386 Mude HAVE_SHADOW=Yes para HAVE_SHADOW=no Faça a seguinte mudança no arquivo mount/pivot _ root.c.: Acrescente include <errno.h >
tar xvfj util linux 2.11y.tar.bz2 cd util linux 2.11y./configure make cp disk utils /mkfs /mnt/sbin cp fdisk/fdisk /mnt/sbin cp login utils/agetty /mnt/sbin ln -s agetty /mnt/sbin/getty cp login utils/login /mnt/bin cp misc utils/kill /mnt/bin cp mount/{mount,umount} /mnt /bin cp mount/swapon /mnt/sbin cp sys utils/dmesg /mnt/bin strip --strip debug /mnt/sbin/*
Explicações Linux em disquete make CC= gcc -mcpu=i386 : Tem a mesma função que a opção - host=i386 pc-linux gnu. Mude HAVE_SHADOW=yes para HAVE_SHADOW=no : Faz com que o programa não utilize senhas criptografadas. Acrescente include <errno.h> em mount/pivot_root.c: Ao compilar o util-linux, algumas versões do glibc pode nos causar problemas; para evitarmos isso, acrescentamos esta linha.
Criaremos agora os dispositivos que usaremos no sistema. mkdir /mnt/dev mknod /mnt/dev/initctl p mknod /mnt/dev/console c 5 1 mknod /mnt/dev/ram0 b 1 0 mknod /mnt/dev/ fd0 b 2 0 mknod /mnt/dev/null c 1 3
Arquivos do Sistemas Estamos chegando à reta final. Agora, vamos criar todos os arquivos de configuração para que o nosso disquete funcione. O primeiro arquivo que iremos criar é o mtab. Este arquivo contém o estado atual das partições montadas. mkdir /mnt/{etc,proc} cd /mnt/etc ln -s /proc/mounts mtab Agora é vez da fstab cat >/mnt/etc/fstab << EOF proc /proc proc noauto 0 0 /dev/ram0 / ext2 defaults 1 1 EOF
Vamos escrever um script para o sistema de arquivos proc, mas antes vamos criar um diretório necessário. mkdir /mnt/etc/init.d cat > /mnt/etc/init.d/proc_fs << EOF!/bin/sh proc _ fs monta o sistema de arquivos proc PATH=/sbin:/bin export PATH mout -t proc proc /proc EOF
Criaremos agora o arquivo /inittab. cat > /mnt/etc/inittab << EOF /etc/inittab - arquivo de configuração do processo init Nível de execução Id:1:initdefault: Sistema de inicialização Si:S:sysinit:/etc/init.d/rc S Arquivos dos níveis de execução r0:0:wait:/etc/init.d/rc 0 r1:1:respawn:/bin/sh r2:2:wait:/etc/init.d/rc 2 r3:3:wait:/etc/init.d/rc 3 r4:4:wait:/etc/init.d/rc 4 r5:5:wait:/etc/init.d/rc 5 r6:6:wait:/etc/init.d/rc 6
Para criar o script rc faça o seguinte. cat > /mnt/etc/init.d/rc << EOF!/bin/sh PATH=/sbin:/bin SCRIPT _ DIR= /etc/rc$1.d Verifica se o diretorio rcn.d existe. if [ -d $SCRIPT_DIR ] ; then Executa o script kill primeiro. for SCRIPT in $SCRIPT_DIR / K *; do if [ -x $SCRIPT ]; then $SCRIPT stop; fi ; done ; Executa o script Start por último. for SCRIPT in $SCRIPT_DIR/S*; do if [ -x $SCRIPT ]; then $SCRIPT start ; fi ; done ; fi EOF
Esse script faz uma checagem no sistema de arquivos e realize sua montagem. cat > /mnt/etc/init.d/local_fs << EOF!/bin/sh local _ fs - Verifica e monta sistema de arquivos PATH=/sbin:/bin ; export PATH case $1 in ( start echo Checando integridade do sistema de arquivo local. fsck -ATCp if [ $(($?)) -gt $((1)) ]; then echo Sistema de arquivo com erros! Favor verificar. /bin/sh else fi ; ; ( stop echo Remontando / com permissão de leitura escrita. mount -o remount,rw / echo Montando sistema de arquivos locais. mount -a
; ; default ) ; ; echo Desmontando sistema de arquivos locais. umount -a echo Remontando / com permissão de somente leitura. mount -o remount,rw / echo Flushing disk cache. sync echo usage: $0 start stop ; esac EOF
Criando o script hostname cat > /mnt/etc/init.d/hostname << EOF!/bin/sh hostname - atribui o nome do sistema para o arquivo /etc/hostname PATH=/sbin:/bin ; export PATH echo Atribuindo hostname. if [ -f /etc/hostname ]; then ( etc/hostname / hostname $(cat else hostname gnu linux fi EOF
Criando os scripts de halt e reboot cat > /mnt/etc/init.d/halt << EOF!/bin/sh halt Desliga o sistema PATH=/sbin:/bin; export PATH echo O sistema está sendo desligado. halt EOF
cat > /mnt/etc/init.d/reboot << EOF!/bin/sh reboot - reinicia o sistema PATH=/sbin:/bin; export PATH echo O sistema está sendo reiniciado. reboot EOF
Criando os diretórios rcn. d e seus respectivos links. cd /mnt/etc mkdir rc{0,1,2,3,4,5,6,s }.d cd /mnt/etc/rcs.d ln -s../init.d/proc_fs S10proc_fs ln -s../init.d/local_fs S20local_ fs ln -s../init.d/hostname S30hostname cd /mnt/etc/rc0.d ln -s../init.d/local_fs k10local_fs ln -s../init.d/halt k90halt cd /mnt/etc/rc6.d ln -s../init.d/local_ fs k10local _ fs ln -s../init.d/reboot k90reboot
Atribuindo as permissões corretas. chown -R 0:0 /mnt/* chmod 750 /mnt/etc/init.d/* chmod 755 /mnt/bin/* chmod 755 /mnt/lib/* chmod 750 /mnt/sbin/* chmod 660 /mnt/dev/{fd0, ram0} chmod 666 /mnt/mnt/dev/ null chmod 622 /mnt/dev/console chmod 600 /mnt/dev/initctl
O Último Passo Linux em disquete Criando a imagem do disquete de root. cd / umount /dev/ram7 dd if=/dev/ram7 of=lecdisk.img bs=1k gzip -9 lecdisk.img Copiando a imagem para o disquete. Insira um disquete com a etiqueta Lec Root Disk dentro do drive de disquete e faça: dd if=lecdisk.img.gz of=/dev/fd0 bs=1k A hora da verdade é agora. Reinicie o PC com o disquete de boot no drive e quando o prompt do Lilo aparecer, precione a tecla Enter.
Se tudo correu bem, você cera uma tela parecida com o exemplo: LILO boot: Loading lecdisk Uncompressing Linux... ok, booting kernel..... [ varias mensagens do kernel ].. VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER Agora, retire o disquete de boot e coloque o de root e pressione a tecla Enter. Uma mensagem parecida com esta deverá aparecer. RAMDISK: Compressed image found at block 0 VFS: Mounted root ( ext2 filesystem ) readonly. Freeing unused kernel memory: 178k freed Checking local filesystem integrity. / dev / ram0: clean 105 / 1024 files 2842 / 4096 blocks Remounting / as read-write. Mounting local filesystems. Setting the hostname. INIT : Entering runlevel: 1 _