【鸿蒙OS开发入门】12 - 启动流程代码分析之第一个用户态进程:init 进程 之 pre-init 任务详解
- 一、 /etc/init.cfg 系统默认cfg
- 1.1 /etc/init.Hi3516DV300.cfg
- 二、/system/etc/init 下的cfg
- 2.1 faultloggerd32.cfg 崩溃临时日志管理模块
- 2.2 hilogd.cfg 日志文件系统
本系列文章汇总:
- 《【鸿蒙OS开发入门】01 - 搭建Ubuntu虚拟机开发环境》
- 《【鸿蒙OS开发入门】02 - 启动流程代码分析之Uboot 第一阶段:之解压并引导加载u-boot.bin》
- 《【鸿蒙OS开发入门】03 - 启动流程代码分析之Uboot 第二阶段:之board_init初始化》
- 《【鸿蒙OS开发入门】04 - 启动流程代码分析之Uboot 第二阶段:之U_BOOT_CMD原理》
- 《【鸿蒙OS开发入门】05 - 启动流程代码分析之Uboot 第二阶段:之bootm引导加载Kernel OS》
- 《【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核》
- 《【鸿蒙OS开发入门】07 - 安装docker环境编译openharmony 2.0代码》
- 《【鸿蒙OS开发入门】08 - 启动流程代码分析之KernelOS:之启动 liteos_a 内核》
- 《【鸿蒙OS开发入门】09 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 中do_basic_setup()所干的大事》
- 《【鸿蒙OS开发入门】10 - 启动流程代码分析之第一个用户态进程:init 进程》
- 《【鸿蒙OS开发入门】11 - 启动流程代码分析之第一个用户态进程:init 进程 之 Services简介》
- 《【鸿蒙OS开发入门】12 - 启动流程代码分析之第一个用户态进程:init 进程 之 pre-init 任务详解》
- 《【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解》
- 《【鸿蒙OS开发入门】14 - 启动流程代码分析之第一个用户态进程:init 进程 之 post-init 任务详解》
- 《【鸿蒙OS开发入门】15 - 启动流程代码分析之第一个用户态进程:init 进程 之 libuv 做了啥?》
在前面,我们大概介绍了harmony os系统中有哪些Services,本来本文我们要接着分析下,这些service 又是何时启动的。
但实际了,前面在 ParseInitCfg() 中解析出这么多service 后,并没有启动,只是将相关的信息都保存起来了,供后续调用。
接下来几篇文章,我们先来看下 pre-init、init、post-init 这些流程中,又做了什么事,分析完这些后,估计我们对services 启动的时机会有更加深入的了解。
int main(int argc, char **argv)
{
......
// 4. 分别执行pre-init、init、post-init 等相关的事情
InitReadCfg();
--------->
+ ParseInitCfg(INIT_CONFIGURATION_FILE); // "/etc/init.cfg"
+ DumpAllServices(); // 打印所有的服务信息,系统中所有现有的服务保存在 static Service* g_services 中,通过g_servicesCnt来进行索引计数。
+ DoJob("pre-init"); // 执行 `/etc/init.cfg` 中 `pre-init`的内容
+ DoJob("init"); // 执行 `/etc/init.cfg` 中 `init`的内容
+ DoJob("post-init"); // 执行 `/etc/init.cfg` 中 `post-init`的内容
+ ReleaseAllJobs(); // 释放init.cfg中所有的jobs 命令所占用的空间
<---------
......
}
DoJob("pre-init");的作用是,触发启动 json cfg文件中所有pre-init 字段的命令,我们分别来看看这些命令的功能吧。
一、 /etc/init.cfg 系统默认cfg
在init.cfg加载了"/etc/init.usb.cfg", "/etc/init.usb.configfs.cfg", "/etc/init.Hi3516DV300.usb.cfg", "/etc/init.Hi3516DV300.cfg"这几个config,会把它们的信息全部整合进来。
先来看下 init.cfg 中的pre-init阶段的事情吧:
- 关闭Sysrq 系统调试工具
0 - disable sysrq completely
1 - enable all functions of sysrq
2 - enable control of console logging level
4 - enable control of keyboard (SAK, unraw)
8 - enable debugging dumps of processes etc.
16 - enable sync command
32 - enable remount read-only
64 - enable signalling of processes (term, kill, oom-kill)
128- allow reboot/poweroff
256- allow nicing of all RT tasks
使能Sysrq工具后,系统会生成 /proc/sysrq-trigger 这个节点用于调试:
- 启动ueventd Services服务,供后续管理设备节点
- 挂载vendor分区在/vendor目录
- 挂载userdata分区在/data目录
{
"import" : [
"/etc/init.usb.cfg",
"/etc/init.usb.configfs.cfg",
"/etc/init.usb.cfg",
"/etc/init.Hi3516DV300.usb.cfg",
"/etc/init.Hi3516DV300.cfg"
],
"jobs" : [{
"name" : "pre-init",
"cmds" : [
"write /proc/sys/kernel/sysrq 0", // 关闭Sysrq 系统调试工具
"mkdir /acct/uid", // 创建 /acct/uid目录
"chown root system /dev/memcg/memory.pressure_level", // 设置内存压力的通知事件,配合cgroup.event_control一起使用
"chmod 0040 /dev/memcg/memory.pressure_level",
"mkdir /dev/memcg/apps/ 0755 system system",
"mkdir /dev/memcg/system 0550 system system",
"start ueventd", // 启动 ueventd Services服务,供后续管理设备节点
"mkdir /vendor", // 挂载 vendor分区在 /vendor目录
"mkdir /data", // 挂载 userdata分区在 /data目录
"mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor /vendor wait rdonly barrier=1",
"mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/userdata /data wait nosuid nodev noatime barrier=1,data=ordered,noauto_da_alloc"
]
},
1.1 /etc/init.Hi3516DV300.cfg
在/etc/init.usb.cfg", "/etc/init.usb.configfs.cfg", "/etc/init.Hi3516DV300.usb.cfg"中没有pre-init的任务,
我们来看下/etc/init.Hi3516DV300.cfg 中的pre-init任务干了啥:
修改系统所保留空闲内存的最低限值为10240,约为404kb
m i n _ f r e e _ k b y t e s = s q r t ( l o w m e m _ k b y t e s ∗ 16 ) = 4 ∗ s q r t ( l o w m e m _ k b y t e s ) min\_free\_kbytes = sqrt(lowmem\_kbytes * 16) = 4 * sqrt(lowmem\_kbytes) min_free_kbytes=sqrt(lowmem_kbytes∗16)=4∗sqrt(lowmem_kbytes) (注:lowmem_kbytes即可认为是系统内存大小)
{
"import" : [
"init.${ro.hardware}.usb.cfg"
],
"jobs" : [{
"name" : "pre-init",
"cmds" : [
"write /proc/sys/vm/min_free_kbytes 10240"
]
}
二、/system/etc/init 下的cfg
存在 pre-init 的cfg 总共有这些文件:
./base/hiviewdfx/faultloggerd/services/config/faultloggerd32.cfg:3: "name" : "pre-init",
./base/hiviewdfx/hilog/services/hilogd/etc/hilogd.cfg:3: "name" : "pre-init",
我们分别来看下吧。
2.1 faultloggerd32.cfg 崩溃临时日志管理模块
export LD_PRELOAD /system/lib/libdfx_signalhandler.z.so: 提前加载 /system/lib/libdfx_signalhandler.z.so 这个动态链接库。
{
"jobs" : [{
"name" : "pre-init",
"cmds" : [
"export LD_PRELOAD /system/lib/libdfx_signalhandler.z.so"
]
}, {
"name" : "post-fs-data",
"cmds" : [
"mkdir /data/log/faultlog/ 0770 system system",
"mkdir /data/log/faultlog/temp/ 0770 system system",
"start faultloggerd"
]
}
],
"services" : [{
"name" : "faultloggerd",
"path" : ["/system/bin/faultloggerd"],
"uid" : "root",
"gid" : ["system", "log"],
"writepid" : [
"/dev/cpuset/system-background/tasks"
]
}
]
}
2.2 hilogd.cfg 日志文件系统
修改 max_dgram_qlen 为 600,这个参数是域通信 Socket 在数据报( UDP )方式下,队列里最大数据报个数。
官方解释:max_dgram_qlen limits how many datagrams can be queued on a unix domain socket's (SOCK_DGRAM) receive buffer. If a sender tries to send more datagrams, it blocks (in a blocking sendto) or returns error (in a non-blocking sendto). The default value is 10.
{
"jobs" : [{
"name" : "pre-init",
"cmds" : [
"write /proc/sys/net/unix/max_dgram_qlen 600"
]
}, {
"name" : "post-fs-data",
"cmds" : [
"mkdir /data/log/ 0770 system log",
"mkdir /data/log/hilog/ 0750 logd log",
"start hilogd"
]
}
],
"services" : [{
"name" : "hilogd",
"path" : ["/system/bin/hilogd"],
"disabled" : 1,
"uid" : "logd",
"gid" : "log",
"socket" : [
"hilogInput dgram 0666 logd logd passcred",
"hilogControl seqpacket 0600 logd logd false"
]
}
]
}
可以看出,在pre-init 阶段,主要是启动ueventd服务,以及挂载vendor、userdata 这两个分区。
下篇,我们来看下 init 阶段做了哪些事情吧!