Atualmente, estou começando a programação do kernel implementando um driver de dispositivo de bloco. Consegui fazer uma implementação "simples" e gostaria de aprofundar o que o subsistema de blocos oferece.
Para fazer isso, gostaria de emular meu próprio sistema operacional usando o qemu para evitar travar meu sistema operacional de desenvolvimento sempre que cometer um erro no código do dispositivo do kernel.
Configuração do sistema host
Na minha estação de trabalho estou usando o Debian 9 rodando com o kernel 4.9.0.
$ uname -a
Linux PC325 4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux
Criação de disco de imagem
Para criar a máquina virtual, criei uma imagem bruta de 500M comdd if=/dev/zero of=vm-image.raw bs=1M count=512
E, em seguida, formate-o para ext4 usandomkfs.ext4 vm-image.raw
ATUALIZAÇÃO após o comentário @meuh: Preenchi
a imagem do disco da seguinte maneira:
mount vm-image.raw /mnt
mkdir /mnt/dev /mnt/lib /mnt/proc /mnt/root /mnt/run /mnt/sbin /mnt/sys
cp -r /etc /mnt/
cp -r /lib/systemd /mnt/lib
ln -s /lib/systemd/systemd /mnt/sbin/init
Agora estou tentando inicializar o sistema operacional emulado, mas estou tendo problemas para configurá-lo.
Comando de execução
$ qemu-system-x86_64 -k fr -kernel /boot/vmlinuz-$(uname -r) -initrd /boot/initrd.img-$(uname -r) -hda vm/vm-image.raw -append "initrd=/boot/initrd.img-$(uname -r) root=/dev/sda rw console=ttyS0" -nographic
Rastreamento de inicialização
[...] Kernel boot sequence [...]
Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... [ 2.015241] tsc: Refined TSC clocksource calibration: 3392.292 MHz
[ 2.016768] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x30e5dd94d34, max_idle_ns: 440795304975 ns
[ 2.895630] random: fast init done
Begin: Waiting for suspend/resume device ... Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
[ 11.111765] random: crng init done
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
Begin: Running /scripts/local-block ... done.
done.
Gave up waiting for suspend/resume device
done.
Begin: Will now check root file system ... fsck from util-linux 2.29.2
[/sbin/fsck.ext4 (1) -- /dev/sda] fsck.ext4 -a -C0 /dev/sda
/dev/sda: clean, 3607/32768 files, 12617/131072 blocks
done.
[ 35.528453] EXT4-fs (sda): mounted filesystem with ordered data mode. Opts: (null)
done.
Begin: Running /scripts/local-bottom ... done.
Begin: Running /scripts/init-bottom ... done.
run-init: /sbin/init: No such file or directory
[ 35.569247] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[ 35.569247]
[ 35.570469] CPU: 0 PID: 1 Comm: run-init Not tainted 4.9.0-6-amd64 #1 Debian 4.9.82-1+deb9u3
[ 35.571599] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
[ 35.572695] 0000000000000000 ffffffff9792e074 ffff974c05e14d00 ffffa66e8003feb8
[ 35.573741] ffffffff9777cfbd ffff974c00000010 ffffa66e8003fec8 ffffa66e8003fe60
[ 35.574780] a4112d94e56af84a ffff974c05e14d80 0000000000000100 ffff974c05e84490
[ 35.575793] Call Trace:
[ 35.576132] [<ffffffff9792e074>] ? dump_stack+0x5c/0x78
[ 35.576815] [<ffffffff9777cfbd>] ? panic+0xe4/0x23f
[ 35.577453] [<ffffffff9767c2de>] ? do_exit+0xade/0xae0
[ 35.578136] [<ffffffff978058b4>] ? vfs_write+0x144/0x190
[ 35.578830] [<ffffffff9767c313>] ? SyS_exit+0x13/0x20
[ 35.579510] [<ffffffff97603b7f>] ? do_syscall_64+0x8f/0xf0
[ 35.580223] [<ffffffff97c113b8>] ? entry_SYSCALL_64_after_swapgs+0x42/0xb0
[ 35.581209] Kernel Offset: 0x16600000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
[ 35.582584] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
[ 35.582584]
Problemas
1 - Tentando ler disquete
Na inicialização, parece que o kernel tenta ler de um dispositivo de disquete que não existe ou não pode ser lido. O kernel desistiu após 30 tentativas, portanto não é um problema crítico, mas está diminuindo a sequência de inicialização em 30 segundos.
Eu tentei executar qemu com -no-fd-bootchk
opção, mas não mudou nada
ATUALIZAÇÃO:
Precisando-fda floppy.img
defloppy.img
1ko suprime as mensagens de erro relacionadas ao disquete e economiza até 20 segundos na inicialização. No entanto, como você pode ver no rastreamento de inicialização,/scripts/local-block
ainda está sendo executado várias vezes e leva até 10 segundos antes de passar para a próxima etapa.
2 - Não foi possível inicializar o sistema
ATUALIZAÇÃO após o comentário @meuh:
Parece que o kernel não consegue encontrar um script init valib. No entanto /sbin/init
, está presente na imagem do disco e é um link simbólico para /lib/systemd/systemd
.
Estou experimentando um kernel panic, mas não sei o que está causando isso.
Pergunta
Sou muito novo no qemu e acho que não estou tão longe de ter meu sistema emulado funcionando, mas não posso ir além.
Tentei brincar com os parâmetros, mas não consigo encontrar uma solução para inicializar totalmente e ter um prompt bash em vez de initramdisk.
ATUALIZADO após o comentário do @meuh:
O que devo copiar para a imagem do disco para poder inicializar o sistema ?
Eu não fiz isso, pois normalmente alguém instalaria o qemu a partir de um iso ou de uma imagem existente do qemu; portanto, provavelmente há uma maneira mais fácil do que a seguinte. O que você está perdendo é praticamente equivalente ao sistema de arquivos que você precisaria para um chroot .
Uma coisa a tentar é
que desce e descompacta cerca de 300Mbytes de arquivos que você pode "inicializar" como um contêiner systemd e testar com
Veja
man machinectl
. Você pode montar sua imagem qemu tornando-a um dispositivo de bloco:e copie esta árvore para ele. Ao executar o qemu, você normalmente precisa fornecer um tamanho de VM maior para evitar falhas:
O uso
-boot d
pode evitar o acesso ao disquete.