操作系统实战45讲:HelloOS运行笔记
Posted 嵌入式基地
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统实战45讲:HelloOS运行笔记相关的知识,希望对你有一定的参考价值。
本篇文章主要记录《极客时间-操作系统实战45讲》的第一个实验HelloOS的实现过程。
@toc
1.实验环境:
1.1 系统环境
- Ubuntu 20.04.2.0 LTS
- vmware虚拟机
1.2 安装编译环境
- 安装汇编编译器
sudo apt-get install nasm
- 安装gcc(该命令会安装包括gcc在内的所有软件)
sudo apt install build-essential
2. HelloOS实现说明
2.1 HelloOS文件构成
- entry.asm
- 供grub调用的引导程序,用于设置CPU工作模式与工作环境,并调用C语言编写的main函数
-
main.c
- 打印字符串
#include "vgastr.h" void main() printf("Hello OS!"); return;
- 打印字符串
-
vgastr.c / vgastr.h
- 实现在显示屏上输出信息
void _strwrite(char *string) char *p_strdst = (char *)(0xb8000); //指向显存开始的地址 while(*string) *p_strdst = *string++; p_strdst += 2; //每两个字节对应一个字符,其中一个字节是字符的ASCII码,另一个字节为字符的的颜色值 return;
void printf(char *fmt, ...)
_strwrite(fmt);
return; - 实现在显示屏上输出信息
-
hello.lds
-
链接器脚本,用于指导链接过程,设定不同程序段的布局
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
- 编译脚本
2.2 屏幕显示说明
若想使用屏幕显示出字符,则需要使用代码对显卡进行控制。
- 编译脚本
不论是集显、核显、独显,它们都支持VESA标准,该标准有两种工作模式:字符模式与图形模式。这些显卡为了兼容VESA标准,他们都会提供VGABios的固件程序。
2.2.1 显卡的字符模式
在字符模式下,屏幕将会被分为24行,每行80个字符,然后将这24 * 80个字符映射到从0xb8000地址开始的内存中,每两个字节对应一个字符,一个字节对应字符的ASCII码,一个字节对应字符的颜色。
更多关于显卡文本模式下输出字符,可参考下文的chapter 2:点击查看
2.3 部署HelloOS
部署之前,首先了解下HelloOS的引导流程
PC机的BIOS固化在主板上的ROM中,上电后第一条指令就是BIOS固件中的,它负责检测与初始化CPU,内存,主板,之后加载引导设备中的第一个扇区,到0x7c00地址开始的内存空间,然后跳转到0x7c00处执行指令。
本次实验使用的是GRUB引导程序。
2.3.1 准备文件
2.3.1.1 编译HelloOS
- 将生成的HelloOS.bin文件复制到boot文件夹下。(也可将bin文件放置在其他文件夹下,不过一般放在boot中)
sudo mv HelloOS.bin /boot/
2.3.1.2 修改启动项等待时间
-
修改默认启动项的等待时间,打开grub文件,修改GRUB_TIMEOUT参数,默认为10s
sudo gedit /etc/default/grub
- 修改之后使用以下命令更新文件设置,该命令会将/boot/grub/grub.cfg文件给初始化,若之前有所修改,则需要再次进行修改
sudo update-grub
2.3.1.3 虚拟机添加启动项
- 打开grub.cfg文件:
sudo gedit /boot/grub/grub.cfg
- 在文件中插入以下代码
- 代码之间使用的是空格,不能是tab键或其他字符(tab键将会导致启动时找不到相关命令)
menuentry HelloOS insmod part_msdos #GRUB加载分区模块识别分区 insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统 set root=hd0,msdos5 #注意boot目录挂载的分区,这是我机器上的情况 multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin boot
-
insmod 与 set root说明
- multiboot2说明
- 该参数是HelloOS.bin文件存放的路径,该参数设置错误的话,启动HelloOS时将会出现“HelloOS.bin not found”错误
- boot挂载情况主要分为两种:独立分区单独挂载 与 属于根分区的一部分
- 使用
df -h /boot/
命令查看boot的挂载情况,也可使用df -h
查看所有的挂在 - 属于根分区的一部分
- multiboot2 /boot/HelloOS.bin
- 独立分区单独挂载
- multiboot2 /HelloOS.bin
2.3.1.4 物理机添加启动项
- 参考 2.3.1.3 虚拟机添加启动项 进入grub引导界面,查看磁盘分区信息
- 这里物理机的磁盘分区为gpt方式,修改insmod参数
- insmod part_gpt
- 使用
ls (hdx,gptx)/
或ls (hdx,gptx)/boot/
命令进行查找bin文件(前者为单独分区,后者为属于根分区的一部分) - 启动代码
menuentry HelloOS insmod part_gpt #GRUB加载分区模块识别分区 insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统 set root=hd0,gpt5 #注意boot目录挂载的分区,这是我机器上的情况 multiboot2 /HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin boot #GRUB启动HelloOS.bin
- msdos与gpt这两种分区的区别:点击查看
HelloOS运行结果
关注v-x-公-众-号:【嵌入式基地】
后-台-回-复:【电赛】 即可获资料
回复【编程】即可获取
包括有:C、C++、C#、JAVA、Python、javascript、php、数据库、微信小程序、人工智能、嵌入式、Linux、Unix、QT、物联网、算法导论、大数据等资料
以上是关于操作系统实战45讲:HelloOS运行笔记的主要内容,如果未能解决你的问题,请参考以下文章