操作系统实战 45 讲
彭东
网名 LMOS,Intel 傲腾项目关键开发者
65203 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 60 讲
尝尝鲜:从一个Hello到另一个Hello (2讲)
特别放送 (1讲)
操作系统实战 45 讲
15
15
1.0x
00:00/00:00
登录|注册

13 | 第一个C函数:如何实现板级初始化?

初始化中断控制器
初始化中断
初始化内存
初始化平台
初始化内核层
初始化hal层
第一个C函数
Cosmos HAL层初始化

该思维导图由 AI 生成,仅供参考

你好,我是 LMOS。
前面三节课,我们为调用 Cosmos 的第一个 C 函数 hal_start 做了大量工作。这节课我们要让操作系统 Cosmos 里的第一个 C 函数真正跑起来啦,也就是说,我们会真正进入到我们的内核中。
今天我们会继续在这个 hal_start 函数里,首先执行板级初始化,其实就是 hal 层(硬件抽象层,下同)初始化,其中执行了平台初始化,hal 层的内存初始化,中断初始化,最后进入到内核层的初始化。
这节课的配套代码,你可以从这里下载。

第一个 C 函数

任何软件工程,第一个函数总是简单的,因为它是总调用者,像是一个管理者,坐在那里发号施令,自己却是啥活也不干。
由于这是第一个 C 函数,也是初始化函数,我们还是要为它单独建立一个文件,以显示对它的尊重,依然在 Cosmos/hal/x86/ 下建立一个 hal_start.c 文件。写上这样一个函数。
void hal_start()
{
//第一步:初始化hal层
//第二步:初始化内核层
for(;;);
return;
}
根据前面的设计,Cosmos 是有 hal 层和内核层之分,所以在上述代码中,要分两步走。第一步是初始化 hal 层;第二步,初始化内核层。只是这两步的函数我们还没有写。
然而最后的死循环却有点奇怪,其实它的目的很简单,就是避免这个函数返回,因为这个返回了就无处可去,避免走回头路。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

