openharmony之启动恢复子系统详解
OpenHarmony的启动恢复子系统负责整个系统的启动流程,其中init进程是整个系统启动的第一个用户态进程(PID=1),承担着系统初始化的核心职责
🎯 目录结构
- 📋 理论基础
- 🔍 源码结构分析
- ⚙️ 配置体系详解
- 🚀 启动流程深度解析
- 🐛 调试与故障排除
- 📊 性能优化实践
- 🎯 实战配置案例
系统启动大致流程:
上电 -> Bootloader -> Kernel -> init进程 -> (解析init.cfg) -> 启动appspawn、foundation -> foundation启动AMS、BMS等核心服务 -> 启动Launcher桌面 ->
系统就绪
📋 理论基础
🔄 init进程核心概念
1️⃣ 进程模型与职责
OpenHarmony的init进程是系统的第一个用户态进程(PID=1),采用多阶段启动模型,职责包括:
🎯 核心职责 | 📝 具体任务 | 🔗 相关源码 |
---|---|---|
系统初始化 | 挂载文件系统、创建设备节点、设置系统参数 | init/main.c |
服务管理 | 解析配置、启动服务、监控状态、重启策略 | init/service_manager.c |
事件处理 | 处理uevent、属性变化、信号处理 | init/event_handler.c |
安全管理 | SELinux策略加载、权限检查、沙盒管理 | init/security.c |
2️⃣ 三阶段启动架构
基本概念:
1.jobs是init组件下init.cfg文件中的一组命令构成的集合, 最多添加4096个job。 jobs可以在 cfg 文件中配置,通常在init启动过程中执行,服务于service的正常启动或特定基础功能的初始化。init解析程序会把相同名字job的命令合并到一个job中。同一名字的job只能保证init.cfg中的命令优先执行,其他cfg间的命令执行顺序不保证。
1.1.init进程的三个阶段: pre-init:init前置阶段,其他服务所依赖的,类似于ueventd、watchdog、hilogd等的关键服务会在这一阶段启动,data分区的挂载也在这一阶段进行。 init:init进程的主要阶段,这一阶段除了大量命令的执行,同时也是init分组并行启动boot组(第一组)服务的启动阶段,一些关乎系统功能的重要服务会在这一阶段被拉起。 post-init:这一阶段主要是通过trigger命令触发其他阶段执行,可以把所有被触发的阶段看作一个个的小阶段,也可以把它们统一看作post-init阶段,这一阶段会执行大量命令,并且它还是init分组并行启动normal组(第二组)服务的启动阶段,cfg中配置的大部分服务都是在这一阶段被拉起的。
2.服务管理: 服务管理主要通过init解析服务进程配置文件来实现,服务进程配置文件(xxx.cfg)可以根据业务场景按需配置服务,当前支持的增值服务包括启动控制、按需启动、命令执行、定时启动、fd代持、沙盒。
2.1服务进程配置文件: 一般命名为:serviceName.cfg(serviceName 为服务进程名,例如:appspawn.cfg)
3.系统参数配置: OHOS系统参数为各系统服务提供简单易用的键值对访问接口,使得各个系统服务可以通过各自的系统参数来进行业务功能的配置。
读参数:
param get paramName
GetParameter(const char* key, const char* def, char* value, unsigned int len)
写参数:
param set paramName paramValue
SetParameter(const char* key, const char* value)
监听参数:
hdc shell进入终端,执行param shell,进入Parameter shell后执行 watcher parameter param.key.xxx(系统参数名),
当系统参数值发生变化时,会收到类似"Receive parameter commit 691 change aaa.aaa 11111"的消息
3.1注意事项: 默认DAC规则只允许三方应用对参数具有get, watch 的权限,因此三方应用若需要set权限需要重新设置DAC规则。 此外, 三方应用的selinux权限默认是未设置的,因此需要参照mac访问控制权限设置进行设置
4.沙箱管理: 在init里面创建系统组件沙盒和芯片组件沙盒,native服务根据功能进入system沙盒或者chipset沙盒。在system-sandbox.json、chipset-sandbox.json等配置文件中设置沙盒组件中mount
bind 的目录或文件,实现沙盒组件通过mount属性进行隔离
沙箱相关配置文件:base/startup/init/interfaces/innerkits/sandbox
🔍 源码结构分析
📁 源码目录结构
base/startup/init/
├── 📋 核心模块
│ ├── main.c # 主入口
│ ├── init.c # 初始化逻辑
│ ├── service_manager.c # 服务管理
│ ├── job_parser.c # 作业解析
│ └── param_manager.c # 参数管理
├── 🔧 配置解析
│ ├── cfg_parser.c # 配置解析器
│ ├── json_parser.c # JSON解析
│ └── import_handler.c # 导入处理
├── 🛡️ 安全模块
│ ├── security.c # 安全检查
│ ├── selinux.c # SELinux集成
│ └── sandbox.c # 沙盒管理
├── 🐛 调试工具
│ ├── debug.c # 调试接口
│ ├── log.c # 日志系统
│ └── begetctl.c # 调试命令
└── 📊 工具函数├── utils.c # 通用工具├── file_utils.c # 文件操作└── string_utils.c # 字符串处理
🔍 关键数据结构
1️⃣ 服务结构体(service结构)
// 源码位置: base/startup/init/interfaces/innerkits/service_define.h
typedef struct {char *name; // 服务名称char **path; // 可执行文件路径数组int pathArgs; // 路径参数数量uid_t uid; // 用户IDgid_t gid; // 组IDgid_t *gidCount; // 附加组ID数组int gidCount; // 附加组数量char *secon; // SELinux上下文char *permission; // 权限声明int critical; // 是否为关键服务int once; // 是否只启动一次int restartDelay; // 重启延迟(秒)int restartTimes; // 最大重启次数int restartPeriod; // 重启周期(秒)struct socket_info *sockets; // socket信息struct sandbox_info *sandbox; // 沙盒配置
} service_t;
2️⃣ job结构体
typedef struct {char *name; // 名称char **cmds; // 命令数组int cmdCount; // 命令数量int priority; // 执行优先级struct job *next; // 下一个作业
} job_t;
⚙️ 配置体系详解
📂 配置文件架构
init进程启动时,首先完成系统初始化工作,然后开始解析配置文件。系统在解析配置文件时,会将配置文件分成三类:
- init.cfg默认配置文件,由init系统定义,优先解析。
- /system/etc/init/*.cfg各子系统定义的配置文件。
- /vendor/etc/init/*.cfg厂商定义的配置文件。
/system/etc/init/
├── init.cfg # 主配置
├── ueventd.cfg # 设备节点管理
├── servicemgr.cfg # 服务管理器
├── appspawn.cfg # 应用孵化器
└── *.cfg # 各子系统配置/vendor/etc/init/ # 厂商定制配置
/chipset/etc/init/ # 芯片相关配置
/sys_prod/etc/init/ # 产品配置
/chip_prod/etc/init/ # 单板配置
1️⃣ 分层配置模型
2️⃣ 配置优先级规则
🏆 优先级 | 📂 配置路径 | 🎯 覆盖范围 | 💡 使用场景 |
---|---|---|---|
1️⃣ 最高 | /chip_prod/etc/init/*.cfg | 单板特定配置 | 硬件适配 |
2️⃣ 高 | /sys_prod/etc/init/*.cfg | 产品级配置 | 产品定制 |
3️⃣ 中 | /chipset/etc/init/*.cfg | 芯片级配置 | 芯片适配 |
4️⃣ 低 | /system/etc/init/*.cfg | 系统通用配置 | 基础服务 |
📝 配置文件详解
1️⃣ init.cfg 主配置文件
文件路径: /system/etc/init/init.cfg
完整结构:
{"import": ["/system/etc/init/servicemgr.cfg","/system/etc/init/appspawn.cfg","/system/etc/init/hiview.cfg"],"jobs": [{"name": "pre-init","priority": 0,"cmds": ["mkdir /dev/pts 0755 root root","mount devpts /dev/pts devpts 0 0","start ueventd","load_persist_params","mount_required_partitions","chmod 0666 /dev/__properties__","setparam sys.boot.phase pre-init"]},{"name": "init","priority": 1,"cmds": ["start servicemgr","start hiview","start appspawn","setparam sys.boot.phase init"]},{"name": "post-init","priority": 2,"cmds": ["trigger late-init","trigger boot-complete","setparam sys.boot.phase post-init"]},{"name": "boot-complete","priority": 3,"cmds": ["setparam sys.boot.completed 1","setparam sys.boot.phase completed"]}],"services": [{"name": "ueventd","path": ["/system/bin/ueventd"],"uid": "root","gid": ["root"],"secon": "u:r:ueventd:s0","critical": true,"once": 1,"capabilities": ["CAP_MKNOD", "CAP_SYS_ADMIN"],"priority": -20}]
}
2️⃣ 服务配置文件示例
servicemgr.cfg:
{"services": [{"name": "servicemgr","path": ["/system/bin/sa_main", "/system/profile/servicemgr.xml"],"uid": "system","gid": ["system"],"secon": "u:r:servicemgr:s0","permission": ["ohos.permission.SYSTEM_STARTUP"],"critical": true,"restart_delay": 5,"restart_times": 3,"restart_period": 300,"socket": [{"name": "servicemgr","family": "unix","type": "stream","perm": "0666","uid": "system","gid": "system"}]}]
}
appspawn.cfg(应用孵化器)
{"services" : [{"name" : "appspawn","path" : ["/system/bin/appspawn"],"uid" : "root","gid" : ["system"],"secon" : "u:r:appspawn:s0","permission" : ["ohos.permission.APP_SPAWN"],"socket" : [{"name" : "appspawn","family" : "unix","type" : "stream","perm" : "0666","uid" : "root","gid" : "system"}],"critical" : true}]
}
注意事项:
- cfg文件是严格按照JSON格式编写的,当添加服务或命令未生效时,可以优先排查添加内容的格式是否正确。
- 对于import解析,在解析完成一个import中的cfg文件路径时,会立即解析该cfg文件。
- example1.cfg 需要导入的cfg文件。
- serviceName:service名称, 用户自定义。
- /system/bin/serviceName: 当前服务的可执行文件全路径和参数, 数组形式。
- jobName1:job名称, 用户自定义。
3️⃣ 系统参数配置
参数文件结构:
# 📂 参数文件层次结构
/system/etc/param/
├── ohos_const/ # 系统常量参数
│ ├── ohos.para # 基础系统参数
│ └── build.para # 构建相关参数
├── *.para # 子系统参数
└── ohos.para.dac # 参数权限配置
参数示例:
# 📋 /system/etc/param/ohos.para
# 系统基础参数
const.product.name=OpenHarmony
const.product.model=Dayu200
const.os.version.api=9
const.os.version.release=OpenHarmony 4.0
const.arkui.engine.enable=true# 启动参数
startup.bootanim.enable=true
startup.appspawn.delay=0
startup.servicemgr.timeout=30# 调试参数
debug.init.log.level=INFO
debug.init.log.tags=init,service,job
🚀 启动流程深度解析
🔍 详细启动时序
📊 关键阶段分析
1️⃣ pre-init阶段(0-2秒)
核心任务:
- ✅ 创建基础目录结构
- ✅ 挂载必要的文件系统
- ✅ 启动ueventd服务
- ✅ 加载系统参数
实际执行命令:
# 📂 目录创建
mkdir /dev/pts 0755 root root
mkdir /dev/socket 0755 root root
mkdir /data/misc 0771 system misc# 🔗 文件系统挂载
mount tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,size=1024k,mode=755 0 0
mount devpts /dev/pts devpts rw,seclabel,relatime,mode=600,ptmxmode=000 0 0# ⚙️ 系统参数加载
load_persist_params /system/etc/param/*.para
2️⃣ init阶段(2-5秒)
核心任务:
- ✅ 启动boot组服务
- ✅ 建立服务间通信
- ✅ 初始化核心组件
服务启动顺序:
🔄 顺序 | 🎯 服务 | 📂 配置文件 | 🔗 依赖关系 |
---|---|---|---|
1 | ueventd | init.cfg | 无依赖 |
2 | servicemgr | servicemgr.cfg | 依赖ueventd |
3 | hiview | hiview.cfg | 依赖servicemgr |
4 | appspawn | appspawn.cfg | 依赖servicemgr |
服务启动顺序表
阶段 | 服务 | 配置路径 | 依赖检查 |
---|---|---|---|
pre-init | ueventd | /system/etc/init/init.cfg | 无 |
init | servicemgr | /system/etc/init/servicemgr.cfg | ueventd |
init | hiview | /system/etc/init/hiview.cfg | servicemgr |
post-init | appspawn | /system/etc/init/appspawn.cfg | servicemgr |
3️⃣ post-init阶段(5-10秒)
核心任务:
- ✅ 启动normal组服务
- ✅ 触发boot-complete事件
- ✅ 进入用户态
🐛 调试与故障排除
🔧 调试工具集
1️⃣ begetctl命令详解
基础调试命令:
# 📋 查看服务状态
begetctl dump_service [service_name]# 📊 查看配置加载
begetctl dump_cfg_files# 🔍 查看作业队列
begetctl dump_jobs# ⚙️ 查看系统参数
begetctl param get [param_name]
begetctl param set [param_name] [value]# 🐛 调试日志
begetctl loglevel [level] # 设置日志级别
begetctl logtags [tags] # 设置日志标签
高级调试:
# 🔄 手动启动服务
begetctl start [service_name]# ⏹️ 停止服务
begetctl stop [service_name]# 🔄 重启服务
begetctl restart [service_name]# 📊 查看服务依赖
begetctl check_dependency [service_name]
2️⃣ 日志系统配置
日志级别设置:
{"services": [{"name": "init","loglevel": "DEBUG","logtags": ["init", "service", "job", "param"]}]
}
日志文件位置:
# 📂 日志文件
/var/log/init.log # init主日志
/var/log/servicemgr.log # 服务管理器日志
/var/log/appspawn.log # 应用孵化器日志# 📊 查看日志
tail -f /var/log/init.log | grep -E "(ERROR|WARN)"
🚨 常见故障诊断
1️⃣ 启动卡Logo问题
🔍 故障现象: 设备启动后卡在启动动画界面
📊 诊断步骤:
# 1. 检查关键服务状态
begetctl dump_service | grep -E "(servicemgr|appspawn|hiview)"# 2. 查看系统参数
param get sys.boot.phase
param get sys.boot.completed# 3. 检查文件系统挂载
mount | grep -E "(system|vendor|data)"# 4. 查看SELinux状态
getenforce
ausearch -m avc -ts recent
🛠️ 解决方案:
{"jobs": [{"name": "boot-repair","cmds": ["chmod 0666 /dev/__properties__","setenforce 0","start servicemgr --force"]}]
}
2️⃣ 服务重启循环
🔍 故障现象: 某个服务不断重启,查看日志显示启动失败
📊 诊断步骤:
# 1. 查看服务重启计数
begetctl dump_service [service_name] | grep restart# 2. 检查服务配置
begetctl dump_service [service_name] | grep -E "(path|uid|gid|secon)"# 3. 手动执行服务
/system/bin/[service_binary] --debug# 4. 检查依赖服务
begetctl check_dependency [service_name]
🛠️ 解决方案:
{"services": [{"name": "problem_service","restart_delay": 30,"restart_times": 5,"restart_period": 600,"critical": false,"loglevel": "DEBUG"}]
}
3️⃣ 权限拒绝问题
🔍 故障现象: 服务启动报Permission denied
📊 诊断步骤:
# 1. 检查文件权限
ls -l /system/bin/[service_binary]# 2. 检查SELinux上下文
ls -Z /system/bin/[service_binary]# 3. 检查capabilities
getcap /system/bin/[service_binary]# 4. 查看audit日志
ausearch -m avc -ts recent | grep [service_name]
🛠️ 解决方案:
{"services": [{"name": "permission_service","secon": "u:r:correct_context:s0","capabilities": ["CAP_NET_ADMIN", "CAP_SYS_TIME"],"permission": ["ohos.permission.SYSTEM_STARTUP"]}]
}
📊 性能优化实践
⚡ 启动时间优化
1️⃣ 服务并行启动
优化策略:
{"jobs": [{"name": "parallel-init","cmds": ["start servicemgr &","start hiview &","start appspawn &","wait"]}]
}
2️⃣ 延迟启动策略
非关键服务延迟启动:
{"services": [{"name": "delayed_service","path": ["/system/bin/delayed_service"],"start_mode": "ondemand","trigger": "sys.boot.completed=1"}]
}
3️⃣ 启动时间分析
测量工具:
# 📊 启动时间统计
begetctl bootchart start # 开始记录
begetctl bootchart stop # 停止记录
begetctl bootchart dump # 导出报告# 📈 性能分析
time begetctl start [service_name]
🎯 内存优化
1️⃣ 服务内存限制
内存配置:
{"services": [{"name": "memory_limited_service","memory_limit": "64M","memory_swappiness": 0,"oom_score_adj": -1000}]
}
2️⃣ 资源监控
监控配置:
# 📊 内存监控脚本
#!/system/bin/sh
while true; doecho "=== $(date) ===" >> /var/log/memory.logcat /proc/meminfo >> /var/log/memory.logbegetctl dump_service | grep memory >> /var/log/memory.logsleep 60
done
🎯 实战配置案例
📋 案例1:添加自定义服务
需求: 添加一个名为my_service
的自定义服务
步骤1: 创建服务配置
// 📁 /system/etc/init/my_service.cfg
{"services": [{"name": "my_service","path": ["/system/bin/my_service", "--config", "/etc/my_service.conf"],"uid": "system","gid": ["system", "inet"],"secon": "u:r:my_service:s0","permission": ["ohos.permission.INTERNET","ohos.permission.WRITE_SETTINGS"],"critical": false,"restart_delay": 10,"restart_times": 3,"socket": [{"name": "my_service","family": "unix","type": "stream","perm": "0666","uid": "system","gid": "system"}],"env": ["MY_SERVICE_HOME=/data/my_service","MY_SERVICE_LOG=/var/log/my_service.log"]}]
}
步骤2: 添加到主配置
// 📁 /system/etc/init/init.cfg
{"import": ["/system/etc/init/my_service.cfg"],"jobs": [{"name": "post-init","cmds": ["start my_service"]}]
}
步骤3: 验证配置
# ✅ 检查配置格式
jq . /system/etc/init/my_service.cfg# 🔄 重新加载配置
begetctl reload# 📊 验证服务状态
begetctl dump_service my_service
📋 案例2:创建系统启动钩子
需求: 在系统启动完成后执行自定义脚本
配置:
// 📁 /system/etc/init/startup_hook.cfg
{"jobs": [{"name": "custom-startup","priority": 100,"cmds": ["chmod 0755 /system/etc/init.d/*","exec /system/etc/init.d/startup_hook.sh","log info \"Custom startup hook executed\""]}]
}
钩子脚本:
#!/system/bin/sh
# 📁 /system/etc/init.d/startup_hook.sh# 等待系统完全启动
while [ "$(param get sys.boot.completed)" != "1" ]; dosleep 1
done# 执行自定义操作
/system/bin/custom_init
/system/bin/setup_network
/system/bin/start_monitoringecho "Custom startup hook completed at $(date)" >> /var/log/startup.log
📋 案例3:调试配置问题
问题: 服务启动失败,需要详细调试信息
调试配置:
// 📁 /system/etc/init/debug.cfg
{"services": [{"name": "debug_service","path": ["/system/bin/debug_service"],"uid": "root","gid": ["root"],"secon": "u:r:debug_service:s0","loglevel": "DEBUG","logtags": ["service", "debug", "init"],"stdout": "/var/log/debug_service.out","stderr": "/var/log/debug_service.err","environment": {"DEBUG": "1","VERBOSE": "1"}}]
}
调试脚本:
#!/system/bin/sh
# 📁 /system/bin/debug_init.shecho "=== Debug Service Analysis ==="
echo "Service: debug_service"
echo "Binary: /system/bin/debug_service"
echo "Config: /system/etc/init/debug.cfg"
echo ""echo "1. 检查文件权限:"
ls -la /system/bin/debug_serviceecho "2. 检查SELinux上下文:"
ls -Z /system/bin/debug_serviceecho "3. 检查依赖:"
ldd /system/bin/debug_serviceecho "4. 检查配置:"
begetctl dump_service debug_serviceecho "5. 手动测试:"
/system/bin/debug_service --test-mode
📚 附录
📋 参考资源
1️⃣ 源码位置
base/startup/init/ # init主目录
├── services/ # 服务配置
├── docs/ # 官方文档
├── tests/ # 测试用例
└── tools/ # 调试工具
2️⃣ 调试工具
begetctl
- init调试命令param
- 系统参数管理- `hilog - 日志查看
hitrace
- 系统调用跟踪
3️⃣ 配置文件模板
/system/etc/init/*.cfg
- 服务配置/system/etc/param/*.para
- 参数配置/system/etc/selinux/*
- 安全策略
🎯 总结
OpenHarmony init进程的完整生命周期。
- 🔄 三阶段启动模型 - pre-init、init、post-init
- ⚙️ 配置体系 - 分层配置、优先级规则
- 🐛 调试工具 - begetctl、日志系统、故障诊断
- 📊 性能优化 - 并行启动、延迟加载、内存管理
- 🎯 实战案例 - 自定义服务、启动钩子、调试配置