注:与本系列博客同时同步的还有后面需要学习和研究的FreeRTOS和linux0.11-linux1.0内核代码VV的Linux操作系统内核笔记系列,即使笔者已经自己写了个操作系统了,但是为了能够使博客能读懂,笔者需要把每一个lab和代码打出来做出解释同时笔者也有自己繁重的学习和工作(本科狗),所以进度会非常非常慢
话不多说,迅雷下载下载地址
安装过程不多赘述,安装完成如图所示:
apt-get install docker docker.io docker-compose qemu virtualbox
Eclipse的CDT原生支持Makefile工程,而且虚拟机内存占用较小,所以这里我们就用Eclipse CDT,注意是32位的Eclipse表问我为啥安装Eclipse Indigo这种老玩意,因为最新版本的EC并不支持32位。
在我们编写内核的过程中,我们使用GRUB来启动我们的内核。 至于为什么用GRUB,因为它可以设置多系统共存,这样的话你就可以打包多个系统内核同时存在并且启动的镜像文件。
为了直观和形象,我们直接上图
注意!现代操作系统使用了UEFI启动,但是我们现在不说UEFI,请自行忽略
但是这样也需要我们的Boot程序按照Mutileboot 规范来编译内核,才可以被GRUB引导。 按照Mutileboot规范,内核必须在起始的8KB中的(512字节)包含这一个多引导项头(Multiboot header)。 而且,这个多引导项头里面必须有3个4字节对齐的块。
一个魔术块:包含了魔数[0x1BADB002],是多引导项头结构的定义值。
一个标志块:我们不关心这个块的内容,我们简单设定为0。
一个校检块:校检块,魔术块和标志块的数值的总和必须是0。
我的内核启动代码如下: boot.s
.set MAGIC, 0x1badb002;GRUB魔术块
.set FLAGS, (1<<0 | 1<<1);GRUB标志块
.set CHECKSUM, -(MAGIC + FLAGS);校验块
.section .multboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
.extern kernel_main;导入kernel_main
.extern system_constructors;导入系统构造函数
.global laoder
loader:
mov $kernel_stack, %esp
call system_constructors
push %eax
push %ebx
call kernel_main
stop:
cli
hlt
jmp stop
.section .bss
.space 2*1024*1024
kernel_stack:
一些code解释:
现在建立符号链接来Link我们的所有object文件 linker.ld
ENTRY(boot)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS {
. = 0x0100000;
.text :{
*(.muiltboot)
*(.text*)
*(.rodata)
}
.data :
{
start_ctors = .;
KEEP(*(.init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
end_ctors = .;
*(.data)
}
.bss :
{
*(.bss)
}
/DISCARD/ : {
*(.fini_array*) *(.comment)
}
}
Makefile 没什么好说的,Makefile负责C/C++的 编译依赖过程
GCCPARAMS = -m32 -W -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPPARAMS = --32
LDPARAMS = -melf_i386
GCC = g++
ASM = as
LINKER = ld
CFLAGS = -o $@ -c $<
ASMFLAGS = -o $@ $<
LINKERFLAGS = -T $< -o $@
objects = boot.o kernel.o
%.o: %.c
$(GCC) $(GCCPARAMS) $(CFLAGS)
%.o: %.s
$(ASM) $(ASPPARAMS) $(ASMFLAGS)
kernel_lab.bin: linker.ld $(objects)
$(LINKER) $(LINKERFLAGS) $(objects)
all: kernel_lab.bin
echo "build successed"
clean:
rm -rf *.o
rm -rf *.out
rm -rf iso
rm -rf *.iso
rm -rf *.bin
rebuild: clean all
echo "rebuild"
install: kernel_lab.bin
sudo cp $< /boot/kernel_lab.bin
kernel_lab.iso: rebuild
mkdir iso
mkdir iso/boot
mkdir iso/boot/grub
cp kernel_lab.bin iso/boot/
cp boot/grub.cfg iso/boot/grub/grub.cfg
grub-mkrescue -o $@ iso
rm -rf iso
kernel_vm: kernel_lab.iso
(killall virtualbox) || true
virtualbox -startvm "kernel_lab" &
下面是操作系统的主要程序,我们由C++编写,用extern "C"导出我们的函数符号 kernel.cpp
#include "kernel.h"
//因为我们的操作系统没有TTY IO,所以我们需要重新写一个printf函数
extern "C" void printf(char *str){
u_short *monitor_io_memory=(u_short *)0xb8000;//注意!重点来啦!0xb8000内存地址是显示器地址,往这里写数据就直接能够输出到屏幕上
for(int i=0;str[i]!='\0';++i){
//写入字符串,取或0xff00的意思是我们需要把屏幕高四位拉低,否则就是黑色的字体,黑色的字体黑色的屏幕是啥也看不到的
monitor_io_memory[i]=(monitor_io_memory[i] & 0xff00) | str[i];
}
}
//操作系统构造函数委托方法
typedef void(*constructor)();
//全局定义构造委托
constructor start_ctors;
//全局定义析构委托
constructor end_ctors;
//轮询函数,并且执行
extern "C" void system_constructors(){
for(constructor* i=&start_ctors;i!=&end_ctors;i+=1){
(*i)();
}
}
//操作系统主启动函数,这里我们打印一个字符串然后让操作系统进入等待
extern "C" void kernel_main(const void *multiboot_structure,u_int magicnumber){
printf("Hello Pulsar-V");
while(1);
}
别忘了/boot/下的grub.cfg文件,这个是GRUB的配置文件,负责在启动器中列出我们需要启动的内核列表 grub.cfg
set timeout=10 #超时时间
set default=0 #默认启动项
menuentry "PulsarV's OS" {
multiboot /boot/kernel_lab.bin
boot
}
现在,来看看我们的工程目录结构
在Ubuntu16.04的grub生成.iso镜像文件的时候如果出现
grub-mkrescue: warning: Your xorriso doesn't support `--grub2-boot-info'. Some features are disabled
的时候,就通过
sudo apt-get install xorriso
来安装好你的xorriso 然后通过
grub-mkrescue -o kernel_lab.iso iso
来打包我们的操作内核 接下来要做的事情就是控制台下输入编译命令先运行一下最基本的kernel
make kernel_vm
现在是show time! 首先看到的是我们的GRUB启动界面
接下来按下回车或者等待10s
大功告成,现在可以看见了我们的操作系统的Hello World了。
如果启动失败了,就用压缩文件(Ubuntu归档管理器)的形式打开iso文件,检查你的目录结构和GRUB Config
参考文档: [Grub配置文件]http://www.jinbuguo.com/linux/grub.cfg.html [MIT公开课]https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-828-operating-system-engineering-fall-2012/ [计算机操作系统第四版]
(adsbygoogle = window.adsbygoogle || []).push({});