2017-04-12 106 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段的大小。