声明:严格来说本文档并非真正原创的,这是上了朱有鹏老师的免费课《想读懂鸿蒙 2.0 源码,也许你需要先懂这些》之后,做的一些总结。

课程时间一个半小时,内容也很多,学习过程中我发现朱老师的 PPT 上部分代码/文件,在我本地的鸿蒙系统代码上找不到,或者路径不相同,所以我就做了一些整理。
这里仅摘取课程中的鸿蒙系统在 HI3516DV300 平台上的启动流程部分(从 30:00 开始讲解启动过程)进行汇总和整理,如有错误,请朱老师和各位同学指正。后继在学习过程中会继续对本文当作修正升级。
$repo init -u https://gitee.com/openharmony/manifest.git -b refs/tags/OpenHarmony_release_v1.1.0 --no-repo-verify
$repo sync
OHOS1_1_0LTS$ hb set
[OHOS INFO] Input code path: .
OHOS Which product do you need?
->ipcamera_hispark_taurus@hisilicon
OHOS1_1_0LTS$ hb build
out\hispark_taurus\ipcamera_hispark_taurus
因为本人还没有开发板,无法烧录、抓取 log 分析以及做相关的操作去验证。
01
U-Boot 启动
System startup
Uncompress Ok!
U-Boot 2016.11 (......) hi3516dv300
............
............(省略)
Hit any key to stop autoboot: 0
MMC read: dev #0, block # 2048, count 16384 ... 16384 blocks read: OK
## Starting application at 0x80000000...
device\hisilicon\third_party\uboot\u-boot-2020.01
02
汇编代码引导 LiteOS-a 内核
kernel\liteos_a\tools\build\liteos.ld
ENTRY(reset_vector)
INCLUDE board.ld
SECTIONS
{
......
}
kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_mp.S
同目录下还有一个 reset_vector_up.S 文件,因为 HI3516 是 ARM Cortex A7 双核处理器,所以需要看 mp(多核)这个文件,up 这个是单核的。
“
bl main
_start_hang:
b _start_hang
”
这里调用一个 main 函数,然后执行 _start_hang 进入死循环,至此汇编代码阶段就结束了。通过 main 函数进入内核 LiteOS-a 启动的 C 语言阶段。
03
内核 LiteOS-a 的 C 语言启动阶段
kernel\liteos_a\platform\main.c
******************Welcome******************
Processor : Cortex-A7*2
Run Mode : SMP
GIC Rev : GICv2
build time : ......
Kernel : Huawei LiteOS 2.0.0.xxx
********************************************
main core booting up...
...
...
kernel\liteos_a\platform\main.c
https://gitee.com/weharmony/kernel_liteos_a_note.git
这是在鸿蒙官方开源项目 kernel_liteos_a 基础上,给源代码加上了给常详细的中文注解,有利于加快理解。

kenerl\liteos_a\kernel\common\los_config.c
主要做了:

其中的:
①OsTickInit(......); // tick 初始化,包含注册中断事件,硬件时钟初始化,启动节拍,注册硬中断。
OsProcessCreateInit(processCB, OS_KERNEL_MODE, "KProcess", 0);
③OsSwtmrInit(); //软时钟模块初始化,创建 Swt_Task(software timmer) 线程,父进程是 2 号进程 KProcess。
④OsSystemInit(); 系统初始化,系统软硬件的初始化,由 2 号进程 KProcess 创建“system_wq”“SystemInit”“memshow_Task”等线程。
“SystemInit”线程:

其入口函数则由内核外部提供,在:
device\hisilicon\hispark_taurus\sdk_liteos\mpp\module_init\src\system_init.c
里的 SystemInit() 函数:

kernel\liteos_a\fs\proc\os_adept\proc_init.c
②SDK_init() calling SDK_init form HISI_SDK,初始化 3516DV300 特有的 SDK,用内部的 DSP 硬件来做视频编解码,只提供相关库文件,不开源。
代码在:
device\hisilicon\hispark_taurus\sdk_liteos\mpp\module_init\src\sdk_init.c
out\hispark_taurus\ipcamera_hispark_taurus\rootfs.tar
OsProcessCreateInit(processCB, OS_USER_MODE, "Init", OS_PROCESS_USERINIT_PRIORITY); //28
接下来这一小部分还没理解透,调用 OsLoadUserInit() load init 的相关配置:

再使用 __user_init_entry 参数,调用OsUserInitProcessStart()。

__user_init_entry 就是第一个用户态根进程的地址,它通过宏 LITE_USER_SEC_ENTRY 进行定义,代码在:
kernel\liteos_a\kernel\user\src\los_user_init.c

04
鸿蒙系统应用层的启动
这个应用层实际上就是鸿蒙的 framework,启动 init 入口在:
base\startup\init_lite\services\src\main.c

①ReadFileToBuf()
vendor\hisilicon\hispark_taurus\init_configs\init_liteos_a_3516dv300.cfg
而后面的"services"则包含一组服务的定义,它们是系统里的关键进程。

②DoJob("init")
由“1 号进程 init”,在应用层通过 start 指令创建和启动:shell/apphilogcat/.../ai_server 等 3~9 号进程,它们都是用户态进程,父进程都是“1 号进程 init”。
init 将根据上面 cfg 配置的 job 和 services 来做对应的操作和启动对应的服务程序,并设置它们的 uid、gid、进程优先级和权限等。
可以在 shell 内执行 task 命令查看进程和线程信息,表格见文末。
base\startup\init_lite\README_zh.md
这个 init 组件(即 base\startup\init_lite)负责处理从内核加载第一个用户态进程(2 号进程 init)开始,到第一个应用程序启动之间的系统服务进程启动过程。
init 将系统启动分为三个阶段:
“pre-init”阶段:启动系统服务之前需要先执行的操作,例如挂载文件系统、创建文件夹、修改权限等。
“init”阶段:系统服务启动阶段。
“post-init”阶段:系统服务启动完后还需要执行的操作。
上述每个阶段在配置文件 init.cfg 中都用一个 job 表示,每个 job 都对应一个命令集合,init 通过依次执行每个 job 中的命令来完成系统初始化。
job 执行顺序:先执行“pre-init”,再执行“init”,最后执行“post-init”,所有 job 都集中放在 init.cfg 的 jobs 数组中。
除上述 jobs 数组之外,init.cfg 中还有一个 services 数组,用于存放所有需要由 init 进程启动的系统关键服务的服务名、可执行文件路径、权限和其他属性信息。
配置文件 init.cfg 位于代码仓库 vendor/hisilicon/hispark_aries/init_configs/ 目录,部署在 etc/ 下,采用 json 格式,文件大小目前限制在 100KB 以内。
init 组件会编译成 out\hispark_taurus\ipcamera_hispark_taurus 目录下的 bin/init,同时打包在根文件系统 rootfs.tar 内,上面挂载根文件系统时,会挂载成 bin/init,由第三阶段的最后一步 OsUserInit() 调用和执行。
base\startup\init_lite\README_zh.md
05
鸿蒙应用(APP)的启动
鸿蒙应用开发的第一个示例程序“helloworld”的启动也应该类似。
#include <stdio.h>
#include "ohos_init.h"
#include "ohos_types.h"
void HelloWorld(void)
{
printf("[Init] Hello World!\n");
}
SYS_RUN(HelloWorld);
06
#task命令查看进程/线程信息(简表)



鸿蒙人专属的华为开发者日(HDD)来啦!技术干货+现场鸿蒙场景沉浸体验+全天 Codelab!社区大佬带你一起飞!
活动时间:2021 年 4 月 17 日(本周六)
活动地点:上海市浦东新区卓美亚喜马拉雅酒店 3 楼宴会厅
想亲手摸一摸搭载了鸿蒙系统的电器么?想看看大佬是怎么开发鸿蒙应用么?报名还有鸿蒙官方周边送上哦!

如果没法去线下的话
也可以点击“阅读原文”报名我们线上直播
👇点击关注鸿蒙技术社区👇
专注开源技术,共建鸿蒙生态

点“阅读原文”立即报名线上直播






