操作系统实战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、javascriptphp、数据库、微信小程序、人工智能、嵌入式、Linux、Unix、QT、物联网、算法导论、大数据等资料

以上是关于操作系统实战45讲:HelloOS运行笔记的主要内容,如果未能解决你的问题,请参考以下文章

《MySQL实战45讲》读后笔记

操作系统实战:实验环境搭建热门问题解答

[OS 45讲 笔记目录]手写一个简易OS

《MySQL实战45讲》(1-10讲)学习总结

精选好课分享MySQL实战45讲完结

MySQL实战45讲