在操作系统Cosmos中实现板级初始化的过程以及在Cosmos/hal/x86/下建立一个halmm.c文件,用于初始化内存的具体步骤和技术细节。作者详细介绍了编写第一个C函数hal_start以及其中执行的板级初始化过程,包括平台初始化、内存初始化和中断初始化。文章展示了相关代码,并介绍了初始化中断的重要性和实现过程,包括中断表的定义和中断门描述符的设置。此外,作者还展示了在halsgdidt.c文件中编写的初始化中断描述符表的函数。整篇文章通过详细的代码和注释,帮助读者了解了在Cosmos中实现板级初始化和初始化内存的具体步骤和技术细节。文章内容涵盖了操作系统底层的关键技术,对于想深入了解操作系统内部实现的读者具有很高的参考价值。文章还介绍了中断控制器的初始化和进入内核层的过程,为读者提供了全面的操作系统底层知识。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《操作系统实战 45 讲》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(35)

  • 最新
  • 精选
  • 李亮亮
    置顶
    录了一个 win11+virtualbox的操作视频 https://www.bilibili.com/video/BV1yb4y1N7ya/?share_source=copy_web&vd_source=2e2d7d5fe4bfed959537727318688414

    编辑回复: 感谢你分享,行动力超赞!期待后面看到你的更多思考和输出。

    2024-01-23归属地:湖南
    1
  • 老王
    有了前面基础实验很快就做通了,只是实验步骤课程没有说 1.下载最新源码 git clone https://gitee.com/lmos/cosmos.git 2 进入课程的目录 cd cosmos/lesson13/Cosmos 3 编译 make all 这个过程中可能会报告错误 ../hal/x86/kernel.asm:6: fatal: unable to open include file `kernel.inc' krnlbuidrule.mk:14: recipe for target 'kernel.o' failed make[2]: *** [kernel.o] Error 1 Makefile.x86:28: recipe for target 'all' failed make[1]: *** [all] Error 2 Makefile:59: recipe for target 'all' failed make: *** [all] Error 2 警告不管 解决错误即可 使用 find -name "kernel.inc" 搜索头文件的位置 ./include/halinc/kernel.inc 把这个头文件拷贝到和kernel.asm相同的目录。或者是更改../hal/x86/kernel.asm 第6行 改为%include "../include/halinc/kernel.inc" 再次make 可以正常编译 4.生成内核镜像文件 make cplmildr (这一步会拷贝 initldrimh.bin initldrkrl.bin initldrsve.bin 到源码顶层目录的release下 ) make cprelease (这一步会拷贝 Cosmos.bin 到源码顶层目录的release下 ) make KIMG (这一步会调用lmoskrlimg 把initldrimh.bin initldrkrl.bin initldrsve.bin Cosmos.bin logo.bmp background.bmp font.fnt按一定的格式打包成Cosmos.eki镜像文件 ) 5.拷贝Cosmos.eki镜像文件到虚拟磁盘 源码目录已经创建了磁盘文件hd.img(如果没有这个文件可以按照前面的课程自己创建) sudo mount -o loop ./hd.img ./hdisk/ (挂载虚拟磁盘到hidsk目录,hd.img hidsk目录已经存在) sudo cp release/Cosmos.eki hdisk/boot (拷贝编译好的镜像Cosmos.eki 到虚拟磁盘中) sudo umount hdisk (卸载挂载目录/或者是目录和磁盘中的内容) VBoxManage convertfromraw ./hd.img --format VDI ./hd.vdi (把hd.img转为hd.vdi格式,因为课程使用的虚拟机是VirtualBox) 6.参考前面课程使用hd.vdi启动系统 总结: 要想搞清楚整个程序的流程,除了分析代码本身,还需要深入分析Makefile和各个链接脚本

    编辑回复: 感谢老铁的分享,特别赞。

    2021-06-07
    10
    42
  • neohope
    稍微整理了一下: 一、HAL层调用链 hal_start() A、先去处理HAL层的初始化 ->init_hal() ->->init_halplaltform()初始化平台 ->->->init_machbstart() 主要是把二级引导器建立的机器信息结构,复制到了hal层一份给内核使用,同时也为释放二级引导器占用内存做好准备。 其做法就是拷贝了一份mbsp到kmbsp,其中用到了虚拟地址转换hyadr_to_viradr ->->->init_bdvideo() 初始化图形机构 初始化BGA显卡 或 VBE图形显卡信息【函数指针的使用】 清空屏幕 找到"background.bmp",并显示背景图片 ->->->->hal_dspversion() 输出版本号等信息【vsprintfk】 其中,用ret_charsinfo根据字体文件获取字符像素信息 ->->move_img2maxpadr() 将移动initldrsve.bin到最大地址 ->->init_halmm()初始化内存 ->->->init_phymmarge 申请phymmarge_t内存 根据 e820map_t 结构数组,复制数据到phymmarge_t 结构数组 按内存开始地址进行排序 ->->init_halintupt();初始化中断 ->->->init_descriptor();初始化GDT描述符x64_gdt ->->->init_idt_descriptor();初始化IDT描述符x64_idt,绑定了中断编号及中断处理函数 ->->->init_intfltdsc();初始化中断异常表machintflt,拷贝了中断相关信息 ->->->init_i8259();初始化8529芯片中断 ->->->i8259_enabled_line(0);好像是取消mask,开启中断请求 最后,跳转去处理内核初始化 ->init_krl() 二、中断调用链,以硬件中断为例 A、kernel.inc中,通过宏定义,进行了中断定义。以硬件中断为例,可以在kernel.inc中看到: 宏为HARWINT,硬件中断分发器函数为hal_hwint_allocator %macro HARWINT 1 保存现场...... mov rdi, %1 mov rsi,rsp call hal_hwint_allocator 恢复现场...... %endmacro B、而在kernel.asm中,定义了各种硬件中断编号,比如hxi_hwint00,作为中断处理入口 ALIGN 16 hxi_hwint00: HARWINT (INT_VECTOR_IRQ0+0) C、有硬件中断时,会先到达中断处理入口,然后调用到硬件中断分发器函数hal_hwint_allocator 第一个参数为中断编号,在rdi 第二个参数为中断发生时的栈指针,在rsi 然后调用异常处理函数hal_do_hwint D、hal_do_hwint 加锁 调用中断回调函数hal_run_intflthandle 释放锁 E、hal_run_intflthandle 先获取中断异常表machintflt 然后调用i_serlist 链表上所有挂载intserdsc_t 结构中的中断处理的回调函数,是否处理由函数自己判断 F、中断处理完毕 G、异常处理类似,只是触发源头不太一样而已

    作者回复: 老哥 6666

    2021-06-08
    3
    21
  • pedro
    [ hal_start ] --> [ init_hal ] --> [ init_krl ] [ init_hal ] --> [ init_halplaltform ] --> [ move_img2maxpadr ] --> [ init_halmm ] --> [ init_halintupt ] [ init_krl ] --> [ die ] [ init_halplaltform ] --> [ init_machbstart ] --> [ init_bdvideo ] [ init_halmm ] --> [ init_phymmarge ] [ init_halintupt ] --> [ init_descriptor ] --> [ init_idt_descriptor ] --> [ init_intfltdsc ] --> [ init_i8259 ] --> [ i8259_enabled_line ] 如果有 graph-easy 的同学,直接 CV,然后: ```sh graph-easy calltree.txt ```

    作者回复: 铁汁牛皮

    2021-06-07
    4
    15
  • LunaElf
    Cosmos hal 层函数调用关系: 1. `hal_start()` 1. `init_hal()` 1. `init_halplatform()` 1. `init_machbstart()` 1. `machbstart_t_init()` 2. `init_bdvideo()` 2. `init_halmm()` 1. `init_phymmarge()` 1. `initpmrge_core()` 3. `init_halintupt()` 1. `init_idt_descriptor()` 1. `set_idt_desc()` 2. `init_intfltdsc()` 3. `init_i8259()` 2. `init_krl()` 1. `hal_fault_allocator()` 1. `hal_do_hwint()` 1. `hal_run_intflthandle()` 1. `hal_hwint_allocator()` 1. `hal_do_hwint()` 1. `hal_run_intflthandle()`

    作者回复: 66666

    2021-10-19
    4
  • 卢承灏
    有一个问题,回过头来二刷的时候没想明白,如果中断传递的只是一个中断号,然后中断号是进行共用的,那在hal_run_intflthandle 中的list_for_each 中,每个设备注册的handler方法,怎么判断自己需不需要执行呢? handler传入的s->device 也是从循环中的每一个intserdsc_t取出,和最开始的中断号看不出中什么关联。还希望大神们解答

    作者回复: 中断共享 需要设备驱动程序自己处理

    2021-09-07
    2
    4
  • 云师兄
    太硬了啊,有点磕牙,不过再咬两口试试😬

    编辑回复: 哈哈哈,舌尖上的操作系统,老铁加油!

    2021-06-09
    4
  • 吴建平
    代码走查出一个安全问题,下面这个函数里,如果for里一个满足条件的都没找到,那么后面校验的时候 retemp->saddr 就空指针了。 e820map_t *ret_kmaxmpadrcmpsz_e820map(machbstart_t *mbsp, u64_t mappadr, u64_t cpsz) { if (NULL == mbsp) { return NULL; } u64_t enr = mbsp->mb_e820nr; e820map_t *emp = (e820map_t *)phyadr_to_viradr((adr_t)mbsp->mb_e820padr); e820map_t *retemp = NULL; u64_t maxadr = emp[0].saddr; for (u64_t i = 0; i < enr; i++) { if (emp[i].type == RAM_USABLE) { if (emp[i].saddr >= maxadr && //内存区首地址大于已知最大区域起始地址(初始化位第一个区首地址 (mappadr > (emp[i].saddr + emp[i].lsize)) && //内存区尾地址小于内存映射最大地址 (emp[i].lsize >= cpsz)) //内存区大小大于镜像文件大小 { maxadr = emp[i].saddr; //已知最大区域起始地址 retemp = &emp[i]; //更新最后满足条件内存区域 } } } if ((mappadr > (retemp->saddr + retemp->lsize)) && (retemp->lsize >= cpsz)) //校验,但除非一个都不满足条件 { return retemp; } return NULL; }

    作者回复: 对的 厉害了 找出了BUG

    2021-07-01
    2
  • 很好奇move_img2maxpadr(&kmachbsp);这个函数 功能:move_img2maxpadr(&kmachbsp);这个函数是把镜像文件搬到最大的物理地址处。 作用:我感觉是因为镜像文件是加载在0x4000000处,而空闲地址是从内核文件加载处开始计算的(0x2000000+内核大小),随着内存的分配,空闲地址不断向上增长,迟早会覆盖镜像文件,所以提前把镜像文件搬走了。

    作者回复: 对,你理解的很正确

    2021-06-07
    2
  • Victor
    在ubuntu 18.04环境下make时报错: root@ubuntu1804:~/LMOS/cosmos/lesson13/Cosmos# make all Initldr:清理全部已构建文件... ^_^ *********正在开始编译构建系统************* AS -[M] 正在构建... ../ldrkrl/imginithead.asm CC -[M] 正在构建... ../ldrkrl/inithead.c CC -[M] 正在构建... ../ldrkrl/vgastr.c AS -[M] 正在构建... ../ldrkrl/ldrkrl32.asm CC -[M] 正在构建... ../ldrkrl/ldrkrlentry.c CC -[M] 正在构建... ../ldrkrl/fs.c CC -[M] 正在构建... ../ldrkrl/chkcpmm.c CC -[M] 正在构建... ../ldrkrl/graph.c CC -[M] 正在构建... ../ldrkrl/bstartparm.c AS -[M] 正在构建... ../ldrkrl/realintsve.asm OBJCOPY -[M] 正在构建... initldrimh.bin OBJCOPY -[M] 正在构建... initldrkrl.bin OBJCOPY -[M] 正在构建... initldrsve.bin 恭喜我,Initldr编译构建完成! ^_^ ../hal/x86/kernel.asm:6: fatal: unable to open include file `kernel.inc' krnlbuidrule.mk:14: recipe for target 'kernel.o' failed make[2]: *** [kernel.o] Error 1 Makefile.x86:28: recipe for target 'all' failed make[1]: *** [all] Error 2 Makefile:59: recipe for target 'all' failed make: *** [all] Error 2

    作者回复: 是不是下载 的完整代码

    2021-06-07
    3
    2
收起评论
显示
设置
留言
35
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部