当前位置: 首页 > backend >正文

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进程启动时,首先完成系统初始化工作,然后开始解析配置文件。系统在解析配置文件时,会将配置文件分成三类:

  1. init.cfg默认配置文件,由init系统定义,优先解析。
  2. /system/etc/init/*.cfg各子系统定义的配置文件。
  3. /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}]
}

注意事项:

  1. cfg文件是严格按照JSON格式编写的,当添加服务或命令未生效时,可以优先排查添加内容的格式是否正确。
  2. 对于import解析,在解析完成一个import中的cfg文件路径时,会立即解析该cfg文件。
  3. example1.cfg 需要导入的cfg文件。
  4. serviceName:service名称, 用户自定义。
  5. /system/bin/serviceName: 当前服务的可执行文件全路径和参数, 数组形式。
  6. 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

🚀 启动流程深度解析

🔍 详细启动时序

🔄 内核📋 init进程🔌 ueventd🎯 servicemgr🥚 appspawn启动/init进程解析init.cfg执行pre-init作业启动ueventd服务监听设备事件挂载required分区启动servicemgr加载服务配置启动appspawn初始化应用孵化器触发boot-complete🔄 内核📋 init进程🔌 ueventd🎯 servicemgr🥚 appspawn

📊 关键阶段分析

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组服务
  • ✅ 建立服务间通信
  • ✅ 初始化核心组件

服务启动顺序:

🔄 顺序🎯 服务📂 配置文件🔗 依赖关系
1ueventdinit.cfg无依赖
2servicemgrservicemgr.cfg依赖ueventd
3hiviewhiview.cfg依赖servicemgr
4appspawnappspawn.cfg依赖servicemgr

服务启动顺序表

阶段服务配置路径依赖检查
pre-initueventd/system/etc/init/init.cfg
initservicemgr/system/etc/init/servicemgr.cfgueventd
inithiview/system/etc/init/hiview.cfgservicemgr
post-initappspawn/system/etc/init/appspawn.cfgservicemgr
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进程的完整生命周期。

  1. 🔄 三阶段启动模型 - pre-init、init、post-init
  2. ⚙️ 配置体系 - 分层配置、优先级规则
  3. 🐛 调试工具 - begetctl、日志系统、故障诊断
  4. 📊 性能优化 - 并行启动、延迟加载、内存管理
  5. 🎯 实战案例 - 自定义服务、启动钩子、调试配置
http://www.xdnf.cn/news/18513.html

相关文章:

  • Doxygen是什么?
  • Neural Network with Softmax output|神经网络的Softmax输出
  • 深入剖析Spring Boot应用启动全流程
  • 第七章 利用Direct3D绘制几何体
  • flink常见问题之非法配置异常
  • Hive Metastore和Hiveserver2启停脚本
  • jetson ubuntu 打不开 firefox和chromium浏览器
  • Python 实战:内网渗透中的信息收集自动化脚本(2)
  • 嵌入式LINUX——————网络TCP
  • Mysql InnoDB 底层架构设计、功能、原理、源码系列合集【六、架构全景图与最佳实践】
  • ArcGIS Pro 安装路径避坑指南:从崩溃根源到规范实操(附问题修复方案)
  • 在 CentOS 7 上搭建 OpenTenBase 集群:从源码到生产环境的全流程指南
  • SpringMVC相关自动配置
  • 第四十三天(JavaEE应用ORM框架SQL预编译JDBCMyBatisHibernateMaven)
  • 算法训练营day60 图论⑩ Bellman_ford 队列优化算法、判断负权回路、单源有限最短路
  • Vue 3 useModel vs defineModel:选择正确的双向绑定方案
  • [特殊字符] 在 Windows 新电脑上配置 GitHub SSH 的完整记录(含坑点与解决方案)
  • 简单留插槽的方法
  • 生成一个竖直放置的div,宽度是350px,上面是标题固定高度50px,下面是自适应高度的div,且有滚动条
  • 航空复杂壳体零件深孔检测方法 - 激光频率梳 3D 轮廓检测
  • FFMPEG相关解密,打水印,合并,推流,
  • 鸿蒙中Snapshot分析
  • Vue3+ElementPlus倒计时示例
  • 应用服务器和数据库服务器的区别
  • 机器学习案例——预测矿物类型(数据处理部分)
  • [CISCN2019 华北赛区 Day1 Web5]CyberPunk
  • `sudo apt update` 总是失败
  • Linux问答题:调优系统性能
  • 李宏毅NLP-12-语音分类
  • 基于Labview的旋转机械AI智能诊断系统