鸿蒙系统如何运⾏,鸿蒙系统的启动流程,建议收藏!
声明:严格来说本⽂档并⾮真正原创的,这是上了朱有鹏⽼师的免费课《想读懂鸿蒙 2.0 源码,也许你需要先懂这些》之后,做的⼀些总结。
课程时间⼀个半⼩时,内容也很多,学习过程中我发现朱⽼师的 PPT 上部分代码/⽂件,在我本地的鸿蒙系统代码上不到,或者路径不相同,所以我就做了⼀些整理。
这⾥仅摘取课程中的鸿蒙系统在 HI3516DV300 平台上的启动流程部分(从 30:00 开始讲解启动过程)进
⾏汇总和整理,如有错误,请朱⽼师和各位同学指正。后继在学习过程中会继续对本⽂当作修正升级。
我的本地代码是基于最新发布的 OpenHarmony 1.1.0 LTS(2021-04-01) 版本抓取的,代码根⽬录 OHOS1_1_0LTS:
在根⽬录下执⾏:
即可开始编译 hi3516dv300 平台代码。输出的过程⽂件和最终 bin,在以下路径内:
因为本⼈还没有开发板,⽆法烧录、抓取 log 分析以及做相关的操作去验证。
01
U-Boot 启动
到此为⽌属于 U-Boot 的启动。Uboot 不属于鸿蒙系统,这⾥不做进⼀步分析,代码在⽬录:
02
汇编代码引导 LiteOS-a 内核
Uboot 引导 liteos-a 内核启动起来,需要有⼀个⼊⼝,在:
打开这个⽂件,可见:
reset_vector 就是整个鸿蒙内核启动的⼊⼝点,这是⼀个符号,定义在:
同⽬录下还有⼀个 reset_vector_up.S ⽂件,因为 HI3516 是 ARM Cortex A7 双核处理器,所以需要看 mp(多核)这个⽂件,up 这个是单核的。
打开 reset_vector_mp.S ⽂件,到“reset_vector:”符号,从这⾥开始跑汇编代码,引导 liteos-a 内核的启动,⼀直到:
这⾥调⽤⼀个 main 函数,然后执⾏ _start_hang 进⼊死循环,⾄此汇编代码阶段就结束了。通过 main 函数进⼊内核 LiteOS-a 启动的C 语⾔阶段。
03
内核 LiteOS-a 的 C 语⾔启动阶段
上⾯汇编阶段调⽤的 main 函数,位于:
main 函数通过 OsSystemInfo(); 函数⾥打印下⾯这些信息:
从这⼀步的 main 开始读 liteos-a 的 C 语⾔源码,可以直接在鸿蒙代码的
进⾏阅读理解。不过,推荐从下⾯仓库拉代码下来读,鸿蒙内核源码注解分析:
这是在鸿蒙官⽅开源项⽬ kernel_liteos_a 基础上,给源代码加上了给常详细的中⽂注解,有利于加快理解。main 函数截图如下:
Line173 ⾏调⽤的 OsMain() 函数,位于:
主要做了:
其中的:
OsTickInit(......); // tick 初始化,包含注册中断事件,硬件时钟初始化,启动节拍,注册硬中断。
OsKernelInitProcess(); // 完成内核进程的初始化,调⽤:
⾸先创建 2 号进程 KProcess,最⾼优先级 0,这是⼀个内核态进程。鸿蒙进程⼀共有 32 个优先级(0-31),其中 0-9 级为内核进程,⽤户进程可配置的优先级有 22 个(10-31)。
然后创建 2 号进程的 2 个⼦线程 ResourceTask 和 KIdle,详见代码。可以在 shell 内执⾏ task 命令查看进程和线程信息,表格见⽂末。
注意,此时 1 号进程还没有创建,它是⽤户态根进程,要到稍微后⾯才创建。
OsSwtmrInit(); //软时钟模块初始化,创建 Swt_Task(software timmer) 线程,⽗进程是 2 号进程 KProcess。
OsSystemInit(); //系统初始化,系统软硬件的初始化,由 2 号进程 KProcess 创
建“system_wq”“SystemInit”“memshow_Task”等线程。
“SystemInit”线程:
其⼊⼝函数则由内核外部提供,在:
⾥的 SystemInit() 函数:
其中的:
ProcFsInit(),创建和挂载/proc ⽂件系统,代码见:
SDK_init() //calling SDK_init form HISI_SDK,初始化 3516DV300 特有的 SDK,⽤内部的 DSP 硬件来做视频编解码,只提供相关库⽂件,不开源。
代码在:
OsMountRootfs(),挂载根⽂件系统:
可以通过 tar -tf rootfs.tar 命令查看⾥⾯都有些什么内容。开始查根⽂件系统⾥的 /bin/init 并创建 init 进程。
OsUserInitProcess(),调⽤:
这时候才创建 1 号进程 init,这是⽤户态根进程,优先级别为 28,这个 1 号进程接下来会创建和启动其他的⽤户态进程
(shell/apphilogcat/.../ai_server等 3~9 号进程)。shell命令属于什么语言
接下来这⼀⼩部分还没理解透,调⽤ OsLoadUserInit() load init 的相关配置:
再使⽤ __user_init_entry 参数,调⽤OsUserInitProcessStart()。
__user_init_entry 就是第⼀个⽤户态根进程的地址,它通过宏 LITE_USER_SEC_ENTRY 进⾏定义,代码在:
/bin/init 就是 kernel 调⽤ init_lite的⼊⼝【见第四阶段对这个的解释】,由此进⼊应⽤层的启动。跑完 OsMain() 函数,LiteOS-a 内核的启动⼯作就基本上完成了,接下来就开始了鸿蒙系统应⽤层的启动。
04
鸿蒙系统应⽤层的启动
这个应⽤层实际上就是鸿蒙的 framework,启动 init ⼊⼝在:
ReadFileToBuf()
这⼀步读取的 /etc/init.cfg ⽂件,在上⾯ OsMountRootfs() 挂载根⽂件系统的时候就挂载上了,它是:
的副本,这个⽂件就包含了“pre-init”“init”“post-init”的相关操作,分别是设置挂载⼀些设备、设置好路径,启动服务等⼯作。
⽽后⾯的"services"则包含⼀组服务的定义,它们是系统⾥的关键进程。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论