当前位置: 首页 > news >正文

Fuchsia入门-zircon微内核单独编译启动

“**实践出真知**”,对新手来说,别人给你说代码架构是怎样怎样的,给你一堆文档,看完还是**一头雾水**。实践很简单,就是代码编译运行,打log。之前的文章:[Fuchsia入门-简介和代码介绍](),介绍Fuchsia的代码编译运行,但是操作起来很**不爽**:
  • 下载代码需要几个小时

  • 代码下载编译后达到将近100G空间

  • 编译需要两个小时

  • qemu运行卡顿

这还怎么**学习调试![](https://i-blog.csdnimg.cn/direct/1de1d1204afd4657b38758ff7a488468.png)**,官网就是给咱**摆了一道**,然后官网基本就是纯概念的讲解。针对这种情况,还想学习Fuchsia主要是zircon微内核原理的人就很痛苦,要么直接看**网页代码**:https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/;bpv=0;bpt=0

然后看官网文档

https://fuchsia.dev/fuchsia-src/get-started?hl=en上看看纯概念文档。

但是还是那句话,**不运行这能学吗?**这也是本篇文章要解决的问题,我们需要**小而精**而且可以qemu运行的代码,直接上干货:**https://github.com/PanQL/zircon**

1. Zircon内核编译运行

https://github.com/PanQL/zircon这个是清华的一个同学从Fuchsia官方的20190715版本代码仓库中分离出来的**Zircon代码**,用于进行Zircon内核学习,现在已经没有了。可以通过Makefile脚本进行编译并在**qemu上运行**。 Zircon 是为 Fuchsia 提供支持的**核心平台**。Zircon 由内核(源代码在/zircon/kernel)以及系统启动、与硬件对话、加载用户空间所必需的一小组用户空间服务、驱动程序和库(源代码在/zircon/system/)组成处理并运行它们等。Fuchsia 在此基础之上构建了一个更大的操作系统。 可以这么说,学习Fuchsia的**精华和原理**,搞清楚这个Zircon就差不多了。

编译环境搭建:

为了减小仓库体积,将prebuilt目录进行了大幅调整;因此运行之前请下载google预编译好的**clang**:

https://chrome-infra-packages.appspot.com/p/fuchsia/clang/linux-amd64/+/

解压后放到某个权限合适的位置,这里我们放入/home/book/tools/clang

然后在代码的public/gn/toolchain/clang.gni绝对目录修改为对应位置,如下:

默认x64架构编译运行,在代码根目录下执行:

Make build Make run

如果想在arm平台上执行,需要修改out/args.gn中的legacy-image-x64为legacy-image-arm64,然后执行:

make build make runarm

2. 学习感想分享

现在我们有**可运行代码**和**文档**,就像OS入门系列里面各个OS都有这两个东西,但是直接看代码也看不懂,直接看文档也不行,然后入门很困难,这里有一个大的误区: 面对一个复杂系统,代码和文档**只看一遍是肯定不行的**,需要三遍起步,而且要代码文档循环的一遍一遍看。 事实就是这么残酷,没有不劳而获,只能付出时间。万事开头难,还有一个关键就是**怎么开头**,我感觉开头首先要调动**兴趣和积极性**,从自己擅长的角度,比如我觉得这个代码可以运行**能打印出来我写的log**,我就会相信这个代码,感觉有兴趣去探索,那我们开始: 我们先抛开官网那一堆概念,**直接看代码的启动过程**,遇到不懂的代码再去看官网概念文档。然后接触一部分概念后,再整体去看一般概念(记不全),然后就是继续看代码,看代码有瓶颈了再看一般文档,循环往复,直到代码和文档都懂了。

修改代码:

运行:

到这里,是否能提起你的兴趣去探索这个代码?

假如你已经有兴趣探索这个代码,那么接下来按照上面说的代码+文档循环往复,这里有一个**功力**的问题:**有的人看的快,有的人看的慢**。或许你会说这跟**工作经验**有关系,大佬看一天的进度,小白可能需要一星期还得加班。是什么造成这样的差异?我们先扯点我自己的见解再开始进入代码,功力的高低的表现,比如有人说看代码如喝水,千把行不歇的,有让你说每一行看着都困难,一个函数摸索老半天,我感觉这里的**功力**与**共性知识**的积累相关,看的多了,积累的基础共性知识就多了,就看的更快。那么共性知识的本质是什么,还是**人类理解世界的能力**,纵观人类的组织结构例如一个**王朝**的组织就跟**操作系统**里面很多机制很像,再本质一点为什么人类会这么组织,那就是我们的**基因**,基因又是从**自然**而来,假如换一个星球一切的根基就又不同了,像三体游戏里面从**文明**的角度来看了,人类是有局限性,但是这种局限性促使我们更快的了解人类的共识,发展自我。 我们去理解一个新的事物可以借助**共识**,但是不能拘泥于细节和条条框框,站在共识的角度更容易去创新,例如最近马斯克说的汽车这么多零部件,当然这些零部件都是有用的,但是为什么不**一体浇筑**岂不是更简单有效率,这种野蛮而又简单的想法像**狼入羊群**一样,冲击传统思维但是又**符合基本规律**。 有时自己也有一些疑问,比如**学习这些东西对自己有多大帮助**,以后忘记了怎么办,这点还想需要一个大局观,**把握本质**脉络可能就是学习的真意,就像领导不看你细节的代码描述只要一个流程图或者框架图,随着这些知识的**理解融汇**,最后达到一个复杂的、不可替代的程度,算是一个**人才**了。 路漫漫,笔者也是一个技术菜鸟,啥都不精通,毅力也不够,天赋也没有,写的这些文章也都是入门篇,之后代码分析估计你会体会到**一顿乱拳**的感觉。只是去想想这些,总有点帮助。下面进入代码的的世界。

3. 编译过程分析

编译就是执行make build,在代码根目录Makefile中:

build: config cd out && ../buildtools/ninja config: buildtools/gn gen --export-compile-commands=x64 out

build依赖于config,conffig用了gn命令,然后build中又使用了ninja命令就完成了编译

代码doc文档里面有这两个工具的解释,都是谷歌很好用的编译工具。不细研究,我们先知道gn就是生成需要编译那些文件到out/compile_commands.json,ninja就去编译这些文件成二进制,ninja的优势就是增量编译和并行编译,代码修改后二次编译非常的快,就是这个痛点谷歌大牛搞了这个工具,用着超级棒

运行代码执行:make run

./scripts/run-zircon-x64-z./out/legacy-image-x64.zbi-t./out/multiboot.bin

./scripts/run-zircon-x64是个脚本:

exec$DIR/run-zircon-ax64"$@"

exec $DIR/run-zircon也是个脚本:

exec$QEMU-kernel"$QEMU_KERNEL"-initrd"$QEMU_INITRD"\$ARGS-append"$CMDLINE""$@"
  • $QEMU_KERNEL就是./out/legacy-image-x64.zbi,也就是

    kernel镜像

  • $QEMU_INITRD就是./out/multiboot.bin

  • $ARGS就是

    qemu命令

    的参数

  • $CMDLINE就是传给

    内核的参数

    ,在内核代码里面可以获取这些信息

那么./out/multiboot.bin是个什么东西?

Multiboot是一个协议,一般协议就是一个约定为了对接两部分的执行实体,具体来说BootLoader去适配Kernel,一般来说是一对一的关系,那么某个bootloader就不具有通用性,有问题就可以通过抽象一层来解决,所以就有了Multiboot协议,满足这个协议的bootloader和kernel可以随意的适配。启动的顺序为qemu->bootloader->multiboot->kernel

Bootloader和multiboot的代码在zicron工程下有,这里不深入研究,直接看kernel。

4. kernel入口分析

Kernel的入口为**_start**,代码在kernel/arch/x86/start.S

从进入_start开始,到跳转到C语言入口lk_main之前,start.S中主要依次完成以下这些任务:

  • 设置临时栈

  • 清空bss段(此处涉及KASLR的实现,清空之前进行了复制)

  • 初始化boot时期的alloc机制

  • 设置新的页表

  • 跳转到fixups代码所在位置,修正KASLR带来的偏差

  • 设置中断向量表

平台初始化可以参考:https://blog.csdn.net/ganyao939543405/article/details/85204534

进入lk_main()函数就是大家熟系的c++语言了,这里我们之前也加了打印。

为什么kernel的入口是_start?

legacy-image-x64.zbi可见kernel的格式是zbi(Zircon Boot Image),参考:https://fuchsia.dev/fuchsia-src/concepts/process/everything_between_power_on_and_your_component

ZBI格式是一种简单的容器格式,它嵌入了引导加载程序传递的项目,包括特定于硬件的信息、提供引导选项的内核“命令行”和 RAM 磁盘映像(通常是压缩的)。内核在引导的早期阶段提取一些基本信息供自己使用。

kernel/target/pc/multiboot/multiboot-main.c中对zbi进行了解析

// Find the kernel item.constzbi_header_t*kernel_item_header=NULL;result=zbi_for_each(zbi,&find_kernel_item,&kernel_item_header);if(result!=ZBI_RESULT_INCOMPLETE_KERNEL){panic("ZBI missing kernel");}// This is the kernel item's payload, but it expects the whole// zircon_kernel_t (i.e. starting with the container header) to be loaded// at PHYS_LOAD_ADDRESS.constzbi_kernel_t*kernel_header=(constvoid*)(kernel_item_header+1);

zbi是二进制文件,里面开头放了zbi_header_tzbi_kernel_t

这两个结构体的定义见system/public/zircon/boot/image.h,这个文件也是ZBI格式定义的核心文件。

Multiboot解析zbi文件后把kernel入口地址放入了寄存器,之后就跳转执行了

"a"(kernel_entry),// %rax: kernel entry point

再来看_start,在kernel/arch/x86/start.S中

// These symbols are used by image.S.globalIMAGE_ELF_ENTRYIMAGE_ELF_ENTRY=_start

在kernel/image.ld链接文件中,规定了入口地址

ENTRY(IMAGE_ELF_ENTRY)

但是看这个链接文件上面的解释,zicrcon并没有用到这个ENTRY而是对zbi二进制文件直接解析找到的IMAGE_ELF_ENTRY,同样在kernel/arch/x86/start.S中如下:

// ZBI file header (zbi_header_t)ZBI_CONTAINER_HEADER(_zbi_file_header,boot_load_end-_zbi_kernel_header)// ZBI kernel header (zbi_header_t)DATA(_zbi_kernel_header).intZBI_TYPE_KERNEL_X64.intboot_load_end-_zbi_kernel_payload.int0.intZBI_FLAG_VERSION.int0.int0.intZBI_ITEM_MAGIC.intZBI_ITEM_NO_CRC32END_DATA(_zbi_kernel_header)// ZBI_TYPE_KERNEL payload (zbi_kernel_t)DATA(_zbi_kernel_payload).quadPHYS(IMAGE_ELF_ENTRY)//该处地址为start.S中的_start地址.quad boot_bss_end-boot_load_end// 在该image加载之后,还应该余下多少内存空间END_DATA(_zbi_kernel_payload)
篇幅有限,下次继续从**lk\_main**介绍**启动流程**,可能会更多的涉及zicron内核里面的**内核对象**,这些内核对象是OS里面很基本和简单的抽象,不像linux宏内核那么复杂,更容易理解OS。

后记:

Fuchsia入门文章:[Fuchsia入门-简介和代码介绍](http://mp.weixin.qq.com/s?__biz=MzUzMDMwNTg2Nw==&mid=2247484294&idx=1&sn=f95790f9d109f8653974fd2ca0a8dbc6&chksm=fa5285a2cd250cb45f99a71e3d58539ea55c4090204c909fc0a12ae260ed15563bd437b12ef5&scene=21#wechat_redirect) 的**阅读量**目前还是**最高**的,说明大家对这个系统很有兴趣,一起来学习吧。

啥都懂一点啥都不精通

干啥都能干干啥啥不是

专业入门劝退堪称程序员杂家”。

后续会继续更新,纯干货分析,无广告,不打赏,欢迎分享给朋友,欢迎评论交流!

“那路谈OS与SoC嵌入式软件”,欢迎关注!

个人文章汇总:https://thatway1989.github.io

http://www.jsqmd.com/news/652870/

相关文章:

  • i.MX6U嵌入式开发:从底层逻辑吃透GPIO初始化,告别死记硬背
  • Unity WebGL音频播放踩坑记:放弃AudioSource,我用HTML5 Audio标签搞定了
  • DataX:从原理到实战,构建企业级数据同步平台的完整指南
  • 2026年装配式围挡企业推荐:五大实力品牌深度测评与选购指南 - 2026年企业推荐榜
  • 【比赛游记】2026 ICPC 深圳邀请赛游记
  • 如何彻底告别网盘限速?8大平台直链下载助手终极指南
  • 【Agent-阿程】OpenClaw v2026.4.14 版本更新全解析
  • 避坑指南:CHI协议Credit机制没搞懂?小心你的多核SoC设计出现死锁和性能瓶颈
  • 2025最权威的十大AI辅助写作神器解析与推荐
  • 模块化浪潮下的优选:2026年现阶段拼装方井模具实力厂家深度测评 - 2026年企业推荐榜
  • 应对2026检测更新:如何高效降低论文AI率?5大主流润色工具深度排雷
  • Electron + better-sqlite3跨版本兼容指南:解决Node与Electron版本冲突
  • CVE-2026-5281全解析:Chrome WebGPU零日漏洞暴露的图形安全新战场
  • 如何管理微服务下Oracle的数据库连接数_调整应用节点的MaxActive汇总以防止超processes
  • 从Unicode到自定义标签:JavaScript中Emoji编码转换的两种实战方案
  • 存储优化嵌入式测试
  • ProxyPin抓包软件:开源跨平台网络抓包工具解决接口调试与API测试难题
  • Cisco Packet Tracer新手必看:5分钟搞定VLAN基础配置(附常见错误排查)
  • 边缘计算与云端计算:各司其职,协同共生
  • 测试数据隐私挑战:GDPR 2026新规下的应对策略
  • 盖茨皮带主流齿型的优势与应用 ——HTD/GT2/GT3 技术解析与场景选型指南
  • CVE-2026-35616漏洞分析与修复
  • Windows Server 2019虚拟机性能优化指南:在VMware中分配多少CPU/内存最合适?
  • 告别官方WebRTC编译噩梦:用libdatachannel轻松搞定USB摄像头实时推流
  • vi编辑器模式切换与高效操作指南
  • 从220V到12V5A:手把手教你搞定反激电源的整流桥与滤波电容选型(附PSIM仿真避坑)
  • 2026年现阶段:沫保温箱行业竞争格局深度解析与五强服务商评选报告 - 2026年企业推荐榜
  • 如何修复固定定位头部容器中悬浮下拉菜单的错位问题
  • 2023最新版Unity汉化终极方案:Hub设置+编辑器界面双语切换教程
  • 汇川AM401 PLC 2ms高速采集实战:用PLC-Recorder V2.12.7搞定UDP时间戳(附完整CODESYS程序)