OHOS3.0启动流程分析丨init阶段 原创 精华
【本文正在参与优质创作者激励】
目录
init阶段
内核启动完是init阶段,源码的路径在 base\startup\init_lite\services\src\main.c,虽然文件夹命名为init_lite,但是init部分的代码是小型系统(small system)和标准系统(standard system)通用的。相关码仓启动模块init进程 (gitee.com)
接下来参考linux内核梳理下启动流程,
Liteos-A | Linux |
---|---|
INIT_CHECK_ONLY_ELOG(setenv(“UV_THREADPOOL_SIZE”, “1”, 1) == 0, “set UV_THREADPOOL_SIZE error : %d.”, errno); | |
CloseStdio(); // 1.关闭输入输出 | |
OpenLogDevice(); // 2.在串口打印调试信息 | |
PrintSysInfo(); | // PrintSysInfo(); |
MountBasicFs(); // 3.挂载目录,建立索引节点 | |
CreateDeviceNode(); | |
EnableDevKmsg(); // 4.开启DevKmsg | |
MakeSocketDir(“/dev/unix/socket/”…) // 5.建立Socket文件夹 | |
SignalInitModule(); | SignalInitModule(); // 6.Singnal初始化 |
ExecuteRcs(); | ExecuteRcs(); // 7.执行命令脚本文件 |
InitReadCfg(); | InitReadCfg(); // 8.【重要】解析并执行*.cfg文件。 |
StartParamService(); // 9.启动参数服务 | |
(void)pause(); | (void)pause(); |
1.关闭输入输出
/dev/null,空设备,特殊的设备文件,丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。其作用是对stdin/stdout/stderr进行保护,把文件描述符0,1,2分配出去,以后再分配的时候就不会将stdin/stdout/stderr打开,以达到保护目的。
2.在串口打印调试信息
写入/dev/kmsg的信息,可以在dmesg(开机信息)中查看。
标准系统空实现,不深究了。
3.挂载目录,建立索引节点
4.开启DevKmsg
注释很清楚了,printk_devkmsg默认是流控的,设置为on取消流控。
5.建立Socket文件夹
/dev/unix/socket/不过这个干啥用的,还没搞清楚。
6.Singnal初始化
7.执行命令脚本文件
兼容常规的*.rc文件,是执行linux运行命令的脚本文件。
8.【重要】解析并执行*.cfg文件。
OHOS3.0中的命令脚本文件是*.cfg,采用JSON格式,存储的信息更多一些。前面都是启动系统的一些准备工作,而接下来才是重要部分。还是用个表格来分析
base\startup\init_lite\services\src\init_read_cfg.c
Liteos-A | Linux |
---|---|
InitParamService(); // a.初始化服务参数的工作区 | |
LoadDefaultParams(“/system/etc/ohos.para”); // 这个文件存放了OHOS版本信息等参数。 | |
ParseInitCfg(“/etc/init.cfg”); | ParseInitCfg(“/etc/init.cfg”); // b.解析init.cfg文件 |
ParseOtherCfgs(); | ParseOtherCfgs(); // c.解析执行/system/etc/init/*.cfg文件 |
DoJob(“pre-init”); | |
TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1); | |
DoJob(“init”); | |
TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2); | |
DoJob(“post-init”); | |
TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3); | |
InitStageFinished(); | |
ReleaseAllJobs(); | |
PostTrigger(EVENT_BOOT, “pre-init”, strlen(“pre-init”)); // d.PostTrigger | |
PostTrigger(EVENT_BOOT, “init”, strlen(“init”)); | |
PostTrigger(EVENT_BOOT, “post-init”, strlen(“post-init”)); |
a.初始化服务参数的工作区
b.解析init.cfg文件
./base/startup/init_lite/services/etc/init.cfg
./base/update/updater/services/etc/init.cfg
./out/ohos-arm-release/packages/phone/system/etc/init.cfg
./out/ohos-arm-release/packages/phone/updater/etc/init.cfg
./out/ohos-arm-release/obj/base/startup/init_lite/services/base/startup/init_lite/services/etc/init.cfg
./out/ohos-arm-release/obj/base/update/updater/services/base/update/updater/services/etc/init.cfg
./device/hisilicon/hi3516dv300/updater/init.cfg
编译框架使用的哪个init.cfg还有待确定。
①.解析"services"部分,并执行
②.解析"jobs"部分,并执行
③.提取init.cfg中"import"的部分,并执行
到这里init.cfg就解析并执行完毕了,需要注意的是,import导入的cfg文件是最后才执行的。
c.解析执行/system/etc/init/*.cfg文件
和import的原理类似,遍历system/etc/init文件夹下的*.cfg文件,并执行。我感觉写在init.cfg的import中应该也是可以的。
d.PostTrigger
PostTrigger(EVENT_BOOT, “pre-init”, strlen(“pre-init”));
9.启动参数服务
使用Libuv库,官网地址。作为Nodejs的底层。
至此,init启动结束,进入pause()。总结下来init首先会执行一些通用的准备操作,同时兼容常规linux内核启动脚本,之后在执行鸿蒙init.cfg和单板相关*.cfg。以上分析都是我个人见解,如有错误欢迎指正。
【本文正在参与优质创作者激励】
讲解的非常全面,感谢分享。
咦 我怎么有种在看linux内核的感觉呀
学习到了~
学习到了~
收藏 点赞 评论三联哈哈
好文章,作者加油