2017-04-12 68 views
1

「無法從引導介質中讀取」我也跟着上Write your own operating system in 1 hour本系列教程創建一個基本的操作系統只有4個文件只是打印的「Hello World」:Makefilekernel.cpploader.slinker.ld無法啓動在VirtualBox中定製的內核:

我正在創建一個mykernel.iso文件,但是當我將它啓動到VirtualBox時,出現錯誤「無法從引導介質讀取:系統暫停」。我確認.iso文件與我的機器實例相關聯。看起來代碼中還有其他一些問題。

這裏是我的Makefile:

#we need to tell the compiler to stop assuming that this will be executed inside an OS 
CPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore 
ASPARAMS = --32 
LDPARAMS = -melf_i386 

objects = loader.o kernel.o 

%.o: %.cpp 
    g++ $(CPPPARAMS) -o [email protected] -c $< 

%.o: %.s 
    as $(ASPARAMS) -o [email protected] $< 

mykernel.bin: linker.ld $(objects) 
    ld $(LDPARAMS) -T $< -o [email protected] $(objects) 

install: mykernel.bin 
    sudo cp $< /boot/mykernel.bin 

mykernel.iso: mykernel.bin 
    mkdir iso 
    mkdir iso/boot 
    mkdir iso/boot/grub 
    cp $< iso/boot/ 
    echo 'set default=0' > iso/boot/grub/grub.cfg 
    echo 'set timeout=0' >> iso/boot/grub/grub.cfg 
    echo '' >> iso/boot/grub/grub.cfg 
    echo 'menuentry "My Personal OS" {' >> iso/boot/grub/grub.cfg 
    echo 'multiboot /boot/mykernel.bin' >> iso/boot/grub/grub.cfg 
    echo 'boot' >> iso/boot/grub/grub.cfg 
    echo '}' >> iso/boot/grub/grub.cfg 
    grub-mkrescue --output [email protected] iso 
    rm -rf iso 

clean: 
    rm -rf iso 
    rm *.o 
    rm mykernel.iso 
    rm mykernel.bin 

這裏是kernel.cpp

void printf(char *str) 
{ 
    unsigned short *VideoMemory = (unsigned short*)0xb8000; 

    for(int i=0;str[i] != '\0';i++) 
     VideoMemory[i] = (VideoMemory[i] & 0xFF00) | str[i]; 
} 

typedef void (*constructor)(); 
extern "C" constructor start_ctors; 
extern "C" constructor end_ctors; 
extern "C" void callConstructors() 
{ 
    for(constructor * i=&start_ctors;i!=&end_ctors;i++) 
     (*i)(); 
} 

extern "C" void kernelMain(void * multiboot_structure, unsigned int magic_number) 
{ 
    printf("Hello World!"); 

    //we do not want to exit from the kernel 
    while(1); 
} 

這裏是loader.s

.set MAGIC, 0x1badb002 
.set FLAGS, (1<<0 | 1<<1) 
.set CHECKSUM, -(MAGIC + FLAGS) 

.section .multiboot 
    .long MAGIC 
    .long FLAGS 
    .long CHECKSUM 

.section .text 
.extern kernelMain 
.extern callConstructors 
.global loader 

loader: 
    mov $kernel_stack, %esp 
    call callConstructors 
    push %eax #AX register has the pointer of multiboot structure stored by bootloader 
    push %ebx #BX register has the magic number 
    call kernelMain 

#double check to not come out of the kernel, creating one more loop 
_stop: 
    cli 
    hlt 
    jmp _stop 


.section .bss 
.space 2*1024*1024 #2MB for stack to grow towards left side 
kernel_stack: 

這裏是linker.ld

ENTRY(loader) 
OUTPUT_FORMAT(elf32-i386) 
OUTPUT_ARCH(i386:i386) 

SECTIONS 
{ 
    . = 0x100000; 

    .text : 
    { 
     *(.multiboot) 
     *(.text*) 
     *(.rodata) 
    } 

    .data : 
    { 
     start_ctors = .; 
     KEEP(*(.init_array)); 
     KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*))); 
     end_ctors = .; 

     *(.data) 
    } 

    .bss : 
    { 
     *(.bss) 
    } 

    /DISCARD/ : 
    { 
     *(.fini_array*) 
     *(.comment) 
    } 
} 

我的開發環境是安裝了virtualbox的Linux Mint 18.1 64位。我的代碼幾乎與系列教師的代碼相匹配,但我仍無法在虛擬機中啓動。

編輯

我試着用qemu-system-i386 -kernel mykernel.bin和正常工作與消息Hello World。那意味着有一些問題,VirtualBox的環境和配置。

+0

在虛擬機啓動過程中,您是否打過F12並告訴它您從光盤啓動? –

+0

我懷疑你的問題可能與棧有關。你創建一個2MB的棧很大。因爲它位於BSS部分,所以多重引導加載程序會將其歸零。在某些環境中,問題是如此龐大的BSS段可能導致多引導加載程序在加載和處理內核時失敗。如果堆棧是問題,請嘗試將大小設置爲2k(2048字節)而不是2mb。它工作嗎? (即將其更改爲:'.section .bss''.space 2 * 1024') –

+0

您應該嘗試用'qemu'來查看您的內核是否正常。可能首先檢查二進制文件(.bin),然後檢查.iso。 –

回答

-1

我沒有這個答案的官方消息來源。它實際上是基於我在Stackoverflow上看到的經驗和其他問題以及我所做的一些發現。

如果您創建的BSS段它會導致GRUB在某些環境中,而不是其他大崩潰內核引導堆時出現。這種情況通常發生在總體大小似乎達到2mb左右時。 Virtualbox似乎是問題似乎出現的一個特例。 Virtualbox中的問題似乎取決於所使用的版本和虛擬硬件配置。

您在loader.s中創建的用於引導您的環境的堆棧並不需要那麼大。一旦你得到你的內存管理和分配器,你可以爲更大的內核堆棧保留區域,並在當時設置爲SS:ESP

爲此,你應該考慮改變:

.section .bss 
.space 2*1024*1024 #2MB for stack to grow towards left side 
kernel_stack: 

的東西1MB或更小。我可能會像64kb:

.section .bss 
.space 64*1024 #64KB for stack to grow towards left side 
kernel_stack: 
+0

我在一臺機器上試了2KB,它工作正常,而同樣大小的其他機器在同一個操作系統上崩潰(64KB適用於這個)。可能是VirtualBox或其他東西的差異。 –

+0

你可以請分享一些很好的教程(如果你知道)介紹內核bootstrapping,BSS,堆棧等。我想探索更多。謝謝。 –

+0

@InsaneCoder [OS Dev Wiki](http://wiki.osdev.org/Main_Page)可能是您最好的選擇 –

0

我遇到了同樣的問題。只需安裝grub-pc-bin並重新編譯內核就可以在虛擬機上成功啓動。

sudo apt-get install grub-pc-bin 

此外,我不必更改BSS段的大小。