提交 8eb62340 编写于 作者: C cheng_jinsong

update zh-cn/device-dev/subsystems/subsys-boot-init-log.md.

Signed-off-by: Ncheng_jinsong <chengjinsong2@huawei.com>
Signed-off-by: Ncheng_jinsong <chengjinsong2@huawei.com>
上级 80898702
...@@ -82,6 +82,8 @@ ...@@ -82,6 +82,8 @@
- [系统参数](subsys-boot-init-sysparam.md) - [系统参数](subsys-boot-init-sysparam.md)
- [沙盒管理](subsys-boot-init-sandbox.md) - [沙盒管理](subsys-boot-init-sandbox.md)
- [插件](subsys-boot-init-plugin.md) - [插件](subsys-boot-init-plugin.md)
- [组件化启动](subsys-boot-init-sub-unit.md)
- [init运行日志规范化](subsys-boot-init-log.md)
- [appspawn应用孵化组件](subsys-boot-appspawn.md) - [appspawn应用孵化组件](subsys-boot-appspawn.md)
- [bootstrap服务启动组件](subsys-boot-bootstrap.md) - [bootstrap服务启动组件](subsys-boot-bootstrap.md)
- [常见问题](subsys-boot-faqs.md) - [常见问题](subsys-boot-faqs.md)
......
...@@ -2,56 +2,74 @@ ...@@ -2,56 +2,74 @@
## 概述 ## 概述
### 功能简介 ### 功能简介
日志的基本功能就是记录init启动中的关键节点,以及定位故障问题。 日志的基本功能就是记录init启动中的关键节点,以及定位故障问题。
- 基于日志可以定位故障问题,可以查看各子系统启动时长,命令执行时长等。
### 基本概念 - 可以查看不同模块的日志tag,如param、uevent、module等。
基于日志可以定位故障问题,可以查看各子系统启动时长,命令执行时长等;可以查看不同模块的日志tag,如param、uevent、module等;输出关键阶段日志,如第一阶段启动日志、required partition设备节点、uevent创建日志、服务启动日志等;日志等级可控,根据需要输出不同级别日志,目前日志级别分为INIT_DEBUG, - 输出关键阶段日志,如第一阶段启动日志、required partition设备节点、uevent创建日志、服务启动日志等。
- 日志等级可控,根据需要输出不同级别日志,目前日志级别分为INIT_DEBUG,
INIT_INFO,INIT_WARN,INIT_ERROR,INIT_FATAL。 INIT_INFO,INIT_WARN,INIT_ERROR,INIT_FATAL。
- 日志输出原理 ### 基本概念
init日志采用内核的dmesg log,即int fd = open("/dev/kmsg", ...),同时将stdin、stdout、stderr重定向到/dev/null,即关闭标准输入输出。设置基础的log等级g_logLevel,当调用的log等级大于等于g_logLevel才会打印出log。 init日志根据OpenHarmony版本不同实现方式不同。
- 对于OpenHarmony标准版本,init日志采用内核的dmesg log实现。
- 对于OpenHarmony liteos L1版本init日志采用hilog接口实现。
- 对于OpenHarmony liteos L0版本init日志采用printf接口实现。
### 约束与限制 ### 约束与限制
对于标准版本log采用dmesg log,对于非标准版本的liteos L1版本log采用hilog接口,对于L0版本采用printf接口。
## 开发指导 ## 开发指导
### 场景介绍 ### 场景介绍
init log主要应用在init的启动过程中,启动相关模块(param、ueventd、module等)中,以及对外提供的begetutils接口中。 init log主要应用在init的启动过程中,启动相关模块(param、ueventd、module等)中,以及对外提供的begetutils接口中。
### 参数说明 ### 接口说明
**表1** log接口说明 **表1** log接口说明
| 接口 | 接口格式和示例 | 说明 | | 接口 | 接口格式和示例 | 说明 |
| -------- | -------- | -------- | | -------- | -------- | -------- |
| INIT_LOGV | INIT_LOGV("Add %s to job %s", service->name, jobName); | 输出debug log | | INIT_LOGV | INIT_LOGV("Add %s to job %s", service->name, jobName); | 输出debug log。 |
| INIT_LOGI | INIT_LOGI("Start init first stage."); | 输出info log | | INIT_LOGI | INIT_LOGI("Start init first stage."); | 输出info log。 |
| INIT_LOGW | INIT_LOGW("initialize signal handler failed"); | 输出warning log | | INIT_LOGW | INIT_LOGW("initialize signal handler failed"); | 输出warning log。 |
| INIT_LOGE | INIT_LOGE("Failed to format other opt"); | 输出err log | | INIT_LOGE | INIT_LOGE("Failed to format other opt"); | 输出err log。 |
| INIT_LOGF | INIT_LOGF("Failed to init system"); | 输出fatal log | | INIT_LOGF | INIT_LOGF("Failed to init system"); | 输出fatal log。 |
| INIT_ERROR_CHECK | INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to get cmd args "); | 判断 ctx != NULL 不成立的情况下输出log,同时执行 return NULL | | INIT_ERROR_CHECK | INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to get cmd args "); | 判断 ctx != NULL 不成立的情况下输出log,同时执行 return NULL。 |
| INIT_INFO_CHECK | INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for service %s", service->name); | 判断 sockopt != NULL 不成立的情况下输出log,同时执行 return SERVICE_FAILURE | | INIT_INFO_CHECK | INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for service %s", service->name); | 判断 sockopt != NULL 不成立的情况下输出log,同时执行 return SERVICE_FAILURE。 |
| INIT_WARNING_CHECK | INIT_WARNING_CHECK(argsCount <= SPACES_CNT_IN_CMD_MAX, argsCount = SPACES_CNT_IN_CMD_MAX, "Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX); | 判断 argsCount <= SPACES_CNT_IN_CMD_MAX 不成立的情况下输出log,同时执行 argsCount = SPACES_CNT_IN_CMD_MAX | | INIT_WARNING_CHECK | INIT_WARNING_CHECK(argsCount <= SPACES_CNT_IN_CMD_MAX, argsCount = SPACES_CNT_IN_CMD_MAX, "Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX); | 判断 argsCount <= SPACES_CNT_IN_CMD_MAX 不成立的情况下输出log,同时执行 argsCount = SPACES_CNT_IN_CMD_MAX。 |
| INIT_CHECK | INIT_CHECK(arg != NULL, return NULL); | 判断arg != NULL 不成立的情况下执行 return NULL | | INIT_CHECK | INIT_CHECK(arg != NULL, return NULL); | 判断arg != NULL 不成立的情况下执行 return NULL。 |
| INIT_CHECK_RETURN_VALUE | INIT_CHECK_RETURN_VALUE(errno == 0, -1); | 判断errno == 0 不成立的情况下执行 return -1 | | INIT_CHECK_RETURN_VALUE | INIT_CHECK_RETURN_VALUE(errno == 0, -1); | 判断errno == 0 不成立的情况下执行 return -1。 |
| INIT_CHECK_ONLY_RETURN | INIT_CHECK_ONLY_RETURN(cmd != NULL); | 判断cmd != NULL 不成立的情况下执行 return | | INIT_CHECK_ONLY_RETURN | INIT_CHECK_ONLY_RETURN(cmd != NULL); | 判断cmd != NULL 不成立的情况下执行 return。 |
| INIT_CHECK_ONLY_ELOG | INIT_CHECK_ONLY_ELOG(execv(argv[0], argv) == 0, "execv %s failed! err %d.", argv[0], errno); | 判断execv(argv[0], argv) == 0 不成立的情况下只打印log "execv %s failed! err %d." | | INIT_CHECK_ONLY_ELOG | INIT_CHECK_ONLY_ELOG(execv(argv[0], argv) == 0, "execv %s failed! err %d.", argv[0], errno); | 判断execv(argv[0], argv) == 0 不成立的情况下只打印log "execv %s failed! err %d."。 |
**表2** 关键日志说明 ### 开发实例
| 日志内容 | 说明 |
| -------- | -------- | 1、调用接口打印日志
| INIT_LOGI("Start init first stage."); | 当前处理init第一阶段启动,第一阶段包括创建基础的设备节点,以及mount基础的required分区(system、chipset等)|
| INIT_LOGI("Start init second stage."); | 开始第二阶段启动,包括解析配置文件、拉起服务等等 | 例如在 //base/startup/init/services/init/standard/init.c中调用接口INIT_LOGI("Start init first stage.")打印日志。
| INIT_LOGI("Handle required partitionName %s", uevent->partitionName); | 创建关键的required 设备节点 | ```c
| BEGET_LOGI("Mount %s to %s successful", item->deviceName, item->mountPoint); | fstab文件系统分区挂载成功 | void SystemPrepare(void)
| INIT_LOGI("Service %s(pid %d) started", service->name, pid); | 提示init拉起服务成功 | {
| INIT_LOGE("Child process %s(pid %d) exit with code : %d", MountBasicFs();
service == NULL ? "Unknown" : service->name, sigPID, sigPID, WTERMSIG(procStat)); | 提示服务异常退出 | CreateDeviceNode();
| INIT_LOGE("Child process %s(pid %d) exit with code : %d", LogInit();
service == NULL ? "Unknown" : service->name, sigPID, WEXITSTATUS(procStat)); | 提示服务正常退出 | // Make sure init log always output to /dev/kmsg.
EnableDevKmsg();
**表3** log等级设置命令 INIT_LOGI("Start init first stage.");
| 命令 | 提示 | 说明 | // Only ohos normal system support
| -------- | -------- | -------- | // two stages of init.
| setloglevel | Command list:setloglevel level --set init log level 0:debug, 1:info, 2:warning, 3:err, 4:fatal | 设置init log等级在0~4之间 | // If we are in updater mode, only one stage of init.
| setloglevel 3 | Success to set log level by param "persist.init.debug.loglevel" 3. | 说明成功设置log等级为3:err | if (InUpdaterMode() == 0) {
| getloglevel | Success to get init log level: 3 from param "persist.init.debug.loglevel" | 获取当前log level为3:err | StartInitSecondStage();
}
}
```
通过dmesg可以查看打印的log,"Start init first stage."。
2、通过命令设置日志等级
通过命令begetctl setloglevel level,其中level对应log的等级0~4,即INIT_DEBUG,
INIT_INFO,INIT_WARN,INIT_ERROR,INIT_FATAL。
设置完成之后init的g_logLevel等级立即生效,上述log接口中log等级大于等于g_logLevel才会打印日志。例如:begetctl setloglevel 3,即设置log等级为INIT_ERROR,则上述的log接口中只有INIT_LOGE、INIT_LOGF才会打印log。
系统重启之后在init.cfg中"load_persist_params "命令之后生效设置的log等级。
...@@ -54,19 +54,11 @@ bootchart 只支持标准系统, begetctl 支持小型系统和标准系统。 ...@@ -54,19 +54,11 @@ bootchart 只支持标准系统, begetctl 支持小型系统和标准系统。
| modulectl uninstall moduleName | 卸载动态插件,例如:<br>modulectl uninstall bootchart | 无 | | modulectl uninstall moduleName | 卸载动态插件,例如:<br>modulectl uninstall bootchart | 无 |
| modulectl install moduleName | 安装动态插件,例如:<br>modulectl install bootchart | 无 | | modulectl install moduleName | 安装动态插件,例如:<br>modulectl install bootchart | 无 |
| modulectl list | 动态插件列表,例如:<br>begetctl modulectl list | 无 | | modulectl list | 动态插件列表,例如:<br>begetctl modulectl list | 无 |
| setloglevel level | 设置log等级为info,例如:<br>begetctl setloglevel 1 | log等级设置范围0~4 |
| getloglevel | 获取当前init的log等级,例如:<br>begetctl getloglevel | 无 |
## 开发指导 ## 开发指导
### 接口说明
**表1** 接口介绍<a name="table14737791479"></a>
| 函数 | 函数解释 |
| ---------- | ---------- |
| void PluginExecCmdByName(const char *name, const char *cmdContent) | 通过名称启动插件。 |
| void PluginExecCmdByCmdIndex(int index, const char *cmdContent) | 通过标志启动插件。 |
| int PluginExecCmd(const char *name, int argc, const char **argv) | 命令启动插件。 |
| int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) | 添加安装插件命令。 |
### 开发步骤 ### 开发步骤
新增一个插件, 以bootchart为例: 新增一个插件, 以bootchart为例:
1. 安装so文件, 定义单独文件,实现下面函数。 1. 安装so文件, 定义单独文件,实现下面函数。
......
# 组件化启动 # 组件化启动
## 概述 ## 概述
### 功能简介 ### 功能简介
构建四个基础组件镜像,提供相应的组件化目录,包括系统组件:system、产品通用配置组件:sys_prod、芯片组件:chipset、产品硬件配置组件:chip_prod; 构建四个基础组件镜像,提供相应的组件化目录,包括:
- 系统组件:system
- 产品通用配置组件:sys_prod
- 芯片组件:chipset
- 产品硬件配置组件:chip_prod;
确保系统参数以及启动脚本都可以按照组件的优先级进行扫描初始化; 确保系统参数以及启动脚本都可以按照组件的优先级进行扫描初始化;
完成系统组件和芯片组件的独立编译构建。 完成系统组件和芯片组件的独立编译构建。
### 基本概念 ### 基本概念
system:系统组件文件系统挂载点,与芯片及硬件无关的平台业务;sys_prod:对系统组件的能力扩展以及能力定制,承载产品级差异能力,存放产品相关的配置文件; - 基础组件
chipset:芯片组件文件系统挂载点,为系统组件提供统一的硬件抽象服务,相同的芯片平台可统一一份芯片组件;
chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存放芯片相关的配置文件。 system:系统组件文件系统挂载点,与芯片及硬件无关的平台业务;
sys_prod:对系统组件的能力扩展以及能力定制,承载产品级差异能力,存放产品相关的配置文件;
chipset:芯片组件文件系统挂载点,为系统组件提供统一的硬件抽象服务,相同的芯片平台可统一一份芯片组件;
chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存放芯片相关的配置文件。
- 组件化编译构建 - 组件化编译构建
...@@ -28,7 +36,7 @@ chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存 ...@@ -28,7 +36,7 @@ chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存
### rk3568产品的组件化构建编译 ### rk3568产品的组件化构建编译
//vendor/hihope/rk3568/config.json 配置文件实现构建此产品需要的组件,如下所示: //vendor/hihope/rk3568/config.json 配置文件实现构建此产品需要的组件,如下所示:
{ {
"product_name": "rk3568", "product_name": "rk3568",
"device_company": "rockchip", "device_company": "rockchip",
... ...
...@@ -36,16 +44,17 @@ chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存 ...@@ -36,16 +44,17 @@ chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存
... ...
"inherit": [ "productdefine/common/inherit/rich.json", "productdefine/common/inherit/chipset_common.json" ], "inherit": [ "productdefine/common/inherit/rich.json", "productdefine/common/inherit/chipset_common.json" ],
"subsystems": [ "subsystems": [
{
"subsystem": "security",
"components": [
{ {
"component": "selinux", "subsystem": "security",
"features": [] "components": [
}] {
} "component": "selinux",
"features": []
}
]
}
... ...
} }
从中可以看出产品名称、芯片厂家、支持的指令集等;inherit指出依赖的通用组件;subsystems指出通用组件以外的部件。 从中可以看出产品名称、芯片厂家、支持的指令集等;inherit指出依赖的通用组件;subsystems指出通用组件以外的部件。
//productdefine/common/inherit/rich.json 如下所示配置系统组件完整的部件;系统组件还可以包括base.json(所有产品都要包含的最小部件集合列表)、headless.json(没有ui界面的产品支持应用安装管理的最小部件集合)。 //productdefine/common/inherit/rich.json 如下所示配置系统组件完整的部件;系统组件还可以包括base.json(所有产品都要包含的最小部件集合列表)、headless.json(没有ui界面的产品支持应用安装管理的最小部件集合)。
...@@ -56,27 +65,27 @@ chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存 ...@@ -56,27 +65,27 @@ chip_prod:单板外设特有硬件能力以及产品级硬件差异配置, 存
{ {
"subsystem": "arkui", "subsystem": "arkui",
"components": [ "components": [
{ {
"component": "ace_engine", "component": "ace_engine",
"features": [] "features": []
}, },
{ {
"component": "napi", "component": "napi",
"features": [] "features": []
} }
] ]
}, },
{ {
"subsystem": "account", "subsystem": "account",
"components": [ "components": [
{ {
"component": "os_account", "component": "os_account",
"features": [] "features": []
} }
] ]
}, },
... ...
} }
### 系统参数根据优先级扫描初始化 ### 系统参数根据优先级扫描初始化
对于服务的cfg配置文件优先级是/system/etc < /system/etc/init < /chipset/etc,即优先级高的配置文件将取代、更新低优先级配置。例如/system/etc/init/camera_service.cfg, 对于服务的cfg配置文件优先级是/system/etc < /system/etc/init < /chipset/etc,即优先级高的配置文件将取代、更新低优先级配置。例如/system/etc/init/camera_service.cfg,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册