本专栏是在学习LMOS的《操作系统实战45讲》时的学习笔记,以检验学习效果。
操作系统的启动
BIOS固件一般是PC机才有的,在嵌入式设备中一般没有BIOS. BIOS是固定放在主板的ROM中的,PC上电后执行的第一条指令即是BIOS. BIOS的主要目的是做一些硬件检测,然后最重要的工作是将硬盘中的GRUB程序加载到内存的固定位置(0x7c00)处,然后CPU会跳转到此处执行。然后由引导程序加载和启动操作系统。
编译HelloOS
HelloOS是《操作系统实战45讲》中的示例OS,代码结构如下:
doalter@doalterUbuntu:~/Documents/code/cosmos/lesson02/HelloOS$ tree
.
├── entry.asm
├── hello.lds
├── install.md
├── main.c
├── Makefile
├── vgastr.c
└── vgastr.h
这一节先不用关心操作系统的实现细节。只需要知道操作系统是怎么运行起来的。
- entry.asm是汇编程序,被GRUB调用,主要目的是初始化寄存器,设置C语言运行环境,并调用main.c
- main.c只有一个printf函数,向屏幕打印一个字符串
- printf函数需要自己实现,所以有了vgastr.c函数,其功能是向显存写字符。显存文本模式下的地址是0xb8000, 即往这个地址写字符就可以了。每个字符用一个字节表示字符本身,一个字节表示颜色。
doalter@doalterUbuntu:~/Documents/code/cosmos/lesson02/HelloOS$ cat vgastr.c
//彭东 @ 2021.01.09
void _strwrite(char* string)
{
char* p_strdst = (char*)(0xb8000);
while (*string)
{
*p_strdst = *string++;
p_strdst += 2;
}
return;
}
void printf(char* fmt, ...)
{
_strwrite(fmt);
return;
}
编译HelloOS就是将上述两个.c和一个.asm文件编成一个可执行的文件。过程如下:
上图中还有一个hello.lds文件没有说明,这个文件实际上是在链接时为程序说明了程序中各段的地址分布。如下,程序起始地址为0x200000
doalter@doalterUbuntu:~/Documents/code/cosmos/lesson02/HelloOS$ cat hello.lds
/*彭东 @ 2021.01.09*/
ENTRY(_start)
OUTPUT_ARCH(i386)
OUTPUT_FORMAT(elf32-i386)
SECTIONS
{
. = 0x200000;
__begin_start_text = .;
.start.text : ALIGN(4) { *(.start.text) }
__end_start_text = .;
__begin_text = .;
.text : ALIGN(4) { *(.text) }
__end_text = .;
__begin_data = .;
.data : ALIGN(4) { *(.data) }
__end_data = .;
__begin_rodata = .;
.rodata : ALIGN(4) { *(.rodata) *(.rodata.*) }
__end_rodata = .;
__begin_kstrtab = .;
.kstrtab : ALIGN(4) { *(.kstrtab) }
__end_kstrtab = .;
__begin_bss = .;
.bss : ALIGN(4) { *(.bss) }
__end_bss = .;
}
makefile的相关知识参考:阮一峰的Make 命令教程
最后在HelloOS目录下执行make就编译生成HelloOS.bin了。
注意1:其实本来生成的是.elf,这个也是可执行文件,最后用objcopy命令把符号表去掉生成了.bin文件。
注意2: 要先安装nasm用于编译.asm文件: sudo apt-get install nasm
装载HelloOS
第一步: 修改/etc/default/grub,使操作系统启动时可以进入引导界面,这样我们才能选择进入HelloOS
修改下面标黄的三行,结果如下:
改完之后,执行sudo update-grub
参考:https://jingyan.baidu.com/article/6dad50755e35d1a123e36ecc.html
第二步: 让grub程序启动HelloOS。
把下面的代码复制,然后插入到/boot/grub/grub.cfg文件中
menuentry ‘HelloOS’ {
insmod part_msdos
insmod ext2
set root='hd0,msdos5’
multiboot2 /boot/HelloOS.bin
boot
}
其中,hd0,msdos4是boot目录挂载的分区。可用df /boot/ 命令查看:
doalter@doalterUbuntu:~/Documents/code/cosmos/lesson02/HelloOS$ df /boot
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda5 19992176 8310984 10642600 44% /
其中的“sda5”就是硬盘的第五个分区,但是 GRUB 的 menuentry 中不能写 sda5,而是要写“hd0,msdos5”,这是 GRUB 的命名方式,hd0 表示第一块硬盘,结合起来就是第一块硬盘的第五个分区。
第三步: 然后把HelloOS.bin文件复制到/boot/目录下最后重启计算机就可以看到HelloOS启动选项了。