共计 2018 个字符,预计需要花费 6 分钟才能阅读完成。
为什么要在 M1 芯片上折腾 ucore?
M1 芯片是 2020 年之后推出的全新适配于 Macbook 的 Arm64 芯片。因为底层的指令集与 x86_64 不同,因而面临着很多兼容性的问题。截止开始写博文的时候,M1 芯片曾经经验了靠近 2 年的磨合期,日趋完善。
ucore 是清华大学为计算机专业本科生提供的微型操作系统内核,代码是基于 x86 架构编写的。麻雀虽小五脏俱全,笼罩了内核的次要机制。通过改写 ucore,堪称学习操作系统原理的不二法门。
之所以要在 M1 芯片上进行 ucore 的开发,调试,次要因为 Macbook 因为其良好的工作体验曾经成为很多程序员离不开的工作机器,而 M1 芯片目前并不反对虚拟机产品运行 x86 零碎(当然 qemu 目前曾经反对,但基于软件实现,效率非常低)。因而如果想用 M1 来开发调试 ucore,肯定会波及到穿插编译的问题。
因而作者花了一下午的工夫,终于搞定了在基于 M1 芯片的 Macbook 上进行 ucore 的编译,运行和调试。写下这篇文章分享给大家我的计划。
筹备相干工具
qemu
qemu 是十分成熟的虚拟化解决方案,通过软件的形式逐条将指标文件的二进制指令翻译成指标架构反对的二进制指令,尽管效率不高,然而使用方便,对 M1 芯片反对非常欠缺,足够用来调试 ucore 了。
# 装置 homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 装置 qemu
brew install qemu
穿插编译工具 gcc
穿插编译意味着咱们在某一架构上编译另一架构的指标文件(能够使 lib,也能够是可执行文件)。因为最终编译的指令集不同,尽管能够依据高级语言和汇编语言编译相应的指标文件,然而并不能在开发者应用的架构上运行指标文件。
在编译 ucore 中,咱们所在的架构师 Arm64 架构,指标架构是 i386 架构。按理来说应该用 i386 架构下的 gcc 进行编译,然而 M1 芯片曾经不反对 32 位的编译器,所以只能装置能够将源码编译为 x86_64 指令的编译工具(x86_64 兼容 i386)。
在 MacOS 中能够应用 homebrew 装置 x86_64-elf-gcc 进行编译brew install x86_64-elf-gcc
。
调试工具
和 gcc 一样,也要装置 x86_64 的调试程序 x86_64-elf-gdb,同样也是应用 homebrew。我不是没有试过原装的 lldb,然而在连贯 qemu 的时候会呈现 error: failed to get reply to handshake packet
的报错。如果有趣味的同学能够钻研一下,我就不搞了。
编译
筹备好所有的工具,就能够开始编译 ucore 了,进入 labcodes/lab1 目录下。
首先须要批改 Makefile 文件,尽管 HOSTCFLAGS 中设置了 - g 的标记,然而同样也指定了代码优化等级为 -O2,集体认为改为 -O0 比拟适合。
执行上面的指令make GCCPREFIX=x86_64-elf-
,次要是指定穿插编译工具。因为代码比较简单,很快就能够编译胜利,也不会有什么坑。
运行和调试
切换到 labcodes/lab1,在 bin 目录下,会呈现 4 个文件,其中 kernel 中蕴含了可执行文件的符号表,用来调试用的。而.img 文件是零碎镜像。
因为 ucore 是一个基于 i386 编写的内核,因而必须要用 qemu-system-i386 能力正确运行。
qemu-system-i386 -S -s -hda bin/ucore.img -monitor stdio
因为 -S -s
的标记,零碎并没有启动,须要用 gdb 来启动零碎。依照上面的流程逐个执行,就能够看到零碎停留在断点 memset 处,执行 continue,操作系统将会启动,并在 qemu 窗口一直打印100 ticks
。
$ x86_64-elf-gdb
GNU gdb (GDB) 12.1
(gdb) file bin/kernel
Reading symbols from bin/kernel...
(gdb) target remote :1234
Remote debugging using :1234
0x0000fff0 in ?? ()
(gdb) b memset
Breakpoint 1 at 0x1032c2: file libs/string.c, line 271.
(gdb) c
Continuing.
Breakpoint 1, memset (s=0x10fa16, c=0 '\000', n=4850) at libs/string.c:271
271 memset(void *s, char c, size_t n) {(gdb) c
Continuing.
总结
本文介绍了如何应用穿插编译的形式在应用 M1 芯片的 Macbook 上进行 ucore 的编译,运行和调试。过程中须要踩几个穿插编译和跨平台调试的坑。借助 qemu 虚拟化,在 Arm64 芯片上运行 x86_64 架构的零碎内核。