diff --git a/zh-cn/device-dev/device-dev-guide.md b/zh-cn/device-dev/device-dev-guide.md index 475c3c942226a4dc177175d11f0269ddb9bb81b3..0a6e2d4fc732926ef7242c35ac6d0a937368818e 100644 --- a/zh-cn/device-dev/device-dev-guide.md +++ b/zh-cn/device-dev/device-dev-guide.md @@ -30,9 +30,6 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按 ## 文档导读 -- [轻量和小型系统开发指导](#table3762949121211) -- [标准系统开发指导](#table17667535516) - **表 1** 轻量和小型系统开发指导(参考内存<128MB) | 学习路径 | 开发者业务 | 相关文档 | @@ -42,7 +39,7 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按 | 快速入门 | 快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行。 | [轻量和小型系统快速入门](quick-start/quickstart-lite.md) | | 基础能力使用 | 使用OpenHarmony提供的基础能力 | - [轻量系统内核开发指南](kernel/kernel-mini-overview.md)
- [小型系统内核开发指南](kernel/kernel-small-overview.md)
- [驱动开发指南](driver/driver-hdf-overview.md)
- [子系统开发指南](subsystems/subsys-build-mini-lite.md)
- [安全指南](security/security-guidelines-overall.md)
- [隐私保护](security/security-privacy-protection.md) | | 进阶开发 | 结合系统能力开发智能设备 | - [WLAN连接类产品](guide/device-wlan-led-control.md)
- [无屏摄像头类产品](guide/device-iotcamera-control-overview.md)
- [带屏摄像头类产品](guide/device-camera-control-overview.md) | -| 移植适配 | - 针对特定芯片做移植适配
- 对三方库进行移植适配 | - [轻量系统芯片移植指导](porting/oem_transplant_chip_prepare_knows.md)
- [小型系统芯片移植指导](porting/porting-smallchip-prepare-needs.md)
- [轻量和小型系统三方库移植指导](porting/porting-thirdparty-overview.md) | +| 移植适配 | - 针对特定芯片做移植适配
- 对三方库进行移植适配 | - [轻量系统芯片移植指导](porting/porting-minichip.md)
- [小型系统芯片移植指导](porting/porting-smallchip-prepare-needs.md)
- [轻量和小型系统三方库移植指导](porting/porting-thirdparty-overview.md) | | 贡献组件 | 为OpenHarmony贡献功能组件 | - [HPM Part 介绍](hpm-part/hpm-part-about.md)
- [HPM Part 开发指导](hpm-part/hpm-part-development.md)
- [HPM Part 参考](hpm-part/hpm-part-reference.md) | | 参考 | 开发参考 | - [API参考](https://gitee.com/link?target=https%3A%2F%2Fdevice.harmonyos.com%2Fcn%2Fdocs%2Fdevelop%2Fapiref%2Fjs-framework-file-0000000000611396)
- [常见问题](faqs/faqs-overview.md) | diff --git a/zh-cn/device-dev/driver/driver-platform-dac-develop.md b/zh-cn/device-dev/driver/driver-platform-dac-develop.md index 14da38d13c404e0885ddb969e3e565bac5f91b79..f60d2b54acfce85dbf21ce0bf9bc75abf99c72cd 100644 --- a/zh-cn/device-dev/driver/driver-platform-dac-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-dac-develop.md @@ -1,22 +1,12 @@ # DAC -- [概述](#1) - - [功能简介](#2) - - [基本概念](#3) - - [运作机制](#4) - - [约束与限制](#5) -- [开发指导](#6) - - [场景介绍](#7) - - [接口说明](#8) - - [开发步骤](#9) +## 概述 -## 概述 - -### 功能简介 +### 功能简介 DAC(Digital to Analog Converter)是一种通过电流、电压或电荷的形式将数字信号转换为模拟信号的设备 。 -### 基本概念 +### 基本概念 DAC模块支持数模转换的开发。它主要用于: @@ -39,33 +29,32 @@ DAC模块支持数模转换的开发。它主要用于: 最低有效位LSB(Least Significant Byte),指的是一个二进制数字中的第0位(即最低位)。 -### 运作机制 +### 运作机制 -在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。DAC模块接口适配模式采用统一服务模式([如图1](#fig14423182615525)所示)。 +在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。DAC模块接口适配模式采用统一服务模式(如图1所示)。 DAC模块各分层的作用为:接口层提供打开设备,写入数据,关闭设备接口的能力。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其他具体的功能。 ![](../public_sys-resources/icon-note.gif) 说明:核心层可以调用接口层的函数,也可以通过钩子函数调用适配层函数,从而使得适配层间接的可以调用接口层函数,但是不可逆转接口层调用适配层函数。 -**图 1** 统一服务模式 +**图 1** 统一服务模式 ![](figures/统一服务模式结构图.png "DAC统一服务模式") +### 约束与限制 -### 约束与限制 - - DAC模块当前仅支持轻量和小型系统内核(LiteOS) 。 + DAC模块当前仅支持轻量和小型系统内核(LiteOS)。 -## 开发指导 +## 开发指导 -### 场景介绍 +### 场景介绍 DAC模块主要在设备中数模转换,音频输出,电机控制等设备使用,设置将DAC模块传入的数字信号转换为输出模拟信号时需要用到DAC数模转换驱动。 -### 接口说明 +### 接口说明 通过以下DacMethod中的函数调用DAC驱动对应的函数。 @@ -84,7 +73,7 @@ struct DacMethod { **表 1** DacMethod结构体成员的回调函数功能说明 - + | 函数成员 | 入参 | 出参 | 返回值 | 功能 | | -------- | ------------------------------------------------------------ | ---- | ------------------ | -------------- | @@ -94,7 +83,7 @@ struct DacMethod { -### 开发步骤 +### 开发步骤 DAC模块适配包含以下四个步骤: @@ -132,7 +121,7 @@ DAC模块适配包含以下四个步骤: | policy | 具体配置为0,不发布服务| | priority | 驱动启动优先级(0-200),值越大优先级越低,,优先级相同则不保证device的加载顺序。| | permission | 驱动权限| - | moduleName | 固定为 HDF_PLATFORM_DAC_MANAGER| + | moduleName | 固定为HDF_PLATFORM_DAC_MANAGER| | serviceName | 固定为HDF_PLATFORM_DAC_MANAGER| | deviceMatchAttr | 没有使用,可忽略| @@ -293,7 +282,7 @@ DAC模块适配包含以下四个步骤: ``` ![](../public_sys-resources/icon-note.gif) **说明:** - DacDevice成员DacMethod的定义和成员说明见[接口说明](#section752964871810)。 + DacDevice成员DacMethod的定义和成员说明见[接口说明](#接口说明)。 - Init函数参考 @@ -304,7 +293,7 @@ DAC模块适配包含以下四个步骤: 返回值: - HDF_STATUS相关状态 (下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 + HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义)。 | 状态(值) | 问题描述 | | ---------------------- | -------------- | diff --git a/zh-cn/device-dev/driver/driver-platform-pin-develop.md b/zh-cn/device-dev/driver/driver-platform-pin-develop.md index 890e385759a8fc987a2ec306b07f8375ecf373c5..c9c687a7d046d36fb4e859ef02e1b03130445fb3 100755 --- a/zh-cn/device-dev/driver/driver-platform-pin-develop.md +++ b/zh-cn/device-dev/driver/driver-platform-pin-develop.md @@ -20,11 +20,12 @@ PIN是一个软件层面的概念,目的是为了统一各SoC厂商PIN管脚 ### 运作机制 -在HDF框架中,PIN模块暂不支持用户态,所以不需要发布服务,接口适配模式采用无服务模式(如[图1](#无服务模式结构图)所示),用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 +在HDF框架中,PIN模块暂不支持用户态,所以不需要发布服务,接口适配模式采用无服务模式(如图1所示),用于不需要在用户态提供API的设备类型,或者没有用户态和内核区分的OS系统,其关联方式是DevHandle直接指向设备对象内核态地址(DevHandle是一个void类型指针)。 PIN模块各分层作用:接口层提供获取PIN管脚、设置PIN管脚推拉方式、获取PIN管脚推拉方式、设置PIN管脚推拉强度、获取PIN管脚推拉强度、设置PIN管脚功能、获取PIN管脚功能、释放PIN管脚的接口。核心层主要提供PIN管脚资源匹配,PIN管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。适配层主要是将钩子函数的功能实例化,实现具体的功能。 **图 1** 无服务模式结构图 + ![无服务模式结构图](figures/无服务模式结构图.png) ### 约束与限制 diff --git a/zh-cn/device-dev/guide/device-outerdriver-demo.md b/zh-cn/device-dev/guide/device-outerdriver-demo.md index b5ba5dbd3b9861daaee42b2894f8d747fe9c71fd..1493098ee35bdb179416fbf13efe1595b71e87ce 100644 --- a/zh-cn/device-dev/guide/device-outerdriver-demo.md +++ b/zh-cn/device-dev/guide/device-outerdriver-demo.md @@ -1,24 +1,5 @@ # 外设驱动开发示例 -- [概述](#section86753818426) - - [硬件资源简介](#section123071189431) - - [Input模型简介](#section53684425430) - -- [环境搭建](#section661075474418) -- [TouchScreen器件驱动开发](#section15233162984520) - - [配置设备描述信息](#section16761205604515) - - [配置Touchscreen器件信息](#section156331030144617) - - [适配器件私有驱动](#section17127331595) - -- [编译及烧录](#section16465031164711) -- [调试验证](#section62577313482) -- [Input模型工作流程解析](#section1578569154917) - - [私有配置信息解析](#section1310113815495) - - [管理驱动层初始化及注册驱动至HDF框架](#section614512119500) - - [公共驱动层初始化及注册驱动至HDF框架](#section16194201755019) - - [器件驱动层初始化及注册驱动至HDF框架](#section1090743312505) - - [具体调用逻辑串联函数](#section81801147529) - ## 概述 @@ -40,7 +21,7 @@ Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动 此外,Input模型预先实现了数据通道以及设备配置信息解析等函数。 -关于Input模型的详细介绍请参考《[Touchscreen开发概述](../driver/driver-peripherals-touch-des.md#section175431838101617)》。 +关于Input模型的详细介绍请参考《[Touchscreen开发概述](../driver/driver-peripherals-touch-des.md#概述)》。 ## 环境搭建 diff --git a/zh-cn/device-dev/kernel/Readme-CN.md b/zh-cn/device-dev/kernel/Readme-CN.md index 460efc5e8e693dffd23f0dd8aca05eb4c165b4b6..f0fefe53ba8461b64a0e960b0fcc98b9c2326038 100755 --- a/zh-cn/device-dev/kernel/Readme-CN.md +++ b/zh-cn/device-dev/kernel/Readme-CN.md @@ -34,8 +34,7 @@ - [LMS调测](kernel-mini-memory-lms.md) - 附录 - [内核编码规范](kernel-mini-appx-code.md) - - 基本数据结构 - - [双向链表](kernel-mini-appx-data-list.md) + - [基本数据结构](kernel-mini-appx-data-list.md) - 标准库支持 - [CMSIS支持](kernel-mini-appx-lib-cmsis.md) - [POSIX支持](kernel-mini-appx-lib-posix.md) @@ -148,11 +147,10 @@ - [tftp](kernel-small-debug-shell-net-tftp.md) - [魔法键使用方法](kernel-small-debug-shell-magickey.md) - [用户态异常信息说明](kernel-small-debug-shell-error.md) - - [Trace](kernel-small-debug-trace.md) + - [Trace调测](kernel-small-debug-trace.md) - [Perf调测](kernel-mini-memory-perf.md) - [LMS调测](kernel-small-memory-lms.md) - - 进程调测 - - [CPU占用率](kernel-small-debug-process-cpu.md) + - [进程调测](kernel-small-debug-process-cpu.md) - 内核态内存调测 - [内存信息统计](kernel-small-debug-memory-info.md) - [内存泄漏检测](kernel-small-debug-memory-leak.md) @@ -165,10 +163,10 @@ - 使用说明 - [接口调用方式](kernel-small-debug-user-guide-use-api.md) - [命令行参数方式](kernel-small-debug-user-guide-use-cli.md) - - [常见问题场景](kernel-small-debug-user-faqs.md) + - [常见问题](kernel-small-debug-user-faqs.md) - 其他内核调测手段 - [临终遗言](kernel-small-debug-trace-other-lastwords.md) - - [常见问题定位方法](kernel-small-debug-trace-other-faqs.md) + - [常见问题](kernel-small-debug-trace-other-faqs.md) - 附录 - 基本数据结构 - [双向链表](kernel-small-apx-dll.md) @@ -176,11 +174,10 @@ - [标准库](kernel-small-apx-library.md) - 标准系统内核 - [Linux内核概述](kernel-standard-overview.md) - - [开发板Patch使用指导](kernel-standard-patch.md) + - [OpenHarmony开发板Patch使用指导](kernel-standard-patch.md) - [Linux内核编译与构建指导](kernel-standard-build.md) - [内核增强特性](kernel-standard-enhanced-features.md) - - [内存管理](kernel-standard-mm.md) - - [Enhanced SWAP特性介绍](kernel-standard-mm-eswap.md) - - [任务调度](kernel-standard-sched.md) - - [关联线程组调度](kernel-standard-sched-rtg.md) - - [CPU轻量级隔离](kernel-standard-sched-cpuisolation.md) + - [Enhanced SWAP特性介绍](kernel-standard-mm-eswap.md) + - [任务调度](kernel-standard-sched.md) + - [关联线程组调度](kernel-standard-sched-rtg.md) + - [CPU轻量级隔离](kernel-standard-sched-cpuisolation.md) diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001222655518.png b/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001222655518.png new file mode 100644 index 0000000000000000000000000000000000000000..040de81850928e0b6cb29ead376b119c41d95d66 Binary files /dev/null and b/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001222655518.png differ diff --git a/zh-cn/device-dev/kernel/kernel-basic-mini-time.md b/zh-cn/device-dev/kernel/kernel-basic-mini-time.md index e87cb53562269c207a2d2e950824a5e39117bbba..dbc2309930171c1fbfb5dac3096931857e6ea520 100644 --- a/zh-cn/device-dev/kernel/kernel-basic-mini-time.md +++ b/zh-cn/device-dev/kernel/kernel-basic-mini-time.md @@ -1,5 +1,6 @@ # 时间管理 + ## 基本概念 时间管理以系统时钟为基础,给应用程序提供所有和时间有关的服务。 @@ -24,20 +25,22 @@ OpenHarmony LiteOS-M内核时间管理模块提供时间转换、统计功能。 OpenHarmony LiteOS-M内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 时间管理接口 +​ **表1** 时间转换 + +| 接口名 | 描述 | +| -------- | -------- | +| LOS_MS2Tick | 毫秒转换成Tick | +| LOS_Tick2MS | Tick转化为毫秒 | +| OsCpuTick2MS | Cycle数目转化为毫秒,使用2个UINT32类型的数值分别表示结果数值的高、低32位。 | +| OsCpuTick2US | Cycle数目转化为微秒,使用2个UINT32类型的数值分别表示结果数值的高、低32位。 | -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 时间转换 | LOS_MS2Tick | 毫秒转换成Tick | -| | LOS_Tick2MS | Tick转化为毫秒 | -| | OsCpuTick2MS | Cycle数目转化为毫秒,使用2个UINT32类型的数值分别表示结果数值的高、低32位。 | -| | OsCpuTick2US | Cycle数目转化为微秒,使用2个UINT32类型的数值分别表示结果数值的高、低32位。 | -| 时间统计 | LOS_SysClockGet | 获取系统时钟 | -| | LOS_TickCountGet | 获取自系统启动以来的Tick数 | -| | LOS_CyclePerTickGet | 获取每个Tick多少Cycle数 | -| | LOS_CurrNanosec |获取自系统启动以来的纳秒数| -| 延时管理 | LOS_UDelay |以us为单位的忙等,但可以被优先级更高的任务抢占| -| | LOS_MDelay |以ms为单位的忙等,但可以被优先级更高的任务抢占| + **表2** 时间统计 + +| 接口名 | 描述 | +| -------- | -------- | +| LOS_SysClockGet | 获取系统时钟 | +| LOS_TickCountGet | 获取自系统启动以来的Tick数 | +| LOS_CyclePerTickGet | 获取每个Tick多少Cycle数 | ## 开发流程 @@ -78,6 +81,7 @@ OpenHarmony LiteOS-M内核的时间管理提供下面几种功能,接口详细 时间转换: + ``` VOID Example_TransformTime(VOID) { @@ -93,6 +97,7 @@ VOID Example_TransformTime(VOID) 时间统计和时间延迟: + ``` VOID Example_GetTime(VOID) { @@ -124,6 +129,7 @@ VOID Example_GetTime(VOID) 时间转换: + ``` tick = 1000 ms = 1000 @@ -131,6 +137,7 @@ ms = 1000 时间统计和时间延迟: + ``` LOS_CyclePerTickGet = 495000 LOS_TickCountGet = 1 diff --git a/zh-cn/device-dev/kernel/kernel-mini-app.md b/zh-cn/device-dev/kernel/kernel-mini-app.md index 3c005673f45203db64e270b4f74da7ffe4bd142a..c2f90748c83ab5e0bdee1ee4526d46d5cd4d5813 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-app.md +++ b/zh-cn/device-dev/kernel/kernel-mini-app.md @@ -1,8 +1,9 @@ # 附录 + - **[内核编码规范](kernel-mini-appx-code.md)** -- **[基本数据结构](kernel-mini-appx-data.md)** +- **[基本数据结构](kernel-mini-appx-data-list.md)** - **[标准库支持](kernel-mini-appx-lib.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-mini-appx-code.md b/zh-cn/device-dev/kernel/kernel-mini-appx-code.md index 13245e58b37571e1d83e3accf841ac611231861f..3c92cc74ce65af388c8dd4295ff6850518028238 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-code.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-code.md @@ -1,16 +1,5 @@ # 内核编码规范 -- [总体原则](#总体原则) -- [目录结构](#目录结构) -- [命名](#命名) -- [注释](#注释) -- [格式](#格式) -- [宏](#宏) -- [头文件](#头文件) -- [数据类型](#数据类型) -- [变量](#变量) -- [断言](#断言) -- [函数](#函数) 此规范基于业界通用的编程规范整理而成,请内核的开发人员遵守这样的编程风格。 @@ -41,7 +30,7 @@ 推荐使用驼峰风格,具体规则如下: -| 类型 | 命名风格 | 形式 | + | 类型 | 命名风格 | 形式 | | -------- | -------- | -------- | | 函数、结构体类型、枚举类型、联合体类型、typedef的类型 | 大驼峰,或带有模块前缀的大驼峰 | AaaBbb
XXX_AaaBbb | | 局部变量,函数参数,宏参数,结构体中字段,联合体中成员 | 小驼峰 | aaaBBB | @@ -52,6 +41,7 @@ 内核对外API建议采用LOS_ModuleFunc的形式,如果有宾语则建议采用前置的方式,比如: + ``` LOS_TaskCreate LOS_MuxLock @@ -59,6 +49,7 @@ LOS_MuxLock kernel目录下内部模块间的接口使用OsModuleFunc的形式,比如: + ``` OsTaskScan OsMuxInit @@ -77,6 +68,7 @@ OsMuxInit 注释风格要统一,建议优先选择/\* \*/的方式,注释符与注释内容之间要有1空格,单行、多行注释风格如下: + ``` /* 单行注释 */ // 单行注释 @@ -96,6 +88,7 @@ OsMuxInit 建议将多条连续的右侧注释对齐,比如: + ``` #define CONST_A 100 /* Const A */ #define CONST_B 2000 /* Const B */ @@ -112,6 +105,7 @@ OsMuxInit 比如: + ``` struct MyType { // 跟随语句放行末,前置1空格 ... @@ -129,6 +123,7 @@ int Foo(int a) { // 函数左大括号独占一行,放行首 每行字符数不要超过 120 个,代码过长时应当换行,换行时将操作符留在行末,新行缩进一层或进行同类对齐,并将表示未结束的操作符或连接符号留在行末。 + ``` // 假设下面第一行已经不满足行宽要求 if (currentValue > MIN && // Good:换行后,布尔操作符放在行末 @@ -156,6 +151,7 @@ int result = DealWithStructLikeParams(left.x, left.y, // 表示一组相关 包括 if/for/while/do-while 语句应使用大括号,即复合语句。 + ``` while (condition) {} // Good:即使循环体是空,也应使用大括号 while (condition) { @@ -165,6 +161,7 @@ while (condition) { case/default 语句相对 switch 缩进一层,风格如下: + ``` switch (var) { case 0: // Good: 缩进 @@ -181,6 +178,7 @@ switch (var) { 指针类型"\*"跟随变量或者函数名,例如: + ``` int *p1; // OK int* p2; // Bad:跟随类型 @@ -200,6 +198,7 @@ sz = sizeof(int*); // OK:右侧没有变量,"*"跟随类型 定义宏时,要使用完备的括号,例如: + ``` #define SUM(a, b) ((a) + (b)) // 符合本规范要求. #define SOME_CONST 100 // Good: 单独的数字无需括号 @@ -217,6 +216,7 @@ sz = sizeof(int*); // OK:右侧没有变量,"*"跟随类型 - 宏参数作为独立部分,在逗号表达式,函数或宏调用列表中,可以不加括号。 + ``` // x 不要加括号 #define MAKE_STR(x) #x diff --git a/zh-cn/device-dev/kernel/kernel-mini-appx-data-list.md b/zh-cn/device-dev/kernel/kernel-mini-appx-data-list.md index a3abed242619a3bc9986b76a63fcf102b00cf268..41afa363c592b3eded5fe30603a16fd860a9cc22 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-data-list.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-data-list.md @@ -1,12 +1,5 @@ -# 双向链表 +# 基本数据结构 -- [基本概念](#基本概念) -- [功能说明](#功能说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -19,22 +12,16 @@ 双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 - -| **功能分类** | **接口名** | **描述** | -| -------- | -------- | -------- | -| 初始化链表 | LOS_ListInit | 将指定双向链表节点初始化为双向链表 | -| | LOS_DL_LIST_HEAD | 定义一个双向链表节点并以该节点初始化为双向链表 | -| 增加节点 | LOS_ListAdd | 将指定节点插入到双向链表头端 | -| | LOS_ListTailInsert | 将指定节点插入到双向链表尾端 | -| 删除节点 | LOS_ListDelete | 将指定节点从链表中删除 | -| | LOS_ListDelInit | 将指定节点从链表中删除,并使用该节点初始化链表 | -| 判断双向链表是否为空 | LOS_ListEmpty | 判断链表是否为空 | -| 获取结构体信息 | LOS_DL_LIST_ENTRY | 获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称 | -| | LOS_OFF_SET_OF | 获取指定结构体内的成员相对于结构体起始地址的偏移量 | -| 遍历双向链表 | LOS_DL_LIST_FOR_EACH | 遍历双向链表 | -| | LOS_DL_LIST_FOR_EACH_SAFE | 遍历双向链表,并存储当前节点的后继节点用于安全校验 | -| 遍历包含双向链表的结构体 | LOS_DL_LIST_FOR_EACH_ENTRY | 遍历指定双向链表,获取包含该链表节点的结构体地址 | -| | LOS_DL_LIST_FOR_EACH_ENTRY_SAFE | 遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址 | + | | | +| -------- | -------- | +| **功能分类** | **接口描述** | +| 初始化链表 | - LOS_ListInit:将指定双向链表节点初始化为双向链表
- LOS_DL_LIST_HEAD:定义一个双向链表节点并以该节点初始化为双向链表 | +| 增加节点 | - LOS_ListAdd:将指定节点插入到双向链表头端
- LOS_ListTailInsert:将指定节点插入到双向链表尾端 | +| 删除节点 | - LOS_ListDelete:将指定节点从链表中删除
- LOS_ListDelInit:将指定节点从链表中删除,并使用该节点初始化链表 | +| 判断双向链表是否为空 | LOS_ListEmpty:判断链表是否为空 | +| 获取结构体信息 | - LOS_DL_LIST_ENTRY:获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称
- LOS_OFF_SET_OF:获取指定结构体内的成员相对于结构体起始地址的偏移量 | +| 遍历双向链表 | - LOS_DL_LIST_FOR_EACH:遍历双向链表
- LOS_DL_LIST_FOR_EACH_SAFE:遍历双向链表,并存储当前节点的后继节点用于安全校验 | +| 遍历包含双向链表的结构体 | - LOS_DL_LIST_FOR_EACH_ENTRY:遍历指定双向链表,获取包含该链表节点的结构体地址
- LOS_DL_LIST_FOR_EACH_ENTRY_SAFE:遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址 | ## 开发流程 @@ -82,6 +69,7 @@ 示例代码如下: + ``` #include "stdio.h" #include "los_list.h" @@ -125,8 +113,10 @@ static UINT32 ListSample(VOID) 编译运行得到的结果为: + ``` -Initial head Add listNode1 success +Initial head +Add listNode1 success Tail insert listNode2 success Delete success ``` diff --git a/zh-cn/device-dev/kernel/kernel-mini-appx-lib-cmsis.md b/zh-cn/device-dev/kernel/kernel-mini-appx-lib-cmsis.md index bdbd7cf6da726af54217abcd96b416ab683c8a38..f16ac17ee787d9a3c30a187834dbc436858b28f9 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-lib-cmsis.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-lib-cmsis.md @@ -1,10 +1,5 @@ # CMSIS支持 -- [基本概念](#基本概念) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -18,90 +13,135 @@ CMSIS-RTOS v2提供下面几种功能,接口详细信息可以查看API参考。 -**表1** CMSIS-RTOS v2接口 - -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 内核信息与控制 | osKernelGetInfo | 获取RTOS内核信息。 | -| | osKernelGetState | 获取当前的RTOS内核状态。 | -| | osKernelGetSysTimerCount | 获取RTOS内核系统计时器计数。 | -| | osKernelGetSysTimerFreq | 获取RTOS内核系统计时器频率。 | -| | osKernelInitialize | 初始化RTOS内核。 | -| | osKernelLock | 锁定RTOS内核调度程序。 | -| | osKernelUnlock | 解锁RTOS内核调度程序。 | -| | osKernelRestoreLock | 恢复RTOS内核调度程序锁定状态。 | -| | osKernelResume | 恢复RTOS内核调度程序。(暂未实现) | -| | osKernelStart | 启动RTOS内核调度程序。 | -| | osKernelSuspend | 挂起RTOS内核调度程序。(暂未实现) | -| | osKernelGetTickCount | 获取RTOS内核滴答计数。 | -| | osKernelGetTickFreq | 获取RTOS内核滴答频率。 | -| 线程管理 | osThreadDetach | 分离线程(线程终止时可以回收线程存储)。 | -| | osThreadEnumerate | 枚举活动线程。(暂未实现) | -| | osThreadExit | 终止当前正在运行的线程的执行。 | -| | osThreadGetCount | 获取活动线程的数量。 | -| | osThreadGetId | 返回当前正在运行的线程的线程ID。 | -| | osThreadGetName | 获取线程的名称。 | -| | osThreadGetPriority | 获取线程的当前优先级。 | -| | osThreadGetStackSize | 获取线程的堆栈大小。 | -| | osThreadGetStackSpace | 根据执行期间的堆栈水印记录获取线程的可用堆栈空间。 | -| | osThreadGetState | 获取线程的当前线程状态。 | -| | osThreadJoin | 等待指定线程终止。 | -| | osThreadNew | 创建一个线程并将其添加到活动线程中。 | -| | osThreadResume | 恢复线程的执行。 | -| | osThreadSetPriority | 更改线程的优先级。 | -| | osThreadSuspend | 暂停执行线程。 | -| | osThreadTerminate | 终止线程的执行。 | -| | osThreadYield | 将控制权传递给处于就绪状态的下一个线程。 | -| 线程标志 | osThreadFlagsSet | 设置线程的指定线程标志。 | -| | osThreadFlagsClear | 清除当前正在运行的线程的指定线程标志。 | -| | osThreadFlagsGet | 获取当前正在运行的线程的当前线程标志。 | -| | osThreadFlagsWait | 等待当前正在运行的线程的一个或多个线程标志发出信号。 | -| 事件标志 | osEventFlagsGetName | 获取事件标志对象的名称。(暂未实现) | -| | osEventFlagsNew | 创建并初始化事件标志对象。 | -| | osEventFlagsDelete | 删除事件标志对象。 | -| | osEventFlagsSet | 设置指定的事件标志。 | -| | osEventFlagsClear | 清除指定的事件标志。 | -| | osEventFlagsGet | 获取当前事件标志。 | -| | osEventFlagsWait | 等待一个或多个事件标志被发出信号。 | -| 通用等待函数 | osDelay | 等待超时(时间延迟)。 | -| | osDelayUntil | 等到指定时间。 | -| 计时器管理 | osTimerDelete | 删除计时器。 | -| | osTimerGetName | 获取计时器的名称。(暂未实现) | -| | osTimerIsRunning | 检查计时器是否正在运行。 | -| | osTimerNew | 创建和初始化计时器。 | -| | osTimerStart | 启动或重新启动计时器。 | -| | osTimerStop | 停止计时器。 | -| 互斥管理 | osMutexAcquire | 获取互斥或超时(如果已锁定)。 | -| | osMutexDelete | 删除互斥对象。 | -| | osMutexGetName | 获取互斥对象的名称。(暂未实现) | -| | osMutexGetOwner | 获取拥有互斥对象的线程。 | -| | osMutexNew | 创建并初始化Mutex对象。 | -| | osMutexRelease | 释放由osMutexAcquire获取的Mutex。 | -| 信号量 | osSemaphoreAcquire | 获取信号量令牌或超时(如果没有可用的令牌)。 | -| | osSemaphoreDelete | 删除一个信号量对象。 | -| | osSemaphoreGetCount | 获取当前信号量令牌计数。 | -| | osSemaphoreGetName | 获取信号量对象的名称。(暂未实现) | -| | osSemaphoreNew | 创建并初始化一个信号量对象。 | -| | osSemaphoreRelease | 释放信号量令牌,直到初始最大计数。 | -| 内存池 | osMemoryPoolAlloc | 从内存池分配一个内存块。 | -| | osMemoryPoolDelete | 删除内存池对象。 | -| | osMemoryPoolFree | 将分配的内存块返回到内存池。 | -| | osMemoryPoolGetBlockSize | 获取内存池中的内存块大小。 | -| | osMemoryPoolGetCapacity | 获取内存池中最大的内存块数。 | -| | osMemoryPoolGetCount | 获取内存池中使用的内存块数。 | -| | osMemoryPoolGetName | 获取内存池对象的名称。 | -| | osMemoryPoolGetSpace | 获取内存池中可用的内存块数。 | -| | osMemoryPoolNew | 创建并初始化一个内存池对象。 | -| 消息队列 | osMessageQueueDelete | 删除消息队列对象。 | -| | osMessageQueueGet | 从队列获取消息,或者如果队列为空,则从超时获取消息。 | -| | osMessageQueueGetCapacity | 获取消息队列中的最大消息数。 | -| | osMessageQueueGetCount | 获取消息队列中排队的消息数。 | -| | osMessageQueueGetMsgSize | 获取内存池中的最大消息大小。 | -| | osMessageQueueGetName | 获取消息队列对象的名称。(暂未实现) | -| | osMessageQueueGetSpace | 获取消息队列中消息的可用插槽数。 | -| | osMessageQueueNew | 创建和初始化消息队列对象。 | -| | osMessageQueuePut | 如果队列已满,则将消息放入队列或超时。 | -| | osMessageQueueReset | 将消息队列重置为初始空状态。(暂未实现) | + **表1** 内核信息与控制 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osKernelGetInfo | 获取RTOS内核信息。 | +| osKernelGetState | 获取当前的RTOS内核状态。 | +| osKernelGetSysTimerCount | 获取RTOS内核系统计时器计数。 | +| osKernelGetSysTimerFreq | 获取RTOS内核系统计时器频率。 | +| osKernelInitialize | 初始化RTOS内核。 | +| osKernelLock | 锁定RTOS内核调度程序。 | +| osKernelUnlock | 解锁RTOS内核调度程序。 | +| osKernelRestoreLock | 恢复RTOS内核调度程序锁定状态。 | +| osKernelResume | 恢复RTOS内核调度程序。(暂未实现) | +| osKernelStart | 启动RTOS内核调度程序。 | +| osKernelSuspend | 挂起RTOS内核调度程序。(暂未实现) | +| osKernelGetTickCount | 获取RTOS内核滴答计数。 | +| osKernelGetTickFreq | 获取RTOS内核滴答频率。 | + + **表2** 线程管理 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osThreadDetach | 分离线程(线程终止时可以回收线程存储)。(暂未实现) | +| osThreadEnumerate | 枚举活动线程。(暂未实现) | +| osThreadExit | 终止当前正在运行的线程的执行。 | +| osThreadGetCount | 获取活动线程的数量。 | +| osThreadGetId | 返回当前正在运行的线程的线程ID。 | +| osThreadGetName | 获取线程的名称。 | +| osThreadGetPriority | 获取线程的当前优先级。 | +| osThreadGetStackSize | 获取线程的堆栈大小。 | +| osThreadGetStackSpace | 根据执行期间的堆栈水印记录获取线程的可用堆栈空间。 | +| osThreadGetState | 获取线程的当前线程状态。 | +| osThreadJoin | 等待指定线程终止。(暂未实现) | +| osThreadNew | 创建一个线程并将其添加到活动线程中。 | +| osThreadResume | 恢复线程的执行。 | +| osThreadSetPriority | 更改线程的优先级。 | +| osThreadSuspend | 暂停执行线程。 | +| osThreadTerminate | 终止线程的执行。 | +| osThreadYield | 将控制权传递给处于就绪状态的下一个线程。 | + + **表3** 线程标志 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osThreadFlagsSet | 设置线程的指定线程标志。(暂未实现) | +| osThreadFlagsClear | 清除当前正在运行的线程的指定线程标志。(暂未实现) | +| osThreadFlagsGet | 获取当前正在运行的线程的当前线程标志。(暂未实现) | +| osThreadFlagsWait | 等待当前正在运行的线程的一个或多个线程标志发出信号。(暂未实现) | + + **表4** 事件标志 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osEventFlagsGetName | 获取事件标志对象的名称。(暂未实现) | +| osEventFlagsNew | 创建并初始化事件标志对象。 | +| osEventFlagsDelete | 删除事件标志对象。 | +| osEventFlagsSet | 设置指定的事件标志。 | +| osEventFlagsClear | 清除指定的事件标志。 | +| osEventFlagsGet | 获取当前事件标志。 | +| osEventFlagsWait | 等待一个或多个事件标志被发出信号。 | + + **表5** 通用等待函数 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osDelay | 等待超时(时间延迟)。 | +| osDelayUntil | 等到指定时间。 | + + **表6** 计时器管理 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osTimerDelete | 删除计时器。 | +| osTimerGetName | 获取计时器的名称。(暂未实现) | +| osTimerIsRunning | 检查计时器是否正在运行。 | +| osTimerNew | 创建和初始化计时器。 | +| osTimerStart | 启动或重新启动计时器。 | +| osTimerStop | 停止计时器。 | + + **表7** 互斥管理 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osMutexAcquire | 获取互斥或超时(如果已锁定)。 | +| osMutexDelete | 删除互斥对象。 | +| osMutexGetName | 获取互斥对象的名称。(暂未实现) | +| osMutexGetOwner | 获取拥有互斥对象的线程。 | +| osMutexNew | 创建并初始化Mutex对象。 | +| osMutexRelease | 释放由osMutexAcquire获取的Mutex。 | + + **表8** 信号量 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osSemaphoreAcquire | 获取信号量令牌或超时(如果没有可用的令牌)。 | +| osSemaphoreDelete | 删除一个信号量对象。 | +| osSemaphoreGetCount | 获取当前信号量令牌计数。 | +| osSemaphoreGetName | 获取信号量对象的名称。(暂未实现) | +| osSemaphoreNew | 创建并初始化一个信号量对象。 | +| osSemaphoreRelease | 释放信号量令牌,直到初始最大计数。 | + + **表9** 内存池 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osMemoryPoolAlloc | 从内存池分配一个内存块。 | +| osMemoryPoolDelete | 删除内存池对象。 | +| osMemoryPoolFree | 将分配的内存块返回到内存池。 | +| osMemoryPoolGetBlockSize | 获取内存池中的内存块大小。 | +| osMemoryPoolGetCapacity | 获取内存池中最大的内存块数。 | +| osMemoryPoolGetCount | 获取内存池中使用的内存块数。 | +| osMemoryPoolGetName | 获取内存池对象的名称。 | +| osMemoryPoolGetSpace | 获取内存池中可用的内存块数。 | +| osMemoryPoolNew | 创建并初始化一个内存池对象。 | + + **表10** 消息队列 + +| 接口名 | 接口描述 | +| -------- | -------- | +| osMessageQueueDelete | 删除消息队列对象。 | +| osMessageQueueGet | 从队列获取消息,或者如果队列为空,则从超时获取消息。 | +| osMessageQueueGetCapacity | 获取消息队列中的最大消息数。 | +| osMessageQueueGetCount | 获取消息队列中排队的消息数。 | +| osMessageQueueGetMsgSize | 获取内存池中的最大消息大小。 | +| osMessageQueueGetName | 获取消息队列对象的名称。(暂未实现) | +| osMessageQueueGetSpace | 获取消息队列中消息的可用插槽数。 | +| osMessageQueueNew | 创建和初始化消息队列对象。 | +| osMessageQueuePut | 如果队列已满,则将消息放入队列或超时。 | +| osMessageQueueReset | 将消息队列重置为初始空状态。(暂未实现) | ### 开发流程 @@ -115,6 +155,7 @@ CMSIS-RTOS2组件可以作为库或源代码提供(下图显示了库)。通 ### 编程实例 + ``` #include ... #include "cmsis_os2.h" diff --git a/zh-cn/device-dev/kernel/kernel-mini-appx-lib-posix.md b/zh-cn/device-dev/kernel/kernel-mini-appx-lib-posix.md index 411010397c1cb353126717b540ed34eff5774033..bdf21fb1c7cbf2110e19525c3dba6ba2132dafe8 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-lib-posix.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-lib-posix.md @@ -1,10 +1,5 @@ # POSIX支持 -- [基本概念](#基本概念) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [注意事项](#注意事项) - - [编程实例](#编程实例) ## 基本概念 @@ -16,238 +11,261 @@ OpenHarmony内核使用**musl libc**库以及自研接口,支持部分标准PO ### 接口说明 -**表1** POSIX接口说明 + **表1** process -| 类别 | 需要包含的头文件 | 接口名 | 描述 | -| -------- | -------- | -------- | -------- | -| process | #include | void abort(void); | 中止线程执行 | -| | #include | void assert(scalar expression); | 断言为假终止线程 | -| | #include | int pthread_cond_destroy(pthread_cond_t *cond); | 销毁条件变量 | -| | #include | int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); | 初始化条件变量 | -| | #include | int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *shared); | 获取条件变量属性,目前只支持获取PTHREAD_PROCESS_PRIVATE条件变量属性 | -| | #include | int pthread_condattr_setpshared(pthread_condattr_t *attr, int shared); | 设置条件变量属性 | -| | #include | int pthread_condattr_getclock(const pthread_condattr_t *attr, clockid_t *clock); | 获取线程时钟 | -| | #include | int pthread_condattr_destroy(pthread_condattr_t *attr); | 删除存储并使属性对象无效 | -| | #include | int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); | 等待条件 | -| | #include | int pthread_condattr_init(pthread_condattr_t *attr); | 初始化条件变量属性对象 | -| | #include | int pthread_mutex_unlock(pthread_mutex_t *mutex); | 解锁互斥锁 | -| | #include | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); | 创建一个新的线程 | -| | #include | int pthread_join(pthread_t thread, void **retval); | 等待指定的线程结束 | -| | #include | pthread_t pthread_self(void); | 获取当前线程的ID | -| | #include | int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param); | 获取线程的调度策略和参数 | -| | #include | int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param); | 设置线程的调度策略和参数 | -| | #include | int pthread_setschedprio(pthread_t thread, int prio); | 设置线程优先级 | -| | #include | int pthread_once(pthread_once_t *onceControl, void (*initRoutine)(void)); | 一次性操作任务 | -| | #include | int pthread_setcancelstate(int state, int *oldState); | 线程cancel功能开关 | -| | #include | int pthread_setcanceltype(int type, int *oldType); | 设置线程cancel类型 | -| | #include | int pthread_cancel(pthread_t thread); | 取消线程,目前仅支持先设置PTHREAD_CANCEL_ASYNCHRONOUS状态,再调用pthread_cancel取消线程 | -| | #include | void pthread_testcancel(void); | cancel线程 | -| | #include | int pthread_equal(pthread_t thread1, pthread_t thread2); | 判断是否为同一线程 | -| | #include | int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *outType); | 获取互斥锁的类型属性 | -| | #include | int pthread_mutex_init(pthread_mutex_t *__restrict m, const pthread_mutexattr_t *__restrict a); | 初始化互斥锁 | -| | #include | int pthread_mutex_lock(pthread_mutex_t *m); | 互斥锁加锁操作 | -| | #include | int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *absTimeout); | 申请互斥锁(只在设定时间内阻塞) | -| | #include | int pthread_mutex_trylock(pthread_mutex_t *m); | 互斥锁尝试加锁操作 | -| | #include | int pthread_mutex_destroy(pthread_mutex_t *m); | 销毁互斥锁 | -| | #include | int pthread_attr_init(pthread_attr_t *attr); | 初始化线程属性对象 | -| | #include | int pthread_attr_destroy(pthread_attr_t *attr); | 销毁线程属性对象 | -| | #include | int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize); | 获取线程属性对象的堆栈大小 | -| | #include | int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); | 设置线程属性对象的堆栈大小 | -| | #include | int pthread_attr_setstack(pthread_attr_t *attr, void *stackAddr, size_t stackSize); | 设置线程属性对象的堆栈属性(暂未实现) | -| | #include | int pthread_attr_getstack(const pthread_attr_t *attr, void **stackAddr, size_t *stackSize); | 获取线程属性对象的堆栈(暂未实现) | -| | #include | int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param); | 获取线程属性对象的调度参数属性 | -| | #include | int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); | 设置线程属性对象的调度参数属性 | -| | #include | int pthread_getname_np(pthread_t pthread, char *name, size_t len); | 获取线程名称 | -| | #include | int pthread_setname_np(pthread_t pthread, const char *name); | 设置线程名称 | -| | #include | int pthread_cond_broadcast(pthread_cond_t *c); | 解除若干已被等待条件阻塞的线程 | -| | #include | int pthread_cond_signal(pthread_cond_t *c); | 解除被阻塞的线程 | -| | #include | int pthread_cond_wait(pthread_cond_t *__restrict c, pthread_mutex_t *__restrict m); | 等待条件 | -| fs | #include | char *dirname(char *path); | 获取目录名 | -| | #include | struct dirent *readdir(DIR *dirp); | 读目录 | -| | #include | int stat(const char *restrict path, struct stat *restrict buf); | 获取文件信息 | -| | #include | int unlink(const char *pathname); | 删除文件 | -| | #include | int close(int fd); | 关闭文件 | -| | #include | int rename(const char *oldpath, const char *newpath); | 重命名指定的文件 | -| | #include | DIR *opendir(const char *dirname); | 打开指定目录 | -| | #include | int closedir(DIR *dir); | 关闭指定目录 | -| | #include | int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); | 挂载文件系统 | -| | #include | int umount(const char *target); | 卸载文件系统 | -| | #include | int umount2(const char *target, int flag); | 卸载文件系统 | -| | #include | int fsync(int fd); | 将与指定文件描述符关联的文件同步到存储设备 | -| | #include | int mkdir(const char *pathname, mode_t mode); | 创建目录 | -| | #include | int rmdir(const char *path); | 删除目录 | -| | #include | int fstat(int fd, struct stat *buf); | 获取文件状态信息 | -| | #include | int statfs(const char *path, struct statfs *buf); | 获取指定路径下文件的文件系统信息 | -| time | #include | int gettimeofday(struct timeval *tv, struct timezone *tz); | 获取时间。当前暂无时区概念,tz返回为空 | -| | #include | struct tm *gmtime(const time_t *timep); | 将日期和时间转换为细分时间或ASCII | -| | #include | struct tm *localtime(const time_t *timep); | 获取时间 | -| | #include | struct tm *localtime_r(const time_t *timep, struct tm *result); | 获取时间 | -| | #include | time_t mktime(struct tm *tm); | 将日期和时间转换为细分时间或ASCII | -| | #include | size_t strftime(char *s, size_t max, const char *format,const struct tm *tm); | 格式化日期和时间字符串 | -| | #include | time_t time(time_t *tloc); | 获得日历时间 | -| | #include | clock_t times(struct tms *buf); | 获取线程时间 | -| | #include | int timer_getoverrun(timer_t timerID); | 获取定时器超时次数 | -| | #include | int usleep(useconds_t usec); | 休眠(微秒单位) | -| | #include | int nanosleep(const struct timespec *tspec1, struct timespec *tspec2); | 暂停当前线程直到指定的时间到达 | -| | #include | int clock_gettime(clockid_t id, struct timespec *tspec); | 获取时钟的时间 | -| | #include | int timer_create(clockid_t id, struct sigevent *__restrict evp, timer_t *__restrict t); | 为线程创建计时器 | -| | #include | int timer_delete(timer_t t); | 为线程删除计时器 | -| | #include | int timer_settime(timer_t t, int flags, const struct itimerspec *__restrict val, struct itimerspec *__restrict old); | 为线程设置计时器 | -| | #include | time_t time (time_t *t); | 获取时间 | -| | #include | char *strptime(const char *s, const char *format, struct tm *tm); | 将时间的字符串表示形式转换为时间tm结构 | -| util | #include | int atoi(const char *nptr); | 字符串转换整型(int) | -| | #include | long atol(const char *nptr); | 字符串转换整型(long) | -| | #include | long long atoll(const char *nptr); | 字符串转换整型(long long) | -| | #include | int isalnum(int c); | 检查字母数字字符 | -| | #include | int isascii(int c); | 检查ASCII | -| | #include | int isdigit(int c); | 检查数字字符 | -| | #include | int islower(int c); | 检查小写字符 | -| | #include | int isprint(int c); | 检查任何可打印字符,包括空格 | -| | #include | int isspace(int c); | 检查空格字符 | -| | #include | int isupper(int c); | 检查所传的字符是否是大写字母 | -| | #include | int isxdigit(int c); | 判断字符是否为十六进制数 | -| | #include | long int random (void); | 生成伪随机数 | -| | #include | void srandom(unsigned int seed); | 初始化随机数生成器 | -| | #include | int tolower(int c); | 字母转换成小写 | -| | #include | int toupper(int c); | 字母转换成大写 | -| | #include | type va_arg(va_list ap, type); | 获取可变参数的当前参数,返回指定类型并将指针指向下一参数 | -| | #include | void va_copy(va_list dest, va_list src); | 复制参数 | -| | #include | void va_end(va_list ap); | 清空va_list可变参数列表 | -| | #include | void va_start(va_list ap, last); | 定义变长参数列表的起始位置 | -| | #include | char *strchr(const char *s, int c); | 在字符串中定位字符 | -| | #include | int strcmp(const char *s1, const char *s2); | 比较字符串 | -| | #include | size_t strcspn(const char *s, const char *reject); | 获取前缀子串的长度 | -| | #include | char *strdup(const char *s); | 字符串拷贝到新建的位置处 | -| | #include | size_t strlen(const char *s); | 计算字符串长度 | -| | #include | int strncasecmp(const char *s1, const char *s2, size_t n); | 比较固定长度字符串(忽略大小写) | -| | #include | int strcasecmp(const char *s1, const char *s2); | 比较字符串(忽略大小写) | -| | #include | int strncmp(const char *s1, const char *s2, size_t n); | 比较字符串(指定长度) | -| | #include | char *strrchr(const char *s, int c); | 在字符串中定位字符 | -| | #include | char *strstr(const char *haystack, const char *needle); | 寻找指定的子串 | -| | #include | long int strtol(const char *nptr, char **endptr, int base); | 将字符串转换为long型整数 | -| | #include | unsigned long int strtoul(const char *nptr, char **endptr, int base); | 将字符串转换为unsigned long型整数 | -| | #include | unsigned long long int strtoull(const char *nptr, char **endptr,int base); | 将字符串转换为unsigned long long型整数 | -| | #include | int regcomp(regex_t *preg, const char *regex, int cflags); | 编译正则表达式 | -| | #include | int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags); | 匹配正则表达式 | -| | #include | void regfree(regex_t *preg); | 释放正则表达式 | -| | #include | char *strerror(int errnum); | 返回描述错误号的字符串 | -| math | #include | int abs(int i); | 取绝对值 | -| | #include | double log(double x); | 自然对数函数 | -| | #include | double pow(double x, double y); | 求x的指数y次幂 | -| | #include | double round(double x); | 从零开始,舍入到最接近的整数 | -| | #include | double sqrt(double x); | 平方根 | -| IO | #include | void clearerr(FILE *stream); | 清除流的文件结尾和错误指示 | -| | #include | int fclose(FILE *stream); | 关闭文件流 | -| | #include | FILE *fdopen(int fd, const char *mode); | 通过文件描述符打开文件流 | -| | #include | int feof(FILE *stream); | 检测返回文件末尾指示位 | -| | #include | int fflush(FILE *stream); | 刷新流 | -| | #include | char *fgets(char *s, int size, FILE *stream); | 读取流的下一行 | -| | #include | int fileno(FILE *stream); | 返回流的文件描述符 | -| | #include | FILE *fopen(const char *path, const char *mode); | 打开流 | -| | #include | int fputs(const char *s, FILE *stream); | 向指定流写入一行 | -| | #include | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); | 读一个流 | -| | #include | int fseek(FILE *stream, long offset, int whence); | 设置流指针的位置 | -| | #include | long ftell(FILE *stream); | 获取流指针的位置 | -| | #include | size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream); | 向流写入 | -| | #include | void perror(const char *s); | 打印系统错误信息 | -| | #include | void rewind(FILE *stream); | 重新定位流 | -| | #include | ssize_t write(int fd, const void *buf, size_t size); | 写文件内容 | -| | #include | ssize_t read(int fd, void *buf, size_t size); | 读文件内容 | -| net | #include | void freeaddrinfo(struct addrinfo *res); | 释放调用getaddrinfo所分配的动态内存 | -| | #include | int getaddrinfo(const char *restrict nodename,const char *restrict servname,const struct addrinfo *restrict hints,struct addrinfo **restrict res); | 网络地址和服务转换 | -| | #include | int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,char *restrict node, socklen_t nodelen, char *restrict service,socklen_t servicelen, int flags); | 以协议无关的方式进行地址到名称的转换 | -| | #include | unsigned int if_nametoindex(const char *ifname); | 通过网络接口名得到索引 | -| | #include | in_addr_t inet_addr(const char *cp); | 网络主机地址点分十进制形式转换位二进制形式 | -| | #include | char *inet_ntoa(struct in_addr in); | 网络主机地址二进制形式转换位点分十进制形式 | -| | #include | const char *inet_ntop(int af, const void *src,char *dst, socklen_t size); | 网络地址转换 | -| | #include | int inet_pton(int af, const char *src, void *dst); | 网络地址转换 | -| | #include | int listen(int sockfd, int backlog); | 监听套接字 | -| | #include | ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); | 从套接字接收消息.只支持iov大小为1的场景,且不支持ancillary消息 | -| | #include | ssize_t send(int sockfd, const void *buf, size_t len, int flags); | 从socket发送消息 | -| | #include | ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); | 从socket发送消息。不支持ancillary消息 | -| | #include | ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen); | 从socket发送消息 | -| | #include | int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen); | 设置与套接字关联的选项 | -| mem | #include | int memcmp(const void *s1, const void *s2, size_t n); | 内存比较 | -| | #include | void *memcpy(void *dest, const void *src, size_t n); | 内存拷贝 | -| | #include | void *memset(void *s, int c, size_t n); | 内存初始化 | -| | #include | void *realloc(void *ptr, size_t size); | 重分配内存 | -| | #include | void *malloc(size_t size); | 动态分配内存块大小 | -| | #include | void free(void *ptr); | 释放ptr所指向的内存空间 | -| IPC | #include | int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); | 计时锁定信号量 | -| | #include | int sem_destroy(sem_t *sem); | 销毁指定的无名信号量 | -| | #include | int sem_trywait(sem_t *sem); | 尝试申请一个信号量 | -| | #include | int sem_init(sem_t *sem, int pshared, unsigned int value); | 创建并初始化一个无名信号量 | -| | #include | int sem_post(sem_t *sem); | 增加信号量计数 | -| | #include | int sem_wait(sem_t *sem); | 获取信号量 | -| | #include | mqd_t mq_open(const char *mqName, int openFlag, ...); | 此API用于打开一个具有指定名称的已有消息队列或创建一个新的消息队列 | -| | #include | int mq_close(mqd_t personal); | 此API用于关闭具有指定描述符的消息队列 | -| | #include | int mq_unlink(const char *mqName); | 此API用于删除具有指定名称的消息队列 | -| | #include | int mq_send(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio); | 此API用于将具有指定内容和长度的消息放入具有指定描述符的消息队列中 | -| | #include | ssize_t mq_receive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio); | 此API用于从具有指定描述符的消息队列中删除最老的消息,并将其放入msg_ptr所指向的缓冲区中 | -| | #include | int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, const struct timespec *absTimeout) | 此API用于在预定时间将具有指定内容和长度的消息放入具有描述符的消息队列中 | -| | #include | ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout); | 此API用于从具有指定描述符的消息队列消息中获取具有指定消息内容和长度的消息 | -| | #include | int mq_setattr(mqd_t mqdes, const struct mq_attr *__restrict newattr, struct mq_attr *__restrict oldattr); | 设置描述符指定的消息队列属性 | -| | version | #include | const char *libc_get_version_string(void); | -| | #include | int libc_get_version(void); | 获取libc版本号 | +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <stdlib.h> | void abort(void); | 中止线程执行 | +| \#include <assert.h> | void assert(scalar expression); | 断言为假终止线程 | +| \#include <pthread.h> | int pthread_cond_destroy(pthread_cond_t \*cond); | 销毁条件变量 | +| \#include <pthread.h> | int pthread_cond_init(pthread_cond_t \*restrict co
nd, const pthread_condattr_t \*restrict attr); | 初始化条件变量 | +| \#include <pthread.h> | int pthread_cond_timedwait(pthread_cond_t \*restr
ict cond, pthread_mutex_t \*restrict mutex, const st
ruct timespec \*restrict abstime); | 等待条件 | +| \#include <pthread.h> | int pthread_condattr_init(pthread_condattr_t \*attr); | 初始化条件变量属性对象 | +| \#include <pthread.h> | int pthread_mutex_unlock(pthread_mutex_t \*mutex); | 解锁互斥锁 | +| \#include <pthread.h> | int pthread_create(pthread_t \*thread, const pthread_
attr_t \*attr, void \*(\*start_routine)(void \*), void \*arg); | 创建一个新的线程 | +| \#include <pthread.h> | int pthread_join(pthread_t thread, void \*\*retval); | 等待指定的线程结束 | +| \#include <pthread.h> | pthread_t pthread_self(void); | 获取当前线程的ID | +| \#include <pthread.h> | int pthread_getschedparam(pthread_t thread, int \*
policy, struct sched_param \*param); | 获取线程的调度策略和参数 | +| \#include <pthread.h> | int pthread_setschedparam(pthread_t thread, int
policy, const struct sched_param \*param); | 设置线程的调度策略和参数 | +| \#include <pthread.h> | int pthread_mutex_init(pthread_mutex_t \*__restrict m
, const pthread_mutexattr_t \*__restrict a); | 初始化互斥锁 | +| \#include <pthread.h> | int pthread_mutex_lock(pthread_mutex_t \*m); | 互斥锁加锁操作 | +| \#include <pthread.h> | int pthread_mutex_trylock(pthread_mutex_t \*m); | 互斥锁尝试加锁操作 | +| \#include <pthread.h> | int pthread_mutex_destroy(pthread_mutex_t \*m); | 销毁互斥锁 | +| \#include <pthread.h> | int pthread_attr_init(pthread_attr_t \*attr); | 初始化线程属性对象 | +| \#include <pthread.h> | int pthread_attr_destroy(pthread_attr_t \*attr); | 销毁线程属性对象 | +| \#include <pthread.h> | int pthread_attr_getstacksize(const pthread_attr
_t \*attr, size_t \*stacksize); | 获取线程属性对象的堆栈大小 | +| \#include <pthread.h> | int pthread_attr_setstacksize(pthread_attr_t \*attr
, size_t stacksize); | 设置线程属性对象的堆栈大小 | +| \#include <pthread.h> | int pthread_attr_getschedparam(const pthread_
attr_t \*attr, struct sched_param \*param); | 获取线程属性对象的调度参数属性 | +| \#include <pthread.h> | int pthread_attr_setschedparam(pthread_attr_t \*
attr, const struct sched_param \*param); | 设置线程属性对象的调度参数属性 | +| \#include <pthread.h> | int pthread_getname_np(pthread_t pthread, char
\*name, size_t len); | 获取线程名称 | +| \#include <pthread.h> | int pthread_setname_np(pthread_t pthread, const
char \*name); | 设置线程名称 | +| \#include <pthread.h> | int pthread_cond_broadcast(pthread_cond_t \*c); | 解除若干已被等待条件阻塞的线程 | +| \#include <pthread.h> | int pthread_cond_signal(pthread_cond_t \*c); | 解除被阻塞的线程 | +| \#include <pthread.h> | int pthread_cond_wait(pthread_cond_t \*__restrict
c, pthread_mutex_t \*__restrict m); | 等待条件 | + + **表2** fs + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <libgen.h> | char \*dirname(char \*path); | 获取目录名 | +| \#include <dirent.h> | struct dirent \*readdir(DIR \*dirp); | 读目录 | +| \#include <sys/stat.h> | int stat(const char \*restrict path, struct stat \*restrict buf); | 获取文件信息 | +| \#include <unistd.h> | int unlink(const char \*pathname); | 删除文件 | +| \#include <fcntl.h | int open(const char \*path, int oflags, ...); | 用于打开文件,如文件不存在,创建文件并打开 | +| \#include <nistd.h> | int close(int fd); | 关闭文件 | +| \#include <stdio.h> | int rename(const char \*oldpath, const char \*newpath); | 重命名指定的文件 | +| \#include <dirent.h> | DIR  \*opendir(const char \*dirname); | 打开指定目录 | +| \#include <dirent.h> | int closedir(DIR \*dir); | 关闭指定目录 | +| \#include <sys/mount.h> | int mount(const char \*source, const char \*target, con
st char \*filesystemtype, unsigned long mountflags, c
onst void \*data); | 挂载文件系统 | +| \#include <sys/mount.h> | int umount(const char \*target); | 卸载文件系统 | +| \#include <sys/mount.h> | int umount2(const char \*target, int flag); | 卸载文件系统 | +| \#include <sys/stat.h> | int fsync(int fd); | 将与指定文件描述符关联的文件同步到存储设备 | +| \#include <sys/stat.h> | int mkdir(const char \*pathname, mode_t mode); | 创建目录 | +| \#include <unistd.h> | int rmdir(const char \*path); | 删除目录 | +| \#include <sys/stat.h> | int fstat(int fd, struct stat \*buf); | 获取文件状态信息 | +| \#include <sys/statfs.h> | int statfs(const char \*path, struct statfs \*buf); | 获取指定路径下文件的文件系统信息 | + + **表3** time + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <sys/time.h> | int gettimeofday(struct timeval \*tv, struct timezone \*tz); | 获取时间。当前暂无时区概念,tz返回为空 | +| \#include <time.h> | struct tm \*gmtime(const time_t \*timep); | 将日期和时间转换为细分时间或ASCII | +| \#include <time.h> | struct tm \*localtime(const time_t \*timep); | 获取时间 | +| \#include <time.h> | struct tm \*localtime_r(const time_t \*timep, struct tm \*result); | 获取时间 | +| \#include <time.h> | time_t mktime(struct tm \*tm); | 将日期和时间转换为细分时间或ASCII | +| \#include <time.h> | size_t strftime(char \*s, size_t max, const char \*
format,const struct tm \*tm); | 格式化日期和时间字符串 | +| \#include <time.h> | time_t time(time_t \*tloc); | 获得日历时间 | +| \#include <sys/times.h> | clock_t times(struct tms \*buf); | 获取线程时间 | +| \#include <unistd.h> | int usleep(useconds_t usec); | 休眠(微秒单位) | +| \#include <time.h> | int nanosleep(const struct timespec \*tspec1, struct
timespec \*tspec2); | 暂停当前线程直到指定的时间到达 | +| \#include <time.h> | int clock_gettime(clockid_t id, struct timespec \*tspec); | 获取时钟的时间 | +| \#include <time.h> | int timer_create(clockid_t id, struct sigevent \*__
restrict evp, timer_t \*__restrict t); | 为线程创建计时器 | +| \#include <time.h> | int timer_delete(timer_t t); | 为线程删除计时器 | +| \#include <time.h> | int timer_settime(timer_t t, int flags, const struct
itimerspec \*__restrict val, struct itimerspec \*__restrict old); | 为线程设置计时器 | +| \#include <time.h> | time_t time (time_t \*t); | 获取时间 | +| \#include <time.h> | char \*strptime(const char \*s, const char \*format, struct tm \*tm); | 将时间的字符串表示形式转换为时间tm结构 | + + **表4** util + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <stdlib.h> | int atoi(const char \*nptr); | 字符串转换整型(int) | +| \#include <stdlib.h> | long atol(const char \*nptr); | 字符串转换整型(long) | +| \#include <stdlib.h> | long long atoll(const char \*nptr); | 字符串转换整型(long long) | +| \#include <ctype.h> | int isalnum(int c); | 检查字母数字字符 | +| \#include <ctype.h> | int isascii(int c); | 检查ASCII | +| \#include <ctype.h> | int isdigit(int c); | 检查数字字符 | +| \#include <ctype.h> | int islower(int c); | 检查小写字符 | +| \#include <ctype.h> | int isprint(int c); | 检查任何可打印字符,包括空格 | +| \#include <ctype.h> | int isspace(int c); | 检查空格字符 | +| \#include <ctype.h> | int isupper(int c); | 检查所传的字符是否是大写字母 | +| \#include <ctype.h> | int isxdigit(int c); | 判断字符是否为十六进制数 | +| \#include <stdlib.h> | long int random (void); | 生成伪随机数 | +| \#include <stdlib.h> | void srandom(unsigned int seed); | 初始化随机数生成器 | +| \#include <ctype.h> | int tolower(int c); | 字母转换成小写 | +| \#include <ctype.h> | int toupper(int c); | 字母转换成大写 | +| \#include <stdarg.h> | type va_arg(va_list ap, type); | 获取可变参数的当前参数,返回指定类型并将指针指向下一参数 | +| \#include <stdarg.h> | void va_copy(va_list dest, va_list src); | 复制参数 | +| \#include <stdarg.h> | void va_end(va_list ap); | 清空va_list可变参数列表 | +| \#include <stdarg.h> | void va_start(va_list ap, last); | 定义变长参数列表的起始位置 | +| \#include <string.h> | char \*strchr(const char \*s, int c); | 在字符串中定位字符 | +| \#include <string.h> | int strcmp(const char \*s1, const char \*s2); | 比较字符串 | +| \#include <string.h> | size_t strcspn(const char \*s, const char \*reject); | 获取前缀子串的长度 | +| \#include <string.h> | char \*strdup(const char \*s); | 字符串拷贝到新建的位置处 | +| \#include <string.h> | size_t strlen(const char \*s); | 计算字符串长度 | +| \#include <strings.h> | int strncasecmp(const char \*s1, const char \*s2, size_t n); | 比较固定长度字符串(忽略大小写) | +| \#include <strings.h> | int strcasecmp(const char \*s1, const char \*s2); | 比较字符串(忽略大小写) | +| \#include <string.h> | int strncmp(const char \*s1, const char \*s2, size_t n); | 比较字符串(指定长度) | +| \#include <string.h> | char \*strrchr(const char \*s, int c); | 在字符串中定位字符 | +| \#include <string.h> | char \*strstr(const char \*haystack, const char \*needle); | 寻找指定的子串 | +| \#include <stdlib.h> | long int strtol(const char \*nptr, char \*\*endptr, int base); | 将字符串转换为long型整数 | +| \#include <stdlib.h> | unsigned long int strtoul(const char \*nptr, char
\*\*endptr, int base); | 将字符串转换为unsigned long型整数 | +| \#include <stdlib.h> | unsigned long long int strtoull(const char \*nptr,
char \*\*endptr,int base); | 将字符串转换为unsigned long long型整数 | +| \#include <regex.h> | int regcomp(regex_t \*preg, const char \*regex,
int cflags); | 编译正则表达式 | +| \#include <regex.h> | int regexec(const regex_t \*preg, const char \*
string, size_t nmatch,regmatch_t pmatch[], int eflags); | 匹配正则表达式 | +| \#include <regex.h> | void regfree(regex_t \*preg); | 释放正则表达式 | +| \#include <string.h> | char \*strerror(int errnum); | 返回描述错误号的字符串 | + + **表5** math + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <stdlib.h> | int abs(int i); | 取绝对值 | +| \#include <math.h> | double log(double x); | 自然对数函数 | +| \#include <math.h> | double pow(double x, double y); | 求x的指数y次幂 | +| \#include <math.h> | double round(double x); | 从零开始,舍入到最接近的整数 | +| \#include <math.h> | double sqrt(double x); | 平方根 | + + **表6** IO + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <stdio.h> | void clearerr(FILE \*stream); | 清除流的文件结尾和错误指示 | +| \#include <stdio.h> | int fclose(FILE \*stream); | 关闭文件流 | +| \#include <stdio.h> | FILE \*fdopen(int fd, const char \*mode); | 通过文件描述符打开文件流 | +| \#include <stdio.h> | int feof(FILE \*stream); | 检测返回文件末尾指示位 | +| \#include <stdio.h> | int fflush(FILE \*stream); | 刷新流 | +| \#include <stdio.h> | char \*fgets(char \*s, int size, FILE \*stream); | 读取流的下一行 | +| \#include <stdio.h> | int fileno(FILE \*stream); | 返回流的文件描述符 | +| \#include <stdio.h> | FILE \*fopen(const char \*path, const char \*mode); | 打开流 | +| \#include <stdio.h> | int fputs(const char \*s, FILE \*stream); | 向指定流写入一行 | +| \#include <stdio.h> | size_t fread(void \*ptr, size_t size, size_t nmemb,
FILE \*stream); | 读一个流 | +| \#include <stdio.h> | int fseek(FILE \*stream, long offset, int whence); | 设置流指针的位置 | +| \#include <stdio.h> | long ftell(FILE \*stream); | 获取流指针的位置 | +| \#include <stdio.h> | size_t fwrite(const void \*ptr, size_t size, size_t
nmemb,FILE \*stream); | 向流写入 | +| \#include <stdio.h> | void perror(const char \*s); | 打印系统错误信息 | +| \#include <stdio.h> | void rewind(FILE \*stream); | 重新定位流 | +| \#include <unistd.h> | ssize_t write(int fd, const void \*buf, size_t size); | 写文件内容 | +| \#include <unistd.h> | ssize_t read(int fd, void \*buf, size_t size); | 读文件内容 | + + **表7** net + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <sys/socket.h> | void freeaddrinfo(struct addrinfo \*res); | 释放调用getaddrinfo所分配的动态内存 | +| \#include <sys/socket.h> | int getaddrinfo(const char \*restrict nodename,const
char \*restrict servname,const struct addrinfo \*restrict
hints,struct addrinfo \*\*restrict res); | 网络地址和服务转换 | +| \#include <sys/socket.h> | int getnameinfo(const struct sockaddr \*restrict sa,
socklen_t salen,char \*restrict node, socklen_t nodelen
, char \*restrict service,socklen_t servicelen, int flags); | 以协议无关的方式进行地址到名称的转换 | +| \#include <net/if.h> | unsigned int if_nametoindex(const char \*ifname); | 通过网络接口名得到索引 | +| \#include <arpa/inet.h> | in_addr_t inet_addr(const char \*cp); | 网络主机地址点分十进制形式转换位二进制形式 | +| \#include <arpa/inet.h> | char \*inet_ntoa(struct in_addr in); | 网络主机地址二进制形式转换位点分十进制形式 | +| \#include <arpa/inet.h> | const char \*inet_ntop(int af, const void \*src,char \*dst,
socklen_t size); | 网络地址转换 | +| \#include <arpa/inet.h> | int inet_pton(int af, const char \*src, void \*dst); | 网络地址转换 | +| \#include <sys/socket.h> | int listen(int sockfd, int backlog); | 监听套接字 | +| \#include <sys/socket.h> | ssize_t recvmsg(int sockfd, struct msghdr \*msg, int flags); | 从套接字接收消息.只支持iov大小为1的场景,且不支持ancillary消息 | +| \#include <sys/socket.h> | ssize_t send(int sockfd, const void \*buf, size_t len, int flags); | 从socket发送消息 | +| \#include <sys/socket.h> | ssize_t sendmsg(int sockfd, const struct msghdr \*msg, int flags); | 从socket发送消息。不支持ancillary消息 | +| \#include <sys/socket.h> | ssize_t sendto(int sockfd, const void \*buf, size_t len, int
flags,const struct sockaddr \*dest_addr, socklen_t addrlen); | 从socket发送消息 | +| \#include <sys/socket.h> | int setsockopt(int sockfd, int level, int optname,const
void \*optval, socklen_t optlen); | 设置与套接字关联的选项 | + + **表8** mem + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <string.h> | int memcmp(const void \*s1, const void \*s2, size_t n); | 内存比较 | +| \#include <string.h> | void \*memcpy(void \*dest, const void \*src, size_t n); | 内存拷贝 | +| \#include <string.h> | void \*memset(void \*s, int c, size_t n); | 内存初始化 | +| \#include <stdlib.h> | void \*realloc(void \*ptr, size_t size); | 重分配内存 | +| \#include <stdlib.h> | void \*malloc(size_t size); | 动态分配内存块大小 | +| \#include <stdlib.h> | void free(void \*ptr); | 释放ptr所指向的内存空间 | + + **表9** IPC + +| 需要包含的头文件 | 接口名 | 描述 | +| -------- | -------- | -------- | +| \#include <semaphore.h> | int sem_timedwait(sem_t \*sem, const struct
 timespec \*abs_timeout); | 计时锁定信号量 | +| \#include <semaphore.h> | int sem_destroy(sem_t \*sem); | 销毁指定的无名信号量 | +| \#include <semaphore.h> | int sem_init(sem_t \*sem, int pshared
, unsigned int value); | 创建并初始化一个无名信号量 | +| \#include <semaphore.h> | int sem_post(sem_t \*sem); | 增加信号量计数 | +| \#include <semaphore.h> | int sem_wait(sem_t \*sem); | 获取信号量 | +| \#include <mqueue.h> | mqd_t mq_open(const char \*mqName,
 int openFlag, ...); | 此API用于打开一个具有指定名称的已有消息队列或创建一个新的消息队列 | +| \#include <mqueue.h> | int mq_close(mqd_t personal); | 此API用于关闭具有指定描述符的消息队列 | +| \#include <mqueue.h> | int mq_unlink(const char \*mqName); | 此API用于删除具有指定名称的消息队列 | +| \#include <mqueue.h> | int mq_send(mqd_t personal, const
 char \*msg,size_t msgLen, unsigned int msgPrio); | 此API用于将具有指定内容和长度的消息放入具有指定描述符的消息队列中 | +| \#include <mqueue.h> | ssize_t mq_receive(mqd_t personal, char \*msg,
size_t msgLen, unsigned int \*msgPrio); | 此API用于从具有指定描述符的消息队列中删除最老的消息,并将其放入msg_ptr所指向的缓冲区中 | +| \#include <mqueue.h> | int mq_timedsend(mqd_t personal, const char
\*msg, size_t msgLen, unsigned int msgPrio, c
onst struct timespec \*absTimeout) | 此API用于在预定时间将具有指定内容和长度的消息放入具有描述符的消息队列中 | +| \#include <mqueue.h> | ssize_t mq_timedreceive(mqd_t personal, char
\*msg, size_t msgLen, unsigned int \*msgPrio,
const struct timespec \*absTimeout); | 此API用于从具有指定描述符的消息队列消息中获取具有指定消息内容和长度的消息 | +| \#include <mqueue.h> | int mq_setattr(mqd_t mqdes, const struct mq_
attr \*__restrict newattr, struct mq_attr \*__restrict oldattr); | 设置描述符指定的消息队列属性 | +| \#include <libc.h> | const char \*libc_get_version_string(void); | 获取libc版本字符串 | +| \#include <libc.h> | int libc_get_version(void); | 获取libc版本号 | ### 注意事项 常用错误码对照表: -| C Name | Value | Description | 含义 | +| 错误码 | 值 | 描述 | 含义 | | -------- | -------- | -------- | -------- | | ENOERR | 0 | Success | 成功 | -| EPERM | 1 | Operation not permitted | 操作不允许 | -| ENOENT | 2 | No such file or directory | 没有这样的文件或目录 | -| ESRCH | 3 | No such process | 没有这样的进程(暂不支持) | -| EINTR | 4 | Interrupted system call | 系统调用被中断 | -| EIO | 5 | I/O error | I/O错误 | -| ENXIO | 6 | No such device or address | 没有这样的设备或地址 | -| E2BIG | 7 | Arg list too long | 参数列表太长 | -| ENOEXEC | 8 | Exec format error | 执行格式错误 | -| EBADF | 9 | Bad file number | 坏的文件描述符 | -| ECHILD | 10 | No child processes | 没有子进程(暂不支持) | -| EAGAIN | 11 | Try again | 资源暂时不可用 | -| ENOMEM | 12 | Out of memory | 内存溢出 | -| EACCES | 13 | Permission denied | 拒绝许可 | -| EFAULT | 14 | Bad address | 错误的地址 | -| ENOTBLK | 15 | Block device required | 块设备请求 | -| EBUSY | 16 | Device or resource busy | 设备或资源忙 | -| EEXIST | 17 | File exists | 文件存在 | -| EXDEV | 18 | Cross-device link | 无效的交叉链接 | -| ENODEV | 19 | No such device | 设备不存在 | -| ENOTDIR | 20 | Not a directory | 不是一个目录 | -| EISDIR | 21 | Is a directory | 是一个目录 | -| EINVAL | 22 | Invalid argument | 无效的参数 | -| ENFILE* | 23 | File table overflow | 打开太多的文件系统 | -| EMFILE | 24 | Too many open files | 打开的文件过多 | -| EFBIG | 27 | File too large | 文件太大 | -| ENOSPC | 28 | No space left on device | 设备上没有空间 | -| ESPIPE | 29 | Illegal seek | 非法移位 | -| EROFS | 30 | Read-only file system | 只读文件系统 | -| EMLINK | 31 | Too many links | 太多的链接 | -| EDOM | 33 | Math argument out of domain | 数值结果超出范围 | -| ERANGE | 34 | Math result not representable | 数值结果不具代表性 | -| EDEADLK | 35 | Resource deadlock would occur | 资源死锁错误 | -| ENAMETOOLONG | 36 | Filename too long | 文件名太长 | -| ENOLCK | 37 | No record locks available | 没有可用锁 | -| ENOSYS | 38 | Function not implemented | 功能没有实现 | -| ENOTEMPTY | 39 | Directory not empty | 目录不空 | -| ELOOP | 40 | Too many symbolic links encountered | 符号链接层次太多 | -| ENOMSG | 42 | No message of desired type | 没有期望类型的消息 | -| EIDRM | 43 | Identifier removed | 标识符删除 | -| ELNRNG | 48 | Link number out of range | 链接数超出范围 | -| EBADR | 53 | Invalid request descriptor | 请求描述符无效 | -| EBADRQC | 56 | Invalid request code | 无效的请求代码 | -| ENOSTR | 60 | Device not a stream | 设备不是字符流 | -| ENODATA | 61 | No data available | 无可用数据 | -| ETIME | 62 | Timer expired | 计时器过期 | -| EPROTO | 71 | Protocol error | 协议错误 | -| EBADMSG | 74 | Not a data message | 非数据消息 | -| EOVERFLOW | 75 | Value too large for defined data type | 值太大,对于定义数据类型 | -| EMSGSIZE | 90 | Message too long | 消息太长 | +| EPERM | 1 | Operation not permitted | 操作不允许 | +| ENOENT | 2 | No such file or directory | 没有这样的文件或目录 | +| ESRCH | 3 | No such process | 没有这样的进程(暂不支持) | +| EINTR | 4 | Interrupted system call | 系统调用被中断 | +| EIO | 5 | I/O error | I/O错误 | +| ENXIO | 6 | No such device or address | 没有这样的设备或地址 | +| E2BIG | 7 | Arg list too long | 参数列表太长 | +| ENOEXEC | 8 | Exec format error | 执行格式错误 | +| EBADF | 9 | Bad file number | 坏的文件描述符 | +| ECHILD | 10 | No child processes | 没有子进程(暂不支持) | +| EAGAIN | 11 | Try again | 资源暂时不可用 | +| ENOMEM | 12 | Out of memory | 内存溢出 | +| EACCES | 13 | Permission denied | 拒绝许可 | +| EFAULT | 14 | Bad address | 错误的地址 | +| ENOTBLK | 15 | Block device required | 块设备请求 | +| EBUSY | 16 | Device or resource busy | 设备或资源忙 | +| EEXIST | 17 | File exists | 文件存在 | +| EXDEV | 18 | Cross-device link | 无效的交叉链接 | +| ENODEV | 19 | No such device | 设备不存在 | +| ENOTDIR | 20 | Not a directory | 不是一个目录 | +| EISDIR | 21 | Is a directory | 是一个目录 | +| EINVAL | 22 | Invalid argument | 无效的参数 | +| ENFILE\* | 23 | File table overflow | 打开太多的文件系统 | +| EMFILE | 24 | Too many open files | 打开的文件过多 | +| EFBIG | 27 | File too large | 文件太大 | +| ENOSPC | 28 | No space left on device | 设备上没有空间 | +| ESPIPE | 29 | Illegal seek | 非法移位 | +| EROFS | 30 | Read-only file system | 只读文件系统 | +| EMLINK | 31 | Too many links | 太多的链接 | +| EDOM | 33 | Math argument out of domain | 数值结果超出范围 | +| ERANGE | 34 | Math result not representable | 数值结果不具代表性 | +| EDEADLK | 35 | Resource deadlock would occur | 资源死锁错误 | +| ENAMETOOLONG | 36 | Filename too long | 文件名太长 | +| ENOLCK | 37 | No record locks available | 没有可用锁 | +| ENOSYS | 38 | Function not implemented | 功能没有实现 | +| ENOTEMPTY | 39 | Directory not empty | 目录不空 | +| ELOOP | 40 | Too many symbolic links encountered | 符号链接层次太多 | +| ENOMSG | 42 | No message of desired type | 没有期望类型的消息 | +| EIDRM | 43 | Identifier removed | 标识符删除 | +| ELNRNG | 48 | Link number out of range | 链接数超出范围 | +| EBADR | 53 | Invalid request descriptor | 请求描述符无效 | +| EBADRQC | 56 | Invalid request code | 无效的请求代码 | +| ENOSTR | 60 | Device not a stream | 设备不是字符流 | +| ENODATA | 61 | No data available | 无可用数据 | +| ETIME | 62 | Timer expired | 计时器过期 | +| EPROTO | 71 | Protocol error | 协议错误 | +| EBADMSG | 74 | Not a data message | 非数据消息 | +| EOVERFLOW | 75 | Value too large for defined data type | 值太大,对于定义数据类型 | +| EMSGSIZE | 90 | Message too long | 消息太长 | ### 编程实例 @@ -256,6 +274,7 @@ demo功能: 创建一个线程并将父线程中的信息传递给子线程,在子线程中打印传递过来的信息和自身线程id值。 + ``` #include #include @@ -286,6 +305,7 @@ void DemoForTest() 执行DemoForTest运行结果如下: + ``` ++++++++++++++ Hello world ThreadFn tid = 48 ++++++++++++++ diff --git a/zh-cn/device-dev/kernel/kernel-mini-appx-lib.md b/zh-cn/device-dev/kernel/kernel-mini-appx-lib.md index ee74f5b789afa6ebe1d7566c421e46c8dd3ca845..8ce3db5c735a90579bb5693248740808c0664419 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-lib.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-lib.md @@ -1,6 +1,7 @@ # 标准库支持 + - **[CMSIS支持](kernel-mini-appx-lib-cmsis.md)** - **[POSIX支持](kernel-mini-appx-lib-posix.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-interrupt.md b/zh-cn/device-dev/kernel/kernel-mini-basic-interrupt.md index 176ba1018bc75d8479aa8948a54f37d92b879a42..9c8e2e42ded8903ddaa5a864aea95bef8990e043 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-interrupt.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-interrupt.md @@ -1,10 +1,5 @@ # 中断管理 -- [基本概念](#基本概念) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) -- [结果验证](#结果验证) ## 基本概念 @@ -40,27 +35,29 @@ OpenHarmony LiteOS-M内核的中断模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 中断模块接口 + **表1** 创建、删除中断 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 创建、删除中断 | LOS_HwiCreate | 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序。 | -| | LOS_HwiDelete | 根据指定的中断号,删除中断。 | -| 打开、关闭中断 | LOS_IntUnLock | 开中断,使能当前处理器所有中断响应。 | -| | LOS_IntLock | 关中断,关闭当前处理器所有中断响应。 | -| | LOS_IntRestore | 恢复到使用LOS_IntLock、LOS_IntUnLock操作之前的中断状态。 | -| 使能和屏蔽指定中断 | LOS_HwiDisable | 中断屏蔽。(通过设置寄存器,禁止CPU响应该中断) | -| | LOS_HwiEnable | 中断使能。(通过设置寄存器,允许CPU响应该中断) | -| 设置中断优先级 | LOS_HwiSetPriority | 设置中断优先级。 | -| 触发中断 | LOS_HwiTrigger | 触发中断。(通过写中断控制器的相关寄存器模拟外部中断) | -| 清除中断寄存器状态 | LOS_HwiClear | 清除中断号对应的中断寄存器的状态位,此接口依赖中断控制器版本,非必需。 | +| 接口名 | 描述 | +| -------- | -------- | +| HalHwiCreate | 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序。 | +| HalHwiDelete | 根据指定的中断号,删除中断。 | + + **表2** 打开、关闭中断 + +| 接口名 | 描述 | +| -------- | -------- | +| LOS_IntUnLock | 开中断,使能当前处理器所有中断响应。 | +| LOS_IntLock | 关中断,关闭当前处理器所有中断响应。 | +| LOS_IntRestore | 恢复到使用LOS_IntLock、LOS_IntUnLock操作之前的中断状态。 | ## 开发流程 -1. 调用中断创建接口LOS_HwiCreate创建中断。 -2. 调用中断触发接口LOS_HwiTrigger触发中断。 -3. 调用LOS_HwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。 +1. 调用中断创建接口HalHwiCreate创建中断。 + +2. 调用TestHwiTrigger接口触发指定中断(该接口在测试套中定义,通过写中断控制器的相关寄存器模拟外部中断,一般的外设设备,不需要执行这一步)。 + +3. 调用HalHwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** @@ -85,6 +82,7 @@ OpenHarmony LiteOS-M内核的中断模块提供下面几种功能,接口详细 代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI_NUM_TEST产生中断时,会调用中断处理函数: + ``` #include "los_interrupt.h" @@ -101,12 +99,10 @@ static UINT32 Example_Interrupt(VOID) UINT32 ret; HWI_PRIOR_T hwiPrio = 3; HWI_MODE_T mode = 0; - HwiIrqParam irqParam; - (void)memset_s(&irqParam, sizeof(HwiIrqParam), 0, sizeof(HwiIrqParam)); - irqParam.pDevId = 0; - + HWI_ARG_T arg = 0; + /*创建中断*/ - ret = LOS_HwiCreate(HWI_NUM_TEST, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, &irqParam); + ret = HalHwiCreate(HWI_NUM_TEST, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, arg); if(ret == LOS_OK){ printf("Hwi create success!\n"); } else { @@ -114,17 +110,11 @@ static UINT32 Example_Interrupt(VOID) return LOS_NOK; } - /*触发中断*/ - ret = LOS_HwiTrigger(HWI_NUM_TEST); - if(ret == LOS_OK){ - printf("Hwi trigger success!\n"); - } else { - printf("Hwi trigger failed!\n"); - return LOS_NOK; - } + /* 延时50个Ticks, 当有硬件中断发生时,会调用函数HwiUsrIrq*/ + LOS_TaskDelay(50); /*删除中断*/ - ret = LOS_HwiDelete(HWI_NUM_TEST); + ret = HalHwiDelete(HWI_NUM_TEST); if(ret == LOS_OK){ printf("Hwi delete success!\n"); } else { @@ -141,9 +131,8 @@ static UINT32 Example_Interrupt(VOID) 编译运行得到的结果为: + ``` Hwi create success! -in the func HwiUsrIrq -Hwi trigger success! Hwi delete success! ``` diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-event.md b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-event.md index 0cf23cf3299a0f2c791e49978dbe85bc6ae76a41..a5ef1e1b97839ab25451bd3080c0c91342bd026e 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-event.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-event.md @@ -1,15 +1,5 @@ # 事件 -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [事件控制块](#事件控制块) - - [事件运作原理](#事件运作原理) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -29,6 +19,7 @@ ### 事件控制块 + ``` /** * 事件控制块数据结构 @@ -60,20 +51,20 @@ typedef struct tagEvent { **事件销毁**:销毁指定的事件控制块。 -**图1** 轻量系统事件运作原理图 -![zh-cn_image_0000001200771972](figures/zh-cn_image_0000001200771972.png) + **图1** 轻量系统事件运作原理图 + ![zh-cn_image_0000001200771972](figures/zh-cn_image_0000001200771972.png) ## 接口说明 -| 功能分类 | 接口名 | 描述 | +| 功能分类 | 接口名 | 描述 | | -------- | -------- | -------- | -| 事件检测 | LOS_EventPoll | 根据eventID,eventMask(事件掩码),mode(事件读取模式),检查用户期待的事件是否发生。
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:**
> 当mode含LOS_WAITMODE_CLR,且用户期待的事件发生时,此时eventID中满足要求的事件会被清零,这种情况下eventID既是入参也是出参。其他情况eventID只作为入参。 | -| 初始化 | LOS_EventInit | 事件控制块初始化。 | -| 事件读 | LOS_EventRead | 读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待;
未读取到事件时,返回值为0;
正常读取到事件时,返回正值(事件发生的集合);
其他情况返回特定错误码。 | -| 事件写 | LOS_EventWrite | 写一个特定的事件到事件控制块。 | -| 事件清除 | LOS_EventClear | 根据events掩码,清除事件控制块中的事件。 | -| 事件销毁 | LOS_EventDestroy | 事件控制块销毁。 | +| 事件检测 | LOS_EventPoll | 根据eventID,eventMask(事件掩码),mode(事件读取模式),检查用户期待的事件是否发生。
 ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:**
 当mode含LOS_WAITMODE_CLR,且用户期待的事件发生时,此时eventID中满足要求的事件会被清零,这种情况下eventID既是入参也是出参。其他情况eventID只作为入参。 | +| 初始化 | LOS_EventInit | 事件控制块初始化。 | +| 事件读 | LOS_EventRead | 读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待;
未读取到事件时,返回值为0;
正常读取到事件时,返回正值(事件发生的集合);
其他情况返回特定错误码。 | +| 事件写 | LOS_EventWrite | 写一个特定的事件到事件控制块。 | +| 事件清除 | LOS_EventClear | 根据events掩码,清除事件控制块中的事件。 | +| 事件销毁 | LOS_EventDestroy | 事件控制块销毁。 | ## 开发流程 @@ -121,6 +112,7 @@ typedef struct tagEvent { 示例代码如下: + ``` #include "los_event.h" #include "los_task.h" @@ -207,6 +199,7 @@ UINT32 Example_TaskEntry(VOID) 编译运行得到的结果为: + ``` Example_Event wait event 0x1 Example_TaskEntry write event. diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex.md b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex.md index 2ade826ed4bd7d3cac587ed7382dca1b3c2cff41..77b90fb2079a1ea453acde1d4a85ec13270de23e 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-mutex.md @@ -1,13 +1,5 @@ # 互斥锁 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -24,20 +16,18 @@ 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 -**图1** 轻量系统互斥锁运作示意图 -![zh-cn_image_0000001245411845](figures/zh-cn_image_0000001245411845.png) + **图1** 轻量系统互斥锁运作示意图 + ![zh-cn_image_0000001245411845](figures/zh-cn_image_0000001245411845.png) ## 接口说明 -**表1** 互斥锁模块接口 + **表1** 互斥锁模块接口 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 互斥锁的创建和删除 | LOS_MuxCreate | 创建互斥锁 | -| | LOS_MuxDelete | 删除指定的互斥锁 | -| 互斥锁的申请和释放 | LOS_MuxPend | 申请指定的互斥锁 | -| | LOS_MuxPost | 释放指定的互斥锁 | +| 功能分类 | 接口描述 | +| -------- | -------- | +| 互斥锁的创建和删除 | LOS_MuxCreate:创建互斥锁
LOS_MuxDelete:删除指定的互斥锁 | +| 互斥锁的申请和释放 | LOS_MuxPend:申请指定的互斥锁
LOS_MuxPost:释放指定的互斥锁 | ## 开发流程 @@ -89,6 +79,7 @@ 示例代码如下: + ``` #include #include "los_mux.h" @@ -193,7 +184,8 @@ UINT32 Example_TaskEntry(VOID) ### 结果验证 -编译运行得到的结果为: + 编译运行得到的结果为: + ``` task2 try to get mutex, wait forever. task2 get mutex g_testMux and suspend 100 ticks. diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-queue.md b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-queue.md index a0c26722dc5d3b20d66207016a9ffb75070f563b..8ee81f8ae61a503796f4710da3d7602c1fd3631f 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-queue.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-queue.md @@ -1,15 +1,5 @@ # 消息队列 -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [队列控制块](#队列控制块) - - [队列运作原理](#队列运作原理) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -41,6 +31,7 @@ ### 队列控制块 + ``` /** * 队列控制块数据结构 @@ -81,25 +72,21 @@ typedef struct - 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 -**图1** 队列读写数据操作示意图 -![zh-cn_image_0000001200452026](figures/zh-cn_image_0000001200452026.png) + **图1** 队列读写数据操作示意图 + + ![zh-cn_image_0000001200452026](figures/zh-cn_image_0000001200452026.png) 上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 ## 接口说明 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 创建/删除消息队列 | LOS_QueueCreate | 创建一个消息队列,由系统动态申请队列空间。 | -| | LOS_QueueDelete | 根据队列ID删除一个指定队列。 | -| 读/写队列(不带拷贝) | LOS_QueueRead | 读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。 | -| | LOS_QueueWrite | 向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)。 | -| | LOS_QueueWriteHead | 向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)。 | -| 读/写队列(带拷贝) | LOS_QueueReadCopy | 读取指定队列头节点中的数据。 | -| | LOS_QueueWriteCopy | 向指定队列尾节点中写入入参bufferAddr中保存的数据。 | -| | LOS_QueueWriteHeadCopy | 向指定队列头节点中写入入参bufferAddr中保存的数据。 | -| 获取队列信息 | LOS_QueueInfoGet | 获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务。 | + | 功能分类 | 接口描述 | +| -------- | -------- | +| 创建/删除消息队列 | - LOS_QueueCreate:创建一个消息队列,由系统动态申请队列空间。
- LOS_QueueDelete:根据队列ID删除一个指定队列。 | +| 读/写队列(不带拷贝) | - LOS_QueueRead:读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。
- LOS_QueueWrite:向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)。
- LOS_QueueWriteHead:向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)。 | +| 读/写队列(带拷贝) | - LOS_QueueReadCopy:读取指定队列头节点中的数据。
- LOS_QueueWriteCopy:向指定队列尾节点中写入入参bufferAddr中保存的数据。
- LOS_QueueWriteHeadCopy:向指定队列头节点中写入入参bufferAddr中保存的数据。 | +| 获取队列信息 | LOS_QueueInfoGet:获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务。 | ## 开发流程 @@ -127,7 +114,7 @@ typedef struct > - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 > > - LOS_QueueReadCopy接口的读取长度如果小于消息实际长度,消息将被截断。 -> +> > - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 @@ -153,6 +140,7 @@ typedef struct 示例代码如下: + ``` #include "los_task.h" #include "los_queue.h" @@ -239,6 +227,7 @@ UINT32 ExampleQueue(VOID) 编译运行得到的结果为: + ``` start queue example. create the queue success. diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-sem.md b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-sem.md index 0e56c02c75e1608bc42d7880b1e8ffef05331256..2fb49adb65c17d90504ac54465011f5099760734 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-sem.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc-sem.md @@ -1,15 +1,5 @@ # 信号量 -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [信号量控制块](#信号量控制块) - - [信号量运作原理](#信号量运作原理) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -33,6 +23,7 @@ ### 信号量控制块 + ``` /** * 信号量控制块数据结构 @@ -42,7 +33,8 @@ typedef struct { UINT16 semType; /* 信号量类型 */ UINT16 semCount; /* 信号量计数 */ UINT16 semId; /* 信号量索引号 */ - LOS_DL_LIST semList; /* 用于插入阻塞于信号量的任务 */} LosSemCB; + LOS_DL_LIST semList; /* 用于插入阻塞于信号量的任务 */ +} LosSemCB; ``` @@ -60,19 +52,16 @@ typedef struct { 信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 -**图1** 轻量系统信号量运作示意图 -![zh-cn_image_0000001245051881](figures/zh-cn_image_0000001245051881.png) + **图1** 轻量系统信号量运作示意图 + ![zh-cn_image_0000001245051881](figures/zh-cn_image_0000001245051881.png) ## 接口说明 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 创建/删除信号量 | LOS_SemCreate | 创建信号量,返回信号量ID | -| | LOS_BinarySemCreate | 创建二值信号量,其计数值最大为1 | -| | LOS_SemDelete | 删除指定的信号量 | -| 申请/释放信号量 | LOS_SemPend | 申请指定的信号量,并设置超时时间 | -| | LOS_SemPost | 释放指定的信号量 | + | 功能分类 | 接口描述 | +| -------- | -------- | +| 创建/删除信号量 | - LOS_SemCreate:创建信号量,返回信号量ID
- LOS_BinarySemCreate:创建二值信号量,其计数值最大为1
- LOS_SemDelete:删除指定的信号量 | +| 申请/释放信号量 | - LOS_SemPend:申请指定的信号量,并设置超时时间
- LOS_SemPost:释放指定的信号量 | ## 开发流程 @@ -97,7 +86,7 @@ typedef struct { 本实例实现如下功能: -1. 测试任务ExampleSem创建一个信号量,锁任务调度,创建两个任务ExampleSemTask1、ExampleSemTask2, ExampleSemTask2优先级高于ExampleSemTask1,两个任务中申请同一信号量,解锁任务调度后两任务阻塞,测试任务ExampleSem释放信号量。 +1. 测试任务ExampleSem创建一个信号量,锁任务调度。创建两个任务ExampleSemTask1和ExampleSemTask2, ExampleSemTask2优先级高于ExampleSemTask1。两个任务中申请同一信号量,解锁任务调度后两任务阻塞,测试任务ExampleSem释放信号量。 2. ExampleSemTask2得到信号量,被调度,然后任务休眠20Tick,ExampleSemTask2延迟,ExampleSemTask1被唤醒。 @@ -112,6 +101,7 @@ typedef struct { 示例代码如下: + ``` #include "los_sem.h" #include "securec.h" @@ -231,6 +221,7 @@ UINT32 ExampleSem(VOID) 编译运行得到的结果为: + ``` ExampleSemTask2 try get sem g_semId wait forever. ExampleSemTask2 get sem g_semId and then delay 20 ticks. diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc.md b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc.md index e733e292f6d065daebf101b32d4405238118fa8b..b99e8083c463b204b48c8c24a711dc7f82a38331 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-ipc.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-ipc.md @@ -1,6 +1,7 @@ # 内核通信机制 + - **[事件](kernel-mini-basic-ipc-event.md)** - **[互斥锁](kernel-mini-basic-ipc-mutex.md)** diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-basic.md b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-basic.md index 23abc39d28ad780c93ad3076b2890ed42f860846..f932bc8fc6e0adf41a081640c338f1cd2a337b9a 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-basic.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-basic.md @@ -1,5 +1,6 @@ # 基本概念 + 内存管理模块管理系统的内存资源,它是操作系统的核心模块之一,主要包括内存的初始化、分配以及释放。 diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md index 4b50b4216bcfd0791bc7158abb8718df30f0be1f..195a2bc100783100d863317ebe9b075cc6694b4b 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-dynamic.md @@ -1,12 +1,5 @@ # 动态内存 -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [使用场景](#使用场景) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [结果验证](#结果验证) ## 运行机制 @@ -14,10 +7,10 @@ OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: -**图1** 轻量系统动态内存核心算法 -![zh-cn_image_0000001199352445](figures/zh-cn_image_0000001199352445.png) + **图1** 轻量系统动态内存核心算法 + ![zh-cn_image_0000001199352445](figures/zh-cn_image_0000001199352445.png) -$$根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[2^{7}$, 2^{31}$],如上图size class所示: +根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[27, 231],如上图size class所示: 1. 对[4,127]区间的内存进行等分,如上图下半部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。[4,127]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 @@ -27,8 +20,8 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 内存管理结构如下图所示: -**图2** 轻量系统动态内存管理结构图 -![zh-cn_image_0000001153313284](figures/zh-cn_image_0000001153313284.png) + **图2** 轻量系统动态内存管理结构图 + ![zh-cn_image_0000001153313284](figures/zh-cn_image_0000001153313284.png) - 内存池池头部分 内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。 @@ -38,8 +31,8 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 一些芯片片内RAM大小无法满足要求,需要使用片外物理内存进行扩充。对于这样的多段非连续性内存, LiteOS-M内核支持把多个非连续性内存逻辑上合一,用户不感知底层的多段非连续性内存区域。 LiteOS-M内核内存模块把不连续的内存区域作为空闲内存结点插入到空闲内存节点链表,把不同内存区域间的不连续部分标记为虚拟的已使用内存节点,从逻辑上把多个非连续性内存区域实现为一个统一的内存池。下面通过示意图说明下多段非连续性内存的运行机制: -**图3** 非连续性内存合一示意图 -![zh-cn_image_0000001198253551](figures/zh-cn_image_0000001198253551.png) + **图3** 非连续性内存合一示意图 + ![zh-cn_image_0000001198253551](figures/zh-cn_image_0000001198253551.png) 结合上述示意图,非连续性内存合并为一个统一的内存池的步骤如下: @@ -66,24 +59,16 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 -**表1** 动态内存模块接口 - -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 初始化和删除内存池 | LOS_MemInit | 初始化一块指定的动态内存池,大小为size。 | -| | LOS_MemDeInit | 删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。 | -| 申请、释放动态内存 | LOS_MemAlloc | 从指定动态内存池中申请size长度的内存。 | -| | LOS_MemFree | 释放从指定动态内存中申请的内存。 | -| | LOS_MemRealloc | 按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块。 | -| | LOS_MemAllocAlign | 从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。 | -| 获取内存池信息 | LOS_MemPoolSizeGet | 获取指定动态内存池的总大小。 | -| | LOS_MemTotalUsedGet | 获取指定动态内存池的总使用量大小。 | -| | LOS_MemInfoGet | 获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。 | -| | LOS_MemPoolList | 打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。 | -| 获取内存块信息 | LOS_MemFreeNodeShow | 打印指定内存池的空闲内存块的大小及数量。 | -| | LOS_MemUsedNodeShow | 打印指定内存池的已使用内存块的大小及数量。 | -| 检查指定内存池的完整性 | LOS_MemIntegrityCheck | 对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。 | -| 增加非连续性内存区域 | LOS_MemRegionsAdd | 支持多段非连续性内存区域,把非连续性内存区域逻辑上整合为一个统一的内存池。仅打开LOSCFG_MEM_MUL_REGIONS时有效。如果内存池指针参数pool为空,则使用多段内存的第一个初始化为内存池,其他内存区域,作为空闲节点插入;如果内存池指针参数pool不为空,则把多段内存作为空闲节点,插入到指定的内存池。 | + **表1** 动态内存模块接口 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 初始化和删除内存池 | - LOS_MemInit:初始化一块指定的动态内存池,大小为size。
- LOS_MemDeInit:删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。 | +| 申请、释放动态内存 | - LOS_MemAlloc:从指定动态内存池中申请size长度的内存。
- LOS_MemFree:释放从指定动态内存中申请的内存。
- LOS_MemRealloc:释放从指定动态内存中申请的内存。 | +| 获取内存池信息 | - LOS_MemPoolSizeGet:获取指定动态内存池的总大小。
- LOS_MemTotalUsedGet:获取指定动态内存池的总使用量大小。
- LOS_MemInfoGet:获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。
- LOS_MemPoolList:打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。 | +| 获取内存块信息 | - LOS_MemFreeNodeShow:打印指定内存池的空闲内存块的大小及数量。
- LOS_MemUsedNodeShow:打印指定内存池的已使用内存块的大小及数量。 | +| 检查指定内存池的完整性 | LOS_MemIntegrityCheck:对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。 | +| 增加非连续性内存区域 | LOS_MemRegionsAdd:支持多段非连续性内存区域,把非连续性内存区域逻辑上整合为一个统一的内存池。仅打开LOSCFG_MEM_MUL_REGIONS时有效。如果内存池指针参数pool为空,则使用多段内存的第一个初始化为内存池,其他内存区域,作为空闲节点插入;如果内存池指针参数pool不为空,则把多段内存作为空闲节点,插入到指定的内存池。 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > - 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS_SYS_MEM_SIZE的大小。 @@ -123,6 +108,7 @@ OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接 示例代码如下: + ``` #include "los_memory.h" #define TEST_POOL_SIZE (2*1024) @@ -170,6 +156,7 @@ VOID Example_DynMem(VOID) 输出结果如下: + ``` Mem init success! Mem alloc success! diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-static.md b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-static.md index b4007c0e108eaff2ef24fafb7bdcc229be5cee00..d9d5128a423d956503e01c9ebf6f12f443d86bf9 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-memory-static.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-memory-static.md @@ -1,12 +1,5 @@ # 静态内存 -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [使用场景](#使用场景) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [结果验证](#结果验证) ## 运行机制 @@ -14,8 +7,8 @@ 静态内存池由一个控制块LOS_MEMBOX_INFO和若干相同大小的内存块LOS_MEMBOX_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。 -**图1** 静态内存示意图 -![zh-cn_image_0000001199352039](figures/zh-cn_image_0000001199352039.png) + **图1** 静态内存示意图 + ![zh-cn_image_0000001199352039](figures/zh-cn_image_0000001199352039.png) ## 开发指导 @@ -30,16 +23,14 @@ OpenHarmony LiteOS-M的静态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 -**表1** 静态内存模块接口 + **表1** 静态内存模块接口 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 初始化静态内存池 | LOS_MemboxInit | 初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小。 | -| 清除静态内存块内容 | LOS_MemboxClr | 清零从静态内存池中申请的静态内存块的内容。 | -| 申请、释放静态内存 | LOS_MemboxAlloc | 从指定的静态内存池中申请一块静态内存块。 | -| | LOS_MemboxFree | 释放从静态内存池中申请的一块静态内存块。 | -| 获取、打印静态内存池信息 | LOS_MemboxStatisticsGet | 获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小。 | -| | LOS_ShowBox | 打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址。 | +| 功能分类 | 接口名 | +| -------- | -------- | +| 初始化静态内存池 | LOS_MemboxInit:初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小。 | +| 清除静态内存块内容 | LOS_MemboxClr:清零从静态内存池中申请的静态内存块的内容。 | +| 申请、释放静态内存 | - LOS_MemboxAlloc:从指定的静态内存池中申请一块静态内存块。
- LOS_MemboxFree:释放从静态内存池中申请的一块静态内存块。 | +| 获取、打印静态内存池信息 | - LOS_MemboxStatisticsGet:获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小。
- LOS_ShowBox:打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址。 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 初始化后的内存池的内存块数量,不等于总大小除于内存块大小,因为内存池的控制块和每个内存块的控制头,都存在内存开销,设置总大小时,需要将这些因素考虑进去。 @@ -81,6 +72,7 @@ OpenHarmony LiteOS-M的静态内存管理主要为用户提供以下功能,接 6. 释放该内存块。 示例代码如下: + ``` #include "los_membox.h" @@ -134,6 +126,7 @@ VOID Example_StaticMem(VOID) 输出结果如下: + ``` Membox init success! Mem alloc success! diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-memory.md b/zh-cn/device-dev/kernel/kernel-mini-basic-memory.md index 39ee73a31e1999627805cdd97b45bd3c7c278f41..afc518c52ce6037e598cad7b54a883c0f8c7e6eb 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-memory.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-memory.md @@ -1,6 +1,7 @@ # 内存管理 + - **[基本概念](kernel-mini-basic-memory-basic.md)** - **[静态内存](kernel-mini-basic-memory-static.md)** diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-soft.md b/zh-cn/device-dev/kernel/kernel-mini-basic-soft.md index 723229aafc62bef794580322fc26871adf8ed15c..6f20e088249eda9620ddab7c45302f3a6c934538 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-soft.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-soft.md @@ -1,15 +1,5 @@ # 软件定时器 -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [定时器状态](#定时器状态) - - [定时器模式](#定时器模式) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -72,15 +62,13 @@ OpenHarmony LiteOS-M内核的软件定时器提供三类定时器机制: OpenHarmony LiteOS-M内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 软件定时器接口 + **表1** 软件定时器接口 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 创建、删除定时器 | LOS_SwtmrCreate | 创建定时器 | -| | LOS_SwtmrDelete | 删除定时器 | -| 启动、停止定时器 | LOS_SwtmrStart | 启动定时器 | -| | LOS_SwtmrStop | 停止定时器 | -| 获得软件定时器剩余Tick数 | LOS_SwtmrTimeGet | 获得软件定时器剩余Tick数 | +| 功能分类 | p接口描述 | +| -------- | -------- | +| 创建、删除定时器 | - LOS_SwtmrCreate:创建定时器
- LOS_SwtmrDelete:删除定时器 | +| 启动、停止定时器 | - LOS_SwtmrStart:启动定时器
- LOS_SwtmrStop:停止定时器 | +| 获得软件定时器剩余Tick数 | LOS_SwtmrTimeGet:获得软件定时器剩余Tick数 | ## 开发流程 @@ -142,6 +130,7 @@ OpenHarmony LiteOS-M内核的软件定时器模块提供下面几种功能,接 代码实现如下: + ``` #include "los_swtmr.h" @@ -238,6 +227,7 @@ UINT32 Example_TaskEntry(VOID) 编译烧录运行,输出结果如下: + ``` create Timer1 success start Timer1 success diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic-task.md b/zh-cn/device-dev/kernel/kernel-mini-basic-task.md index 97074adc9157f988de2971b71a9066abee05f444..2c08aa3eaad41bf1cb1a447b01cf4b7e9a887def 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic-task.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic-task.md @@ -1,12 +1,5 @@ # 任务管理 -- [基本概念](#基本概念) - - [任务相关概念](#任务相关概念) - - [任务运行机制](#任务运行机制) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [结果验证](#结果验证) ## 基本概念 @@ -43,8 +36,9 @@ OpenHarmony LiteOS-M的任务模块可以给用户提供多个任务,实现任 **任务状态迁移** -**图1** 任务状态示意图 -![zh-cn_image_0000001200612002](figures/zh-cn_image_0000001200612002.png) + **图1** 任务状态示意图 + + ![zh-cn_image_0000001200612002](figures/zh-cn_image_0000001200612002.png) **任务状态迁移说明:** @@ -107,36 +101,16 @@ OpenHarmony LiteOS-M的任务模块可以给用户提供多个任务,实现任 OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 任务管理模块接口 - -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 创建和删除任务 | LOS_TaskCreateOnly | 创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态。 | -| | LOS_TaskCreate | 创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。 | -| | LOS_TaskDelete | 删除指定的任务。 | -| 控制任务状态 | LOS_TaskResume | 恢复挂起的任务,使该任务进入ready状态。 | -| | LOS_TaskSuspend | 挂起指定的任务,然后切换任务。 | -| | LOS_TaskJoin | 挂起当前任务,等待指定任务运行结束并回收其任务控制块资源。 | -| | LOS_TaskDetach | 修改任务的joinable属性为detach属性,detach属性的任务运行结束会自动回收任务控制块资源。 | -| | LOS_TaskDelay | 任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。 | -| | LOS_Msleep | 传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。 | -| | LOS_TaskYield | 当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。 | -| 控制任务调度 | LOS_TaskLock | 锁任务调度,但任务仍可被中断打断。 | -| | LOS_TaskUnlock | 解锁任务调度。 | -| | LOS_Schedule | 触发任务调度。 | -| 控制任务优先级 | LOS_CurTaskPriSet | 设置当前任务的优先级。 | -| | LOS_TaskPriSet | 设置指定任务的优先级。 | -| | LOS_TaskPriGet | 获取指定任务的优先级。 | -| 获取任务信息 | LOS_CurTaskIDGet | 获取当前任务的ID。 | -| | LOS_NextTaskIDGet | 获取任务就绪队列中优先级最高的任务的ID。 | -| | LOS_NewTaskIDGet | 等同LOS_NextTaskIDGet。 | -| | LOS_CurTaskNameGet | 获取当前任务的名称。 | -| | LOS_TaskNameGet | 获取指定任务的名称。 | -| | LOS_TaskStatusGet | 获取指定任务的状态。 | -| | LOS_TaskInfoGet | 获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。 | -| | LOS_TaskIsRunning | 获取任务模块是否已经开始调度运行。 | -| 任务信息维测 | LOS_TaskSwitchInfoGet | 获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。 | -| 回收任务栈资源 | LOS_TaskResRecycle | 回收所有待回收的任务栈资源。 | + **表1** 任务管理模块接口 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 创建和删除任务 | LOS_TaskCreateOnly:创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。
LOS_TaskCreate:创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。
LOS_TaskDelete:删除指定的任务。 | +| 控制任务状态 | LOS_TaskResume:恢复挂起的任务,使该任务进入ready状态。
LOS_TaskSuspend:挂起指定的任务,然后切换任务。
LOS_TaskJoin:挂起当前任务,等待指定任务运行结束并回收其任务控制块资源
LOS_TaskDelay:任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。
LOS_Msleep:传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。
LOS_TaskYield:当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。 | +| 控制任务调度 | LOS_TaskLock:锁任务调度,但任务仍可被中断打断。
LOS_TaskUnlock:解锁任务调度。
LOS_Schedule:触发任务调度。 | +| 控制任务优先级 | LOS_CurTaskPriSet:设置当前任务的优先级。
LOS_TaskPriSet:设置指定任务的优先级。
LOS_TaskPriGet:获取指定任务的优先级。 | +| 获取任务信息 | LOS_CurTaskIDGet:获取当前任务的ID。
LOS_NextTaskIDGet:获取任务就绪队列中优先级最高的任务的ID。
LOS_NewTaskIDGet:等同LOS_NextTaskIDGet。
LOS_CurTaskNameGet:获取当前任务的名称。
LOS_TaskNameGet:获取指定任务的名称。
LOS_TaskStatusGet:获取指定任务的状态。
LOS_TaskInfoGet:获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。
LOS_TaskIsRunning:获取任务模块是否已经开始调度运行。 | +| 任务信息维测 | LOS_TaskSwitchInfoGet:获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。 | ## 开发流程 @@ -187,6 +161,7 @@ OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口 本实例介绍基本的任务操作方法,包含2个不同优先级任务的创建、任务延时、任务锁与解锁调度、挂起和恢复等操作,阐述任务优先级调度的机制以及各接口的应用。示例代码如下: + ``` UINT32 g_taskHiId; UINT32 g_taskLoId; @@ -304,6 +279,7 @@ UINT32 Example_TskCaseEntry(VOID) 编译运行得到的结果为: + ``` LOS_TaskLock() Success! Example_TaskHi create Success! diff --git a/zh-cn/device-dev/kernel/kernel-mini-basic.md b/zh-cn/device-dev/kernel/kernel-mini-basic.md index 0d44f0cb00f55194f3df263ed1f0846838bb2635..84d2ef47a5229233c419ad55442a1aae81ba0693 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-basic.md +++ b/zh-cn/device-dev/kernel/kernel-mini-basic.md @@ -1,6 +1,7 @@ # 基础内核 + - **[中断管理](kernel-mini-basic-interrupt.md)** - **[任务管理](kernel-mini-basic-task.md)** diff --git a/zh-cn/device-dev/kernel/kernel-mini-debug.md b/zh-cn/device-dev/kernel/kernel-mini-debug.md index 5a847c2509cc93b478bf59bc6ee2bdb68c61a09a..6e9c0f662f4966801cc2524cc39f1179f7e3ade8 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-debug.md +++ b/zh-cn/device-dev/kernel/kernel-mini-debug.md @@ -1,6 +1,7 @@ # 内核调测 + - **[内存调测](kernel-mini-memory-debug.md)** - **[异常调测](kernel-mini-memory-exception.md)** diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-cpup.md b/zh-cn/device-dev/kernel/kernel-mini-extend-cpup.md index c2aaf7f4c8ce85eb6724494215cba8d41f895bc4..9c5831f228d0ab6a019f7c022bb7d345dd3bbd9b 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-cpup.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-cpup.md @@ -1,13 +1,5 @@ # CPU占用率 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) -- [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -43,16 +35,13 @@ OpenHarmony LiteOS-M提供以下两种CPU占用率的信息查询: ## 接口说明 -**表1** 功能列表 + **表1** 功能列表 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 获取系统CPU占用率 | LOS_SysCpuUsage | 获取当前系统CPU占用率 | -| | LOS_HistorySysCpuUsage | 获取系统历史CPU占用率 | -| 获取任务CPU占用率 | LOS_TaskCpuUsage | 获取指定任务CPU占用率 | -| | LOS_HistoryTaskCpuUsage | 获取指定任务历史CPU占用率 | -| | LOS_AllCpuUsage | 获取所有任务CPU占用率 | -| 输出任务CPU占用率 | LOS_CpupUsageMonitor | 输出任务历史CPU占用率 | +| 功能分类 | 接口描述 | +| -------- | -------- | +| 获取系统CPU占用率 | - LOS_SysCpuUsage:获取当前系统CPU占用率
- LOS_HistorySysCpuUsage:获取系统历史CPU占用率 | +| 获取任务CPU占用率 | - LOS_TaskCpuUsage:获取指定任务CPU占用率
- LOS_HistoryTaskCpuUsage:获取指定任务历史CPU占用率
- LOS_HistoryTaskCpuUsage:获取指定任务历史CPU占用率 | +| 输出任务CPU占用率 | LOS_CpupUsageMonitor:输出任务历史CPU占用率 | ## 开发流程 @@ -102,6 +91,7 @@ CPU占用率的典型开发流程: 代码实现如下: + ``` #include "los_task.h" #include "los_cpup.h" @@ -155,7 +145,8 @@ UINT32 ItCpupTest(VOID) ### 结果验证 -编译运行得到的结果为: + 编译运行得到的结果为: + ``` entry cpup test example the current system cpu usage is : 1.5 diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading.md b/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading.md index fd952435e7384edb43ce410368a2cbdffebdf177..4c5ad0d8b4d6e094f3ce4ec070e68d3e81b6d992 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-dynamic-loading.md @@ -1,20 +1,12 @@ # 动态加载 -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [符号表导出](#符号表导出) - - [ELF文件加载](#elf文件加载) - - [ELF文件链接](#elf文件链接) -- [ELF支持规格](#elf支持规格) - - [ELF支持类型](#elf支持类型) - - [ELF共享库编译链接选项](#elf共享库编译链接选项) ## 基本概念 在硬件资源有限的小设备中,需要通过算法的动态部署能力来解决无法同时部署多种算法的问题。以开发者易用为主要考虑因素,同时考虑到多平台的通用性,LiteOS-M选择业界标准的ELF加载方案,方便拓展算法生态。LiteOS-M提供类似于dlopen、dlsym等接口,APP通过动态加载模块提供的接口可以加载、卸载相应算法库。如图1所示,APP需要通过三方算法库所需接口获取对应信息输出,三方算法库又依赖内核提供的基本接口,如malloc等。APP加载所需接口,并对相关的未定义符号完成重定位后,APP即可调用该接口完成功能调用。目前动态加载组件只支持arm架构。此外,待加载的共享库需要验签或者限制来源,确保系统的安全性。 -**图1** LiteOS-M内核动态加载架构图 -![zh-cn_image_0000001200292052](figures/zh-cn_image_0000001200292052.png) + **图1** LiteOS-M内核动态加载架构图 + ![zh-cn_image_0000001200292052](figures/zh-cn_image_0000001200292052.png) ## 运行机制 @@ -24,6 +16,7 @@ 共享库调用内核接口需要内核主动暴露动态库所需的接口,如图2所示,该机制将符号信息编译到指定段中,调用SYM_EXPORT宏即可完成对指定符号的信息导出。符号信息通过结构体SymInfo描述,成员包括符号名和符号地址信息,宏SYM_EXPORT通过__attribute__编译属性将符号信息导入.sym.\*段中。 + ``` typedef struct { CHAR *name; @@ -37,14 +30,16 @@ const SymInfo sym_##func __attribute__((section(".sym."#func))) = { \ }; ``` -**图2** 导出的符号表信息 -![zh-cn_image_0000001245171875](figures/zh-cn_image_0000001245171875.png) + **图2** 导出的符号表信息 + + ![zh-cn_image_0000001245171875](figures/zh-cn_image_0000001245171875.png) ### ELF文件加载 加载过程中,根据ELF文件的句柄以及程序头表的段偏移可以得到需要加载到内存的LOAD段,一般有两个段,只读段及读写段,如下所示,可以用readelf -l查看ELF文件的LOAD段信息。如图3所示,根据相应的对齐属性申请物理内存,通过每个段的加载基址及偏移将代码段或数据段写入内存中。 + ``` $ readelf -l lib.so @@ -66,16 +61,17 @@ Program Headers: 03 .dynamic ``` -**图3** ELF文件的加载过程 -![zh-cn_image_0000001245251887](figures/zh-cn_image_0000001245251887.png) + **图3** ELF文件的加载过程 + ![zh-cn_image_0000001245251887](figures/zh-cn_image_0000001245251887.png) ### ELF文件链接 如图4所示,通过ELF文件的.dynamic段获取重定位表,遍历表中每一个需要重定位的条目,再根据需要重定位的符号名在共享库和内核提供的导出符号表中查找相应符号并更新相应的重定位信息。 -**图4** ELF文件的链接过程 -![zh-cn_image_0000001200612006](figures/zh-cn_image_0000001200612006.png) + **图4** ELF文件的链接过程 + + ![zh-cn_image_0000001200612006](figures/zh-cn_image_0000001200612006.png) ## ELF支持规格 diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-file-fat.md b/zh-cn/device-dev/kernel/kernel-mini-extend-file-fat.md index 3a05c20766c7ff62ca94828b8a8236be4f2c79d2..d6d183f8bc5ae0324aaaed77f367963097408d3f 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-file-fat.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-file-fat.md @@ -1,13 +1,5 @@ # FAT -- [基本概念](#基本概念) -- [开发指导](#开发指导) - - [驱动适配](#驱动适配) - - [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -27,6 +19,7 @@ FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC 2、新增fs_config.h文件,配置FS_MAX_SS(存储设备最大sector大小)、FF_VOLUME_STRS(分区名)等信息,例如: + ``` #define FF_VOLUME_STRS "system", "inner", "update", "user" #define FS_MAX_SS 512 @@ -90,7 +83,8 @@ FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC - 系统已将MMC设备分区挂载到user目录 -代码实现如下: + 代码实现如下: + ``` #include #include @@ -185,6 +179,7 @@ int FatfsTest(void) 编译运行得到的结果为: + ``` Hello OpenHarmony! ``` diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-file-lit.md b/zh-cn/device-dev/kernel/kernel-mini-extend-file-lit.md index f3676d2056f9f2ed831b9d0f28a245c05927e701..be7172df9b76cb985c47322d92780c8b036c40a6 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-file-lit.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-file-lit.md @@ -1,9 +1,5 @@ # LittleFS -- [基本概念](#基本概念) -- [开发指导](#开发指导) -- [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -16,6 +12,7 @@ LittleFS是一个小型的Flash文件系统,它结合日志结构(log-struct 移植LittleFS到新硬件设备上,需要申明lfs_config: + ``` const struct lfs_config cfg = { // block device operations @@ -48,7 +45,8 @@ block_count 可以被擦除的块数量,这取决于块设备的容量及擦 ## 示例代码 -代码实现如下: + 代码实现如下: + ``` #include "lfs.h" #include "stdio.h" @@ -100,6 +98,7 @@ int main(void) { 首次编译运行得到的结果为: + ``` Say hello 1 times. ``` diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-file.md b/zh-cn/device-dev/kernel/kernel-mini-extend-file.md index 6eeb25d0f5c76b9bf37a2293db937bf6c23a9555..65e95f800c497f322f28bc990c0665978e7580bf 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-file.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-file.md @@ -1,31 +1,44 @@ # 文件系统 + M核的文件系统子系统当前支持的文件系统有FATFS与LittleFS。同A核一样,通过VFS层提供了POSIX标准的操作,保持了接口的一致性,但是因为M核的资源非常紧张,VFS层非常轻薄,没有提供类似A核的高级功能(如pagecache等),主要是接口的标准化和适配工作,具体的事务由各个文件系统实际承载。M核文件系统支持的功能如下表所示: -**表1** 功能列表 - -| 功能分类 | 接口名 | 描述 | FATFS | LITTLEFS | -| -------- | -------- | -------- | -------- | -------- | -| 文件操作 | open | 打开文件 | 支持 | 支持 | -| | close | 关闭文件 | 支持 | 支持 | -| | read | 读取文件内容 | 支持 | 支持 | -| | write | 往文件写入内容 | 支持 | 支持 | -| | lseek | 设置文件偏移位置 | 支持 | 支持 | -| | unlink | 删除文件 | 支持 | 支持 | -| | rename | 重命名文件 | 支持 | 支持 | -| | fstat | 通过文件句柄获取文件信息 | 支持 | 支持 | -| | stat | 通过文件路径名获取文件信息 | 支持 | 支持 | -| | fsync | 文件内容刷入存储设备 | 支持 | 支持 | -| 目录操作 | mkdir | 创建目录 | 支持 | 支持 | -| | opendir | 打开目录 | 支持 | 支持 | -| | readdir | 读取目录项内容 | 支持 | 支持 | -| | closedir | 关闭目录 | 支持 | 支持 | -| | rmdir | 删除目录 | 支持 | 支持 | -| 分区操作 | mount | 分区挂载 | 支持 | 支持 | -| | umount | 分区卸载 | 支持 | 支持 | -| | umount2 | 分区卸载,可通过MNT_FORCE参数进行强制卸载 | 支持 | 不支持 | -| | statfs | 获取分区信息 | 支持 | 不支持 | + **表1** 文件操作 + +| 接口名 | 描述 | FATFS | LITTLEFS | +| -------- | -------- | -------- | -------- | +| open | 打开文件 | 支持 | 支持 | +| close | 关闭文件 | 支持 | 支持 | +| read | 读取文件内容 | 支持 | 支持 | +| write | 往文件写入内容 | 支持 | 支持 | +| lseek | 设置文件偏移位置 | 支持 | 支持 | +| unlink | 删除文件 | 支持 | 支持 | +| rename | 重命名文件 | 支持 | 支持 | +| fstat | 通过文件句柄获取文件信息 | 支持 | 支持 | +| stat | 通过文件路径名获取文件信息 | 支持 | 支持 | +| fsync | 文件内容刷入存储设备 | 支持 | 支持 | + + + **表2** 目录操作 + +| 接口名 | 描述 | FATFS | LITTLEFS | +| -------- | -------- | -------- | -------- | +| mkdir | 创建目录 | 支持 | 支持 | +| opendir | 打开目录 | 支持 | 支持 | +| readdir | 读取目录项内容 | 支持 | 支持 | +| closedir | 关闭目录 | 支持 | 支持 | +| rmdir | 删除目录 | 支持 | 支持 | + + + **表3** 分区操作 + +| 接口名 | 描述 | FATFS | LITTLEFS | +| -------- | -------- | -------- | -------- | +| mount | 分区挂载 | 支持 | 支持 | +| umount | 分区卸载 | 支持 | 支持 | +| umount2 | 分区卸载,可通过MNT_FORCE参数进行强制卸载 | 支持 | 不支持 | +| statfs | 获取分区信息 | 支持 | 不支持 | - **[FAT](kernel-mini-extend-file-fat.md)** diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend-support.md b/zh-cn/device-dev/kernel/kernel-mini-extend-support.md index 8213dc8dca9553426516461d6bf09154685a0c16..329d3ee32d8ca6bff71ec983602f2615ab648af2 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-support.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-support.md @@ -1,11 +1,5 @@ # C++支持 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -22,7 +16,7 @@ C++代码的识别主要由编译器支持,系统主要对全局对象进行 ### 接口说明 -**表1** C++支持接口 + **表1** C++支持接口 | 功能分类 | 接口名 | 描述 | | -------- | -------- | -------- | @@ -33,7 +27,7 @@ C++代码的识别主要由编译器支持,系统主要对全局对象进行 使用C++特性之前,需要调用函数LOS_CppSystemInit,实现C++构造函数初始化,其中被初始化的构造函数存在init_array这个段中,段区间通过变量__init_array_start__、__init_array_end__传递。 -**表2** 参数说明 + **表2** 参数说明 | 参数 | 参数说明 | | -------- | -------- | @@ -46,6 +40,7 @@ C++代码的识别主要由编译器支持,系统主要对全局对象进行 ### 编程实例 + ``` void app_init(void) { diff --git a/zh-cn/device-dev/kernel/kernel-mini-extend.md b/zh-cn/device-dev/kernel/kernel-mini-extend.md index b9e0d97ba5a0ef62dae869beee9ff66d271806ce..fb0b5fedacf21e2b220592b24e188020f738c31a 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend.md @@ -1,6 +1,7 @@ # 扩展组件 + - **[C++支持](kernel-mini-extend-support.md)** - **[CPU占用率](kernel-mini-extend-cpup.md)** diff --git a/zh-cn/device-dev/kernel/kernel-mini-imemory-debug-det.md b/zh-cn/device-dev/kernel/kernel-mini-imemory-debug-det.md index 09971dd3ba8df6e0dc199fdf0609016fee328aac..5c074926a9163f0561d11a662a629e9801ec0dff 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-imemory-debug-det.md +++ b/zh-cn/device-dev/kernel/kernel-mini-imemory-debug-det.md @@ -1,12 +1,5 @@ # 内存泄漏检测 -- [基础概念](#基础概念) -- [功能配置](#功能配置) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基础概念 @@ -36,6 +29,7 @@ 调用LOS_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 + ``` node size LR[0] LR[1] LR[2] 0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 @@ -69,6 +63,7 @@ node size LR[0] LR[1] LR[2] 代码实现如下: + ``` #include #include @@ -89,6 +84,7 @@ void MemLeakTest(void) 编译运行输出log如下: + ``` node size LR[0] LR[1] LR[2] 0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc @@ -109,6 +105,7 @@ node size LR[0] LR[1] LR[2] 对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: + ``` 0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 @@ -116,6 +113,7 @@ node size LR[0] LR[1] LR[2] 部分汇编文件如下: + ``` MemLeakTest: 0x80041d4: 0xb510 PUSH {R4, LR} diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-debug-cet.md b/zh-cn/device-dev/kernel/kernel-mini-memory-debug-cet.md index 0e44b1e34853ed016762eee5a8ffbee73c152d8f..82035f33281eac451dd5f9ac57a142954b633b31 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-debug-cet.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-debug-cet.md @@ -1,12 +1,5 @@ # 踩内存检测 -- [基础概念](#基础概念) -- [功能配置](#功能配置) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基础概念 @@ -50,6 +43,7 @@ LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK:开关宏,默认关闭;若打开这 代码实现如下: + ``` #include #include @@ -72,6 +66,7 @@ void MemIntegrityTest(void) 编译运行输出log如下: + ``` [ERR][OsMemMagicCheckPrint], 2028, memory check error! memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-debug-mes.md b/zh-cn/device-dev/kernel/kernel-mini-memory-debug-mes.md index 8d6325dc6b915c0e21904ea48090c054667786d8..3d08d11be21b6a6644c184265f26c12807164a2c 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-debug-mes.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-debug-mes.md @@ -1,12 +1,5 @@ # 内存信息统计 -- [基础概念](#基础概念) -- [功能配置](#功能配置) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基础概念 @@ -31,6 +24,7 @@ LOSCFG_MEM_WATERLINE:开关宏,默认打开;若关闭这个功能,在tar 关键结构体介绍: + ``` typedef struct { UINT32 totalUsedSize; // 内存池的内存使用量 @@ -62,7 +56,8 @@ typedef struct { ### 示例代码 -代码实现如下: + 代码实现如下: + ``` #include #include @@ -109,6 +104,7 @@ int MemTest(void) 编译运行输出的结果如下: + ``` usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 ``` diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-debug.md b/zh-cn/device-dev/kernel/kernel-mini-memory-debug.md index d3e4753307214cffd9e903b54e34f0ce1c6938b1..5f9fc38eb4110569e4980f49a46b3b0e09c2cd4e 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-debug.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-debug.md @@ -1,5 +1,6 @@ # 内存调测 + 内存调测方法旨在辅助定位动态内存相关问题,提供了基础的动态内存池信息统计手段,向用户呈现内存池水线、碎片率等信息;提供了内存泄漏检测手段,方便用户准确定位存在内存泄漏的代码行,也可以辅助分析系统各个模块内存的使用情况;提供了踩内存检测手段,可以辅助定位越界踩内存的场景。 diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-exception.md b/zh-cn/device-dev/kernel/kernel-mini-memory-exception.md index 48cde4d8703c9b6eb87cddb9d90819a9d3a63b80..d3efbaeff1c9c45b5d0390bf448070ca47790cd2 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-exception.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-exception.md @@ -1,11 +1,5 @@ # 异常调测 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) -- [使用指导](#使用指导) - - [开发流程](#开发流程) - - [定位流程](#定位流程) ## 基本概念 @@ -20,8 +14,8 @@ OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析 堆栈分析原理如下图所示,实际堆栈信息根据不同CPU架构有所差异,此处仅做示意。 -**图1** 堆栈分析原理示意图 -![zh-cn_image_0000001132936268](figures/zh-cn_image_0000001132936268.png) + **图1** 堆栈分析原理示意图 + ![zh-cn_image_0000001132936268](figures/zh-cn_image_0000001132936268.png) 图中不同颜色的寄存器表示不同的函数。可以看到函数调用过程中,寄存器的保存。通过FP寄存器,栈回溯到异常函数的父函数,继续按照规律对栈进行解析,推出函数调用关系,方便用户定位问题。 @@ -30,12 +24,11 @@ OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析 OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 回溯栈模块接口 + **表1** 回溯栈模块接口 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 回溯栈接口 | LOS_BackTrace | 打印调用处的函数调用栈关系。 | -| | LOS_RecordLR | 在无法打印的场景,用该接口获取调用处的函数调用栈关系。 | +| 功能分类 | 接口名 | +| -------- | -------- | +| 回溯栈接口 | LOS_BackTrace:打印调用处的函数调用栈关系。
LOS_RecordLR:在无法打印的场景,用该接口获取调用处的函数调用栈关系。 | ## 使用指导 @@ -46,14 +39,15 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 开启异常调测的典型流程如下: 1. 配置异常接管相关宏。 - 需要在target_config.h头文件中修改配置: - | 配置项 | 含义 | 设置值 | + 需要在target_config.h头文件中修改配置: + | 配置项 | 含义 | 设置值 | | -------- | -------- | -------- | | LOSCFG_BACKTRACE_DEPTH | 函数调用栈深度,默认15层 | 15 | | LOSCFG_BACKTRACE_TYPE | 回溯栈类型:
0:表示关闭该功能;
1:表示支持Cortex-m系列硬件的函数调用栈解析;
2:表示用于Risc-v系列硬件的函数调用栈解析; | 根据工具链类型设置1或2 | 1. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。 - 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: + 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: + ``` #include #include "los_config.h" @@ -128,6 +122,7 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 ``` 1. 上述代码串口终端输出异常信息如下: + ``` entering kernel init... LOS_TaskLock() Success! @@ -220,6 +215,7 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 异常接管一般的定位步骤如下: 1. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为: + ``` arm-none-eabi-objdump -S -l XXX.elf ``` @@ -227,6 +223,7 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 1. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。 PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x80037da,找到当前CPU正在执行的指令行,反汇编如下所示: + ``` UINT32 Get_Result_Exception_0(UINT16 dividend){ 80037c8: b480 push {r7} @@ -253,6 +250,7 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 2. 根据LR值查找异常函数的父函数。 包含LR值0x80037fe的反汇编如下所示: + ``` 080037ec : Get_Result_Exception_1(): diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-lms.md b/zh-cn/device-dev/kernel/kernel-mini-memory-lms.md index 15c7df576a060b2e70698cc5ac0835240c5eadd1..1174ac12e59c3c85cf54503f081fbf67c92efdc8 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-lms.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-lms.md @@ -1,13 +1,5 @@ # LMS调测 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -41,7 +33,7 @@ LMS使用影子内存映射标记系统内存的状态,一共可标记为三 OpenHarmony LiteOS-M内核的LMS模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_m/blob/master/components/lms/los_lms.h)参考。 -**表1** LMS模块接口说明 + **表1** LMS模块接口说明 | 功能分类 | 接口名 | 描述 | | -------- | -------- | -------- | @@ -61,7 +53,7 @@ OpenHarmony LiteOS-M内核的LMS模块提供下面几种功能,接口详细信 1. 配置LMS模块相关宏。 配置LMS控制宏LOSCFG_KERNEL_LMS,默认关,在kernel/liteos_m目录下执行 make update_config命令配置"Kernel->Enable Lite Memory Sanitizer"中打开YES: - | 宏 | menuconfig选项 | 含义 | 取值 | + | 宏 | menuconfig选项 | 含义 | 取值 | | -------- | -------- | -------- | -------- | | LOSCFG_KERNEL_LMS | Enable Lms Feature | Lms模块的裁剪开关 | YES/NO | | LOSCFG_LMS_MAX_RECORD_POOL_NUM | Lms check pool max num | LMS支持的检测内存池最大个数 | INT | @@ -72,7 +64,8 @@ OpenHarmony LiteOS-M内核的LMS模块提供下面几种功能,接口详细信 2. 在被检测模块的编译脚本中,修改编译选项。 增加LMS检测编译选项-fsanitize=kernel-address。为避免编译器优化,增加-O0编译选项。 - gcc与clang编译选项存在差异,参照如下示例: + gcc与clang编译选项存在差异,参照如下示例: + ``` if ("$ohos_build_compiler_specified" == "gcc") { cflags_c = [ @@ -109,7 +102,8 @@ OpenHarmony LiteOS-M内核的LMS模块提供下面几种功能,接口详细信 ### 示例代码 -实例代码如下: + 实例代码如下: + ``` #define PAGE_SIZE (0x1000U) #define INDEX_MAX 20 @@ -168,7 +162,8 @@ UINT32 Example_Lms_test(VOID){ ### 结果验证 -输出结果如下: + 输出结果如下: + ``` ######LmsTestOsmallocOverflow start ###### [ERR]* Kernel Address Sanitizer Error Detected Start * diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-perf.md b/zh-cn/device-dev/kernel/kernel-mini-memory-perf.md index 4c4513daeccce1fe02db5b916af5e30c92b37962..242a71ab638868dc519297774227e6f6a47865bc 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-perf.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-perf.md @@ -1,19 +1,5 @@ # Perf调测 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) - - [内核态](#内核态) - - [用户态](#用户态) -- [开发指导](#开发指导) - - [内核态开发流程](#内核态开发流程) -- [内核态编程实例](#内核态编程实例) -- [内核态示例代码](#内核态示例代码) - - [内核态结果验证](#内核态结果验证) - - [用户态开发流程](#用户态开发流程) - - [用户态编程实例](#用户态编程实例) - - [用户态示例代码](#用户态示例代码) - - [用户态结果验证](#用户态结果验证) ## 基本概念 @@ -36,16 +22,14 @@ Perf提供2种工作模式,计数模式和采样模式。 OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_perf.h)参考。 -**表1** Perf模块接口说明 + **表1** Perf模块接口说明 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 开启/停止Perf采样 | LOS_PerfStart | 开启采样 | -| | LOS_PerfStop | 停止采样 | -| 配置Perf采样事件 | LOS_PerfConfig | 配置采样事件的类型、周期等 | -| 读取采样数据 | LOS_PerfDataRead | 读取采样数据到指定地址 | -| 注册采样数据缓冲区的钩子函数 | LOS_PerfNotifyHookReg | 注册缓冲区水线到达的处理钩子 | -| | LOS_PerfFlushHookReg | 注册缓冲区刷cache的钩子 | +| 功能分类 | 接口描述 | +| -------- | -------- | +| 开启/停止Perf采样 | LOS_PerfStart:开启采样
LOS_PerfStop:停止采样 | +| 配置Perf采样事件 | LOS_PerfConfig:配置采样事件的类型、周期等 | +| 读取采样数据 | LOS_PerfDataRead:读取采样数据到指定地址 | +| 注册采样数据缓冲区的钩子函数 | LOS_PerfNotifyHookReg:注册缓冲区水线到达的处理钩子
LOS_PerfFlushHookReg:注册缓冲区刷cache的钩子 | 1. Perf采样事件的结构体为PerfConfigAttr,详细字段含义及取值详见kernel\include\los_perf.h。 @@ -53,6 +37,7 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细 2. 采样数据缓冲区为环形buffer,buffer中读过的区域可以覆盖写,未被读过的区域不能被覆盖写。 3. 缓冲区有限,用户可通过注册水线到达的钩子进行buffer溢出提醒或buffer读操作。默认水线值为buffer总大小的1/2。 示例如下: + ``` VOID Example_PerfNotifyHook(VOID) { @@ -66,6 +51,7 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细 ``` 4. 若perf采样的buffer涉及到cpu 跨cache,则用户可通过注册刷cache的钩子,进行cache同步。 示例如下: + ``` VOID Example_PerfFlushHook(VOID *addr, UINT32 size) { @@ -88,6 +74,7 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细 - write: 用户态采样事件配置 - ioctl: 用户态Perf控制操作,包括 + ``` #define PERF_IOC_MAGIC 'T' #define PERF_START _IO(PERF_IOC_MAGIC, 1) @@ -110,7 +97,7 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细 1. 配置Perf模块相关宏。 配置Perf控制宏LOSCFG_KERNEL_PERF,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Perf Feature"中打开: - | 配置项 | menuconfig选项 | 含义 | 设置值 | + | 配置项 | menuconfig选项 | 含义 | 设置值 | | -------- | -------- | -------- | -------- | | LOSCFG_KERNEL_PERF | Enable Perf Feature | Perf模块的裁剪开关 | YES/NO | | LOSCFG_PERF_CALC_TIME_BY_TICK | Time-consuming Calc Methods->By Tick | Perf计时单位为tick | YES/NO | @@ -155,7 +142,8 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细 前提条件:在menuconfig菜单中完成perf模块的配置。 -实例代码如下: + 实例代码如下: + ``` #include "los_perf.h" STATIC VOID OsPrintBuff(const CHAR *buf, UINT32 num) @@ -240,7 +228,8 @@ LOS_MODULE_INIT(perfTestHwEvent, LOS_INIT_LEVEL_KMOD_EXTENDED); ### 内核态结果验证 -输出结果如下: + 输出结果如下: + ``` --------count mode---------- [EMG] [cycles] eventType: 0xff: 5466989440 @@ -290,6 +279,7 @@ hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08 ./perf list 查看可使用的事件列表, 输出如下: + ``` cycles [Hardware event] instruction [Hardware event] @@ -308,6 +298,7 @@ mux-pend [Software event] ./perf stat -e cycles os_dump, 输出如下: + ``` type: 0 events[0]: 255, 0xffff @@ -325,6 +316,7 @@ time used: 0.058000(s) ./perf record -e cycles os_dump, 输出如下: + ``` type: 0 events[0]: 255, 0xffff @@ -361,7 +353,8 @@ save perf data success at /storage/data/perf.data ### 用户态示例代码 -实例代码如下: + 实例代码如下: + ``` #include "fcntl.h" #include "user_copy.h" @@ -431,7 +424,8 @@ int main(int argc, char **argv) ### 用户态结果验证 -输输出结果如下:出结果如下: + 输出结果如下 + ``` [EMG] dump section data, addr: 0x8000000 length: 0x800000 num: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ... diff --git a/zh-cn/device-dev/kernel/kernel-mini-memory-trace.md b/zh-cn/device-dev/kernel/kernel-mini-memory-trace.md index edf6ffe857a29211ed1cca0da0b3929902a42c8d..664a106625caeff2456c175ab1a0eece8b625b0d 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-trace.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-trace.md @@ -1,13 +1,5 @@ # Trace调测 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [示例代码](#示例代码) - - [结果验证](#结果验证) ## 基本概念 @@ -33,19 +25,15 @@ Trace提供2种工作模式,离线模式和在线模式。 OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** Trace模块接口说明 + **表1** Trace模块接口说明 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 启停控制 | LOS_TraceStart | 启动Trace | -| | LOS_TraceStop | 停止Trace | -| 操作Trace记录的数据 | LOS_TraceRecordDump | 输出Trace缓冲区数据 | -| | LOS_TraceRecordGet | 获取Trace缓冲区的首地址 | -| | LOS_TraceReset | 清除Trace缓冲区中的事件 | -| 过滤Trace记录的数据 | LOS_TraceEventMaskSet | 设置事件掩码,仅记录某些模块的事件 | -| 屏蔽某些中断号事件 | LOS_TraceHwiFilterHookReg | 注册过滤特定中断号事件的钩子函数 | -| 插桩函数 | LOS_TRACE_EASY | 简易插桩 | -| | LOS_TRACE | 标准插桩 | +| 功能分类 | 接口名 | +| -------- | -------- | +| 启停控制 | - LOS_TraceStart:启动Trace
- LOS_TraceStop:停止Trace | +| 操作Trace记录的数据 | - LOS_TraceRecordDump:输出Trace缓冲区数据
- LOS_TraceRecordGet:获取Trace缓冲区的首地址
- LOS_TraceReset:清除Trace缓冲区中的事件 | +| 过滤Trace记录的数据 | LOS_TraceEventMaskSet:设置事件掩码,仅记录某些模块的事件 | +| 屏蔽某些中断号事件 | LOS_TraceHwiFilterHookReg:注册过滤特定中断号事件的钩子函数 | +| 插桩函数 | LOS_TRACE_EASY:简易插桩
LOS_TRACE:标准插桩 | - 当用户需要针对自定义事件进行追踪时,可按规则在目标源代码中进行插桩,系统提供如下2种插桩接口: - LOS_TRACE_EASY(TYPE, IDENTITY, params...) 简易插桩。 @@ -53,45 +41,49 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 - TYPE有效取值范围为[0, 0xF],表示不同的事件类型,不同取值表示的含义由用户自定义。 - IDENTITY类型UINTPTR,表示事件操作的主体对象。 - Params类型UINTPTR,表示事件的参数。 - - 示例: + - 对文件fd读写操作的简易插桩示例: + ``` - 假设需要新增对文件(fd1、fd2)读写操作的简易插桩, - 自定义读操作为type:1, 写操作为type:2,则 - 在读fd1文件的适当位置插入: - LOS_TRACE_EASY(1, fd1, flag, size); - 在读fd2文件的适当位置插入: - LOS_TRACE_EASY(1, fd2, flag, size); - 在写fd1文件的适当位置插入: - LOS_TRACE_EASY(2, fd1, flag, size); - 在写fd2文件的适当位置插入: - LOS_TRACE_EASY(2, fd2,flag, size); + /* 假设自定义读操作为type: 1, 写操作为type: 2 */ + LOS_TRACE_EASY(1, fd, flag, size); /* 在读fd文件的适当位置插入 */ + LOS_TRACE_EASY(2, fd, flag, size); /* 在写fd文件的适当位置插入 */ ``` - LOS_TRACE(TYPE, IDENTITY, params...) 标准插桩。 - 相比简易插桩,支持动态过滤事件和参数裁剪,但使用上需要用户按规则来扩展。 - TYPE用于设置具体的事件类型,可以在头文件los_trace.h中的enum LOS_TRACE_TYPE中自定义事件类型。定义方法和规则可以参考其他事件类型。 - IDENTITY和Params的类型及含义同简易插桩。 - 示例: + 1. 定义FS模块的类型,即FS模块的事件掩码 + + ``` + /* 在enum LOS_TRACE_MASK中定义, 定义规范为TRACE_#MOD#_FLAG, #MOD#表示模块名 */ + TRACE_FS_FLAG = 0x4000 + ``` + + 2. 定义FS模块的具体事件类型 + + + ``` + /* 定义规范为#TYPE# = TRACE_#MOD#_FLAG | NUMBER, */ + FS_READ = TRACE_FS_FLAG | 0; /* 读文件 */ + FS_WRITE = TRACE_FS_FLAG | 1; /* 写文件 */ + ``` + + 3. 定义事件参数 + + + ``` + /* 定义规范为#TYPE#_PARAMS(IDENTITY, parma1...) IDENTITY, ... */ + #define FS_READ_PARAMS(fp, fd, flag, size) fp, fd, flag, size /* 宏定义的参数对应于Trace缓冲区中记录的事件参数,用户可对任意参数字段进行裁剪 */ + #define FS_READ_PARAMS(fp, fd, flag, size) /* 当定义为空时,表示不追踪该类型事件 */ + ``` + + 4. 在目标代码中插桩 + + ``` - 1.在enum LOS_TRACE_MASK中定义事件掩码,即模块级别的事件类型。 - 定义规范为TRACE_#MOD#_FLAG,#MOD#表示模块名。 - 例如: - TRACE_FS_FLAG = 0x4000 - 2.在enum LOS_TRACE_TYPE中定义具体事件类型。 - 定义规范为#TYPE# = TRACE_#MOD#_FLAG | NUMBER, - 例如: - FS_READ = TRACE_FS_FLAG | 0; // 读文件 - FS_WRITE = TRACE_FS_FLAG | 1; // 写文件 - 3.定义事件参数。定义规范为#TYPE#_PARAMS(IDENTITY, parma1...) IDENTITY, ... - 其中的#TYPE#就是上面2中的#TYPE#, - 例如: - #define FS_READ_PARAMS(fp, fd, flag, size) fp, fd, flag, size - 宏定义的参数对应于Trace缓冲区中记录的事件参数,用户可对任意参数字段进行裁剪: - 当定义为空时,表示不追踪该类型事件: - #define FS_READ_PARAMS(fp, fd, flag, size) // 不追踪文件读事件 - 4.在适当位置插入代码桩。 - 定义规范为LOS_TRACE(#TYPE#, #TYPE#_PARAMS(IDENTITY, parma1...)) - LOS_TRACE(FS_READ, fp, fd, flag, size); // 读文件的代码桩, - #TYPE#之后的入参就是上面3中的FS_READ_PARAMS函数的入参 + /* 定义规范为LOS_TRACE(#TYPE#, #TYPE#_PARAMS(IDENTITY, parma1...)) */ + LOS_TRACE(FS_READ, fp, fd, flag, size); /* 读文件操作的代码桩 */ ``` > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** @@ -106,7 +98,8 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 - Trace的典型操作流程为:LOS_TraceStart、 LOS_TraceStop、 LOS_TraceRecordDump. - 针对中断事件的Trace, 提供中断号过滤,用于解决某些场景下特定中断号频繁触发导致其他事件被覆盖的情况,用户可自定义中断过滤的规则, - 示例如下: + 示例如下: + ``` BOOL Example_HwiNumFilter(UINT32 hwiNum) { @@ -129,8 +122,8 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 开启Trace调测的典型流程如下: 1. 配置Trace模块相关宏。 - 需要在target_config.h头文件中修改配置: - | 配置项 | 含义 | 设置值 | + 需要在target_config.h头文件中修改配置: + | 配置项 | 含义 | 设置值 | | -------- | -------- | -------- | | LOSCFG_KERNEL_TRACE | Trace模块的裁剪开关 | YES/NO | | LOSCFG_RECORDER_MODE_OFFLINE | Trace工作模式为离线模式 | YES/NO | @@ -185,6 +178,7 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 示例代码如下: + ``` #include "los_trace.h" UINT32 g_traceTestTaskId; @@ -235,6 +229,7 @@ UINT32 Example_Trace_test(VOID){ 输出结果如下: + ``` ***TraceInfo begin*** clockFreq = 50000000 @@ -263,6 +258,7 @@ Index Time(cycles) EventType CurTask Identity params 下面以序号为0的输出项为例,进行说明。 + ``` Index Time(cycles) EventType CurTask Identity params 0 0x366d5e88 0x45 0x1 0x0 0x1f 0x4 @@ -274,12 +270,13 @@ Index Time(cycles) EventType CurTask Identity params - Identity和params的含义需要查看TASK_SWITCH_PARAMS宏定义: + ``` #define TASK_SWITCH_PARAMS(taskId, oldPriority, oldTaskStatus, newPriority, newTaskStatus) \ taskId, oldPriority, oldTaskStatus, newPriority, newTaskStatus ``` -因为\#TYPE\#_PARAMS(IDENTITY, parma1...) IDENTITY, ...,所以Identity为taskId(0x0),第一个参数为oldPriority(0x1f) + 因为\#TYPE\#_PARAMS(IDENTITY, parma1...) IDENTITY, ...,所以Identity为taskId(0x0),第一个参数为oldPriority(0x1f) > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > params的个数由LOSCFG_TRACE_FRAME_MAX_PARAMS配置,默认为3,超出的参数不会被记录,用户应自行合理配置该值。 diff --git a/zh-cn/device-dev/kernel/kernel-mini-overview.md b/zh-cn/device-dev/kernel/kernel-mini-overview.md index 1a7369be0157374070625b7298c70e614c5cedf3..dde230ec279715e919bf61efad922c7fb2fbec55 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-overview.md +++ b/zh-cn/device-dev/kernel/kernel-mini-overview.md @@ -1,8 +1,5 @@ # 内核概述 -- [内核简介](#内核简介) - - [cpu体系架构支持](#cpu体系架构支持) - - [运行机制](#运行机制) ## 内核简介 @@ -10,28 +7,29 @@ OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系 OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中硬件相关层按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;其他模块属于硬件无关层,其中基础内核模块提供基础能力,扩展模块提供网络、文件系统等组件能力,还提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。 -**图1** 内核架构图 -![zh-cn_image_0000001199351155](figures/zh-cn_image_0000001199351155.png) + **图1** 内核架构图 + ![zh-cn_image_0000001199351155](figures/zh-cn_image_0000001199351155.png) -### cpu体系架构支持 + +### CPU体系架构支持 CPU体系架构分为通用架构定义和特定架构定义两层,通用架构定义层为所有体系架构都需要支持和实现的接口,特定架构定义层为特定体系架构所特有的部分。在新增一个体系架构的时候,必须需要实现通用架构定义层,如果该体系架构还有特有的功能,可以在特定架构定义层来实现。 -**表1** CPU体系架构规则 + **表1** CPU体系架构规则 -| 规则 | 通用体系架构层 | 特定体系架构层 | +| 规则 | 通用体系架构层 | 特定体系架构层 | | -------- | -------- | -------- | -| 头文件位置 | arch/include | arch/<arch>/<arch>/<toolchain>/ | -| 头文件命名 | los_<function>.h | los_arch_<function>.h | -| 函数命名 | Halxxxx | Halxxxx | +| 头文件位置 | arch/include | arch/<arch>/<arch>/<toolchain>/ | +| 头文件命名 | los_<function>.h | los_arch_<function>.h | +| 函数命名 | Halxxxx | Halxxxx | LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M33、RISC-V等主流架构,如果需要扩展CPU体系架构,请参考[芯片架构适配点](../porting/porting-chip-kernel-overview.md#芯片架构适配点)。 ### 运行机制 -在开发板配置文件target_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程。 +在开发板配置文件target_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见下图。 -**图2** 内核启动流程 -![zh-cn_image_0000001160338832](figures/zh-cn_image_0000001160338832.png) + **图2** 内核启动流程 + ![zh-cn_image_0000001160338832](figures/zh-cn_image_0000001160338832.png) diff --git a/zh-cn/device-dev/kernel/kernel-mini.md b/zh-cn/device-dev/kernel/kernel-mini.md index 04e901ddfc80c9b8bd3408d8dbb24bc73ad59583..75f80435e9de24c4aedeed6aa0337fece5622bed 100644 --- a/zh-cn/device-dev/kernel/kernel-mini.md +++ b/zh-cn/device-dev/kernel/kernel-mini.md @@ -1,6 +1,7 @@ # 轻量系统内核 + - **[内核概述](kernel-mini-overview.md)** - **[基础内核](kernel-mini-basic.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md b/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md index 5231d08789b95c0c2be0ec9df4d0ebb2391afb0b..68cc022a69fb0ec50e8fb25b71b78101c77405e7 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md @@ -1,10 +1,5 @@ # 位操作 -- [基本概念](#基本概念) -- [功能说明](#功能说明) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [结果验证](#结果验证) ## 基本概念 @@ -15,17 +10,13 @@ 系统提供标志位的置1和清0操作,可以改变标志位的内容,同时还提供获取状态字中标志位为1的最高位和最低位的功能。用户也可以对系统的寄存器进行位操作。位操作模块为用户提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 位操作模块接口 + **表1** 位操作模块接口 -| **功能分类** | **接口名称** | **描述** | -| -------- | -------- | -------- | -| 置1/清0标志位 | LOS_BitmapSet | 对状态字的某一标志位进行置1操作 | -| | LOS_BitmapClr | 对状态字的某一标志位进行清0操作 | -| 获取标志位为1的bit位 | LOS_HighBitGet | 获取状态字中为1的最高位 | -| | LOS_LowBitGet | 获取状态字中为1的最低位 | -| 连续bit位操作 | LOS_BitmapSetNBits | 对状态字的连续标志位进行置1操作 | -| | LOS_BitmapClrNBits | 对状态字的连续标志位进行清0操作 | -| | LOS_BitmapFfz | 获取从最低有效位开始的第一个0的bit位 | +| **功能分类** | **接口描述** | +| -------- | -------- | +| 置1/清0标志位 | - LOS_BitmapSet:对状态字的某一标志位进行置1操作
- LOS_BitmapClr:对状态字的某一标志位进行清0操作 | +| 获取标志位为1的bit位 | - LOS_HighBitGet:获取状态字中为1的最高位
- LOS_LowBitGet:获取状态字中为1的最低位 | +| 连续bit位操作 | - LOS_BitmapSetNBits:对状态字的连续标志位进行置1操作
- LOS_BitmapClrNBits:对状态字的连续标志位进行清0操作
- LOS_BitmapFfz:获取从最低有效位开始的第一个0的bit位 | ## 编程实例 @@ -43,6 +34,7 @@ 4. 获取标志位为1的最低bit位。 + ``` #include "los_bitmap.h" #include "los_printf.h" @@ -77,6 +69,7 @@ static UINT32 BitSample(VOID) 编译运行得到的结果为: + ``` Bitmap Sample! The flag is 0x10101010 diff --git a/zh-cn/device-dev/kernel/kernel-small-apx-dll.md b/zh-cn/device-dev/kernel/kernel-small-apx-dll.md index 2de8c99b062c099cec780638e565f0a671954688..b78216edc0f115b47f542db820e786773ad35c96 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-dll.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-dll.md @@ -1,9 +1,5 @@ # 双向链表 -- [基本概念](#基本概念) -- [功能说明](#功能说明) -- [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -14,30 +10,17 @@ 双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 -| **功能分类** | **接口名** | **描述** | -| -------- | -------- | -------- | -| 初始化链表 | LOS_ListInit | 将指定节点初始化为双向链表节点 | -| | LOS_DL_LIST_HEAD | 定义一个节点并初始化为双向链表节点 | -| 增加节点 | LOS_ListAdd | 将指定节点插入到双向链表头端 | -| | LOS_ListHeadInsert | 将指定节点插入到双向链表头端,同LOS_ListAdd | -| | LOS_ListTailInsert | 将指定节点插入到双向链表尾端 | -| 增加链表 | LOS_ListAddList | 将指定链表的头端插入到双向链表头端 | -| | LOS_ListHeadInsertList | 将指定链表的头端插入到双向链表头端,同LOS_ListAddList | -| | LOS_ListTailInsertList | 将指定链表的尾端插入到双向链表头端 | -| 删除节点 | LOS_ListDelete | 将指定节点从链表中删除 | -| | LOS_ListDelInit | 将指定节点从链表中删除,并使用该节点初始化链表 | -| 判断双向链表 | LOS_ListEmpty | 判断链表是否为空 | -| | LOS_DL_LIST_IS_END | 判断指定链表节点是否为链表尾端 | -| | LOS_DL_LIST_IS_ON_QUEUE | 判断链表节点是否在双向链表里 | -| 获取结构体信息 | LOS_OFF_SET_OF | 获取指定结构体内的成员相对于结构体起始地址的偏移量 | -| | LOS_DL_LIST_ENTRY | 获取双向链表中第一个链表节点所在的结构体地址,接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称 | -| | LOS_ListPeekHeadType | 获取双向链表中第一个链表节点所在的结构体地址,接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称。如果链表为空,返回NULL。 | -| | LOS_ListRemoveHeadType | 获取双向链表中第一个链表节点所在的结构体地址,并把第一个链表节点从链表中删除。接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称。如果链表为空,返回NULL。 | -| | LOS_ListNextType | 获取双向链表中指定链表节点的下一个节点所在的结构体地址。接口的第一个入参表示的是链表中的头节点,第二个入参是指定的链表节点,第三个入参是要获取的结构体名称,第四个入参是链表在该结构体中的名称。如果链表节点下一个为链表头结点为空,返回NULL。 | -| 遍历双向链表 | LOS_DL_LIST_FOR_EACH | 遍历双向链表 | -| | LOS_DL_LIST_FOR_EACH_SAFE | 遍历双向链表,并存储当前节点的后继节点用于安全校验 | -| 遍历包含双向链表的结构体 | LOS_DL_LIST_FOR_EACH_ENTRY | 遍历指定双向链表,获取包含该链表节点的结构体地址 | -| | LOS_DL_LIST_FOR_EACH_ENTRY_SAFE | 遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址 | + | | | +| -------- | -------- | +| **功能分类** | **接口名** | +| 初始化链表 | - LOS_ListInit:将指定节点初始化为双向链表节点
- LOS_DL_LIST_HEAD:定义一个节点并初始化为双向链表节点 | +| 增加节点 | - LOS_ListAdd:将指定节点插入到双向链表头端
- LOS_ListHeadInsert:将指定节点插入到双向链表头端,同LOS_ListAdd
- LOS_ListTailInsert:将指定节点插入到双向链表尾端 | +| 增加链表 | - LOS_ListAddList:将指定链表的头端插入到双向链表头端
- LOS_ListHeadInsertList:将指定链表的头端插入到双向链表头端
- LOS_ListTailInsertList:将指定链表的尾端插入到双向链表头端 | +| 删除节点 | - LOS_ListDelete:将指定节点从链表中删除
- LOS_ListDelInit:将指定节点从链表中删除,并使用该节点初始化链表 | +| 判断双向链表 | - LOS_ListEmpty:判断链表是否为空
- LOS_DL_LIST_IS_END:判断指定链表节点是否为链表尾端:LOS_DL_LIST_IS_ON_QUEUE:判断链表节点是否在双向链表里 | +| 获取结构体信息 | - LOS_OFF_SET_OF:获取指定结构体内的成员相对于结构体起始地址的偏移量
- LOS_DL_LIST_ENTRY:获取双向链表中第一个链表节点所在的结构体地址,接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称
- LOS_ListPeekHeadType:获取双向链表中第一个链表节点所在的结构体地址,接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称。如果链表为空,返回NULL。
- LOS_ListRemoveHeadType:获取双向链表中第一个链表节点所在的结构体地址,并把第一个链表节点从链表中删除。接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称。如果链表为空,返回NULL。
- LOS_ListNextType:获取双向链表中指定链表节点的下一个节点所在的结构体地址。接口的第一个入参表示的是链表中的头节点,第二个入参是指定的链表节点,第三个入参是要获取的结构体名称,第四个入参是链表在该结构体中的名称。如果链表节点下一个为链表头结点为空,返回NULL。
- LOS_OFF_SET_OF:获取指定结构体内的成员相对于结构体起始地址的偏移量
- LOS_DL_LIST_ENTRY:获取双向链表中第一个链表节点所在的结构体地址,接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称
- LOS_ListPeekHeadType:获取双向链表中第一个链表节点所在的结构体地址,接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称。如果链表为空,返回NULL。
- LOS_ListRemoveHeadType:获取双向链表中第一个链表节点所在的结构体地址,并把第一个链表节点从链表中删除。接口的第一个入参表示的是链表中的头节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称。如果链表为空,返回NULL。
- LOS_ListNextType:获取双向链表中指定链表节点的下一个节点所在的结构体地址。接口的第一个入参表示的是链表中的头节点,第二个入参是指定的链表节点,第三个入参是要获取的结构体名称,第四个入参是链表在该结构体中的名称。如果链表节点下一个为链表头结点为空,返回NULL。 | +| 遍历双向链表 | - LOS_DL_LIST_FOR_EACH:遍历双向链表
- LOS_DL_LIST_FOR_EACH_SAFE:遍历双向链表,并存储当前节点的后继节点用于安全校验 | +| 遍历包含双向链表的结构体 | - LOS_DL_LIST_FOR_EACH_ENTRY:遍历指定双向链表,获取包含该链表节点的结构体地址
- LOS_DL_LIST_FOR_EACH_ENTRY_SAFE:遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址 | ## 开发流程 @@ -82,6 +65,7 @@ 4. 测试操作是否成功。 + ``` #include "stdio.h" #include "los_list.h" @@ -127,8 +111,10 @@ static UINT32 ListSample(VOID) 编译运行得到的结果为: + ``` -Initial head Add listNode1 success +Initial head +Add listNode1 success Tail insert listNode2 success Delete success ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-apx-library.md b/zh-cn/device-dev/kernel/kernel-small-apx-library.md index c69a513d59d42911ce0e75a35fe0899338da7b51..229046a8a171f82ed9260cdf567da6ecc43b8a98 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-library.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-library.md @@ -1,22 +1,14 @@ # 标准库 -- [标准库接口框架](#标准库接口框架) -- [操作实例](#操作实例) -- [与Linux标准库差异](#与linux标准库差异) - - [进程](#进程) - - [内存](#内存) - - [文件系统](#文件系统) - - [信号](#信号) - - [Time](#time) OpenHarmony内核使用musl libc库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。 ## 标准库接口框架 -**图1** POSIX接口框架 + **图1** POSIX接口框架 -![zh-cn_image_0000001172904117](figures/zh-cn_image_0000001172904117.png) + ![zh-cn_image_0000001172904117](figures/zh-cn_image_0000001172904117.png) musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony内核适配支持 ,以满足接口对外描述的功能要求。 @@ -27,6 +19,7 @@ musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony 在本示例中,主线程创建了THREAD_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread_join方法等待所有线程执行结束。 + ``` #include #include @@ -229,6 +222,7 @@ mmap接口原型为:void \*mmap (void \*addr, size_t length, int prot, int fla Linux目前支持的情况如下: + ``` int main(int argc, char *argv[]) { @@ -252,7 +246,8 @@ int main(int argc, char *argv[]) ``` -OpenHarmony支持的情况如下: + OpenHarmony支持的情况如下: + ``` int main(int argc, char *argv[]) { diff --git a/zh-cn/device-dev/kernel/kernel-small-apx-structure.md b/zh-cn/device-dev/kernel/kernel-small-apx-structure.md index 7cd200e74a944bb97069e8b5963d0e4e99569b09..8181febefe7ae639915052d9374f055cb995418d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-structure.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-structure.md @@ -1,6 +1,7 @@ # 基本数据结构 + - **[双向链表](kernel-small-apx-dll.md)** - **[位操作](kernel-small-apx-bitwise.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-apx.md b/zh-cn/device-dev/kernel/kernel-small-apx.md index b785fd1789e556acb8431445e1bf890a115c434d..030e9cf20cc2fdebedb5cdd9d98c95f4996f8b7e 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx.md @@ -1,6 +1,7 @@ # 附录 + - **[基本数据结构](kernel-small-apx-structure.md)** - **[标准库](kernel-small-apx-library.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-atomic.md b/zh-cn/device-dev/kernel/kernel-small-basic-atomic.md index 1188ead10b0fd57df10f4e50f82bf5237fd6476d..ac9755b5eea1c077d3646635cd4bac19667271ea 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-atomic.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-atomic.md @@ -1,11 +1,5 @@ # 原子操作 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -48,34 +42,34 @@ OpenHarmony系统通过对ARMv6架构中的LDREX和STREX进行封装,向用户 OpenHarmony LiteOS-A内核的原子操作模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 原子操作接口说明 + **表1** 原子操作接口说明 -| 功能分类 | 接口**名称** | 描述 | +| 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | -| 读 | LOS_AtomicRead | 读取32bit原子数据 | -| | LOS_Atomic64Read |读取64bit原子数据| -| 写 | LOS_AtomicSet | 设置32bit原子数据 | -| | LOS_Atomic64Set |设置64bit原子数据| -| 加 | LOS_AtomicAdd | 对32bit原子数据做加法 | -| | LOS_Atomic64Add |对64bit原子数据做加法| -| | LOS_AtomicInc |对32bit原子数据做加1| -| | LOS_Atomic64Inc |对64bit原子数据做加1| -| | LOS_AtomicIncRet |对32bit原子数据做加1并返回| -| | LOS_Atomic64IncRet |对64bit原子数据做加1并返回| -| 减 | LOS_AtomicSub | 对32bit原子数据做减法 | -| | LOS_Atomic64Sub |对64bit原子数据做减法| -| | LOS_AtomicDec |对32bit原子数据做减1| -| | LOS_Atomic64Dec |对64bit原子数据做减1| -| | LOS_AtomicDecRet |对32bit原子数据做减1并返回| -| | LOS_Atomic64DecRet |对64bit原子数据做减1并返回| -| 交换 | LOS_AtomicXchgByte | 交换8bit内存数据 | -| | LOS_AtomicXchg16bits |交换16bit内存数据| -| | LOS_AtomicXchg32bits |交换32bit内存数据| -| | LOS_AtomicXchg64bits |交换64bit内存数据| -| 先比较后交换 | LOS_AtomicCmpXchgByte | 比较相同后交换8bit内存数据 | -| | LOS_AtomicCmpXchg16bits |比较相同后交换16bit内存数据| -| | LOS_AtomicCmpXchg32bits |比较相同后交换32bit内存数据| -| | LOS_AtomicCmpXchg64bits |比较相同后交换64bit内存数据| +| 读 | LOS_AtomicRead | 读取32bit原子数据 | +| 读 | LOS_Atomic64Read | 读取64bit原子数据 | +| 写 | LOS_AtomicSet | 设置32bit原子数据 | +| 写 | LOS_Atomic64Set | 设置64bit原子数据 | +| 加 | LOS_AtomicAdd | 对32bit原子数据做加法 | +| 加 | LOS_Atomic64Add | 对64bit原子数据做加法 | +| 加 | LOS_AtomicInc | 对32bit原子数据做加1 | +| 加 | LOS_Atomic64Inc | 对64bit原子数据做加1 | +| 加 | LOS_AtomicIncRet | 对32bit原子数据做加1并返回 | +| 加 | LOS_Atomic64IncRet | 对64bit原子数据做加1并返回 | +| 减 | LOS_AtomicSub | 对32bit原子数据做减法 | +| 减 | LOS_Atomic64Sub | 对64bit原子数据做减法 | +| 减 | LOS_AtomicDec | 对32bit原子数据做减1 | +| 减 | LOS_Atomic64Dec | 对64bit原子数据做减1 | +| 减 | LOS_AtomicDecRet | 对32bit原子数据做减1并返回 | +| 减 | LOS_Atomic64DecRet | 对64bit原子数据做减1并返回 | +| 交换 | LOS_AtomicXchgByte | 交换8bit内存数据 | +| 交换 | LOS_AtomicXchg16bits | 交换16bit内存数据 | +| 交换 | LOS_AtomicXchg32bits | 交换32bit内存数据 | +| 交换 | LOS_AtomicXchg64bits | 交换64bit内存数据 | +| 先比较后交换 | LOS_AtomicCmpXchgByte | 比较相同后交换8bit内存数据 | +| 先比较后交换 | LOS_AtomicCmpXchg16bits | 比较相同后交换16bit内存数据 | +| 先比较后交换 | LOS_AtomicCmpXchg32bits | 比较相同后交换32bit内存数据 | +| 先比较后交换 | LOS_AtomicCmpXchg64bits | 比较相同后交换64bit内存数据 | ### 开发流程 @@ -102,6 +96,7 @@ OpenHarmony LiteOS-A内核的原子操作模块提供下面几种功能,接口 示例代码如下: + ``` #include "los_hwi.h" #include "los_atomic.h" @@ -164,6 +159,7 @@ UINT32 Example_AtomicTaskEntry(VOID) **结果验证** + ``` g_sum = 0 ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-inner-reflect.md b/zh-cn/device-dev/kernel/kernel-small-basic-inner-reflect.md index 81c2af090814874c78f6265479c49d3dec294e1d..6a016a60bff30dbec1854cddac9a92aa42ae204a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-inner-reflect.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-inner-reflect.md @@ -1,17 +1,13 @@ # 虚实映射 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) ## 基本概念 虚实映射是指系统通过内存管理单元(MMU,Memory Management Unit)将进程空间的虚拟地址与实际的物理地址做映射,并指定相应的访问权限、缓存属性等。程序执行时,CPU访问的是虚拟内存,通过MMU页表条目找到对应的物理内存,并做相应的代码执行或数据读写操作。MMU的映射由页表(Page Table)来描述,其中保存虚拟地址和物理地址的映射关系以及访问权限等。每个进程在创建的时候都会创建一个页表,页表由一个个页表条目(Page Table Entry, PTE)构成,每个页表条目描述虚拟地址区间与物理地址区间的映射关系。MMU中有一块页表缓存,称为快表(TLB, Translation Lookaside Buffers),做地址转换时,MMU首先在TLB中查找,如果找到对应的页表条目可直接进行转换,提高了查询效率。CPU访问内存或外设的示意图如下: -**图1** CPU访问内存或外设的示意图 -![zh-cn_image_0000001133263576](figures/zh-cn_image_0000001133263576.png) + **图1** CPU访问内存或外设的示意图 + + ![zh-cn_image_0000001133263576](figures/zh-cn_image_0000001133263576.png) ## 运行机制 @@ -24,8 +20,9 @@ - 若CPU访问已缓存至TLB的页表条目,无需再访问保存在内存中的页表,可加快查找速度。 -**图2** CPU访问内存示意图 -![zh-cn_image_0000001179103451](figures/zh-cn_image_0000001179103451.png) + **图2** CPU访问内存示意图 + + ![zh-cn_image_0000001179103451](figures/zh-cn_image_0000001179103451.png) ## 开发指导 @@ -33,15 +30,16 @@ ### 接口说明 -**表1** 虚实映射模块接口 + **表1** MMU相关操作 + +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_ArchMmuQuery | 获取进程空间虚拟地址对应的物理地址以及映射属性。 | +| LOS_ArchMmuMap | 映射进程空间虚拟地址区间与物理地址区间。 | +| LOS_ArchMmuUnmap | 解除进程空间虚拟地址区间与物理地址区间的映射关系。 | +| LOS_ArchMmuChangeProt | 修改进程空间虚拟地址区间的映射属性。 | +| LOS_ArchMmuMove | 将进程空间一个虚拟地址区间的映射关系转移至另一块未使用的虚拟地址区间重新做映射。 | -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| MMU相关操作 | LOS_ArchMmuQuery | 获取进程空间虚拟地址对应的物理地址以及映射属性。 | -| | LOS_ArchMmuMap |映射进程空间虚拟地址区间与物理地址区间。| -| | LOS_ArchMmuUnmap |解除进程空间虚拟地址区间与物理地址区间的映射关系。| -| | LOS_ArchMmuChangeProt |修改进程空间虚拟地址区间的映射属性。| -| | LOS_ArchMmuMove |将进程空间一个虚拟地址区间的映射关系转移至另一块未使用的虚拟地址区间重新做映射。| ### 开发流程 diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md b/zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md index f301f86be53fb5872f11721c84e0896666d26454..ab1018409e3517cf543bf383a51136b23e92f523 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md @@ -1,12 +1,5 @@ # 中断及异常处理 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [结果验证](#结果验证) ## 基本概念 @@ -23,8 +16,9 @@ 以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的入口函数。 -**图1** 中断向量表 -![zh-cn_image_0000001199713709](figures/zh-cn_image_0000001199713709.png) + **图1** 中断向量表 + + ![zh-cn_image_0000001199713709](figures/zh-cn_image_0000001199713709.png) ## 开发指导 @@ -34,14 +28,11 @@ 异常处理为内部机制,不对外提供接口,中断模块提供对外接口如下: -| 功能分类 | **接口名称** | **描述** | -| -------- | -------- | -------- | -| 创建和删除中断 | LOS_HwiCreate | 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序 | -| | LOS_HwiDelete |删除中断| -| 打开和关闭所有中断 | LOS_IntUnLock | 打开当前处理器所有中断响应 | -| | LOS_IntLock |关闭当前处理器所有中断响应| -| | LOS_IntRestore |恢复到使用LOS_IntLock关闭所有中断之前的状态| -| 获取系统支持的最大中断数 | LOS_GetSystemHwiMaximum | 获取系统支持的最大中断数 | + | 功能分类 | 接口描述 | +| -------- | -------- | +| 创建和删除中断 | - LOS_HwiCreate:中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序
- LOS_HwiDelete:删除中断 | +| 打开和关闭所有中断 | - LOS_IntUnLock:打开当前处理器所有中断响应
- LOS_IntLock:关闭当前处理器所有中断响应
- LOS_IntRestore:恢复到使用LOS_IntLock关闭所有中断之前的状态 | +| 获取系统支持的最大中断数 | LOS_GetSystemHwiMaximum:获取系统支持的最大中断数 | ### 开发流程 @@ -65,6 +56,7 @@ 代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI_NUM_TEST产生中断时,会调用中断处理函数: + ``` #include "los_hwi.h" /*中断处理函数*/ @@ -110,6 +102,7 @@ static UINT32 Example_Interrupt(VOID) 编译运行得到的结果为: + ``` Hwi create success! Hwi delete success! diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-memory-heap.md b/zh-cn/device-dev/kernel/kernel-small-basic-memory-heap.md index b48497b6fe520d6016ef3cd1bf33ec82f39e39f1..7c6f4b6b8be51247a66f90c9316b6e397966d807 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-memory-heap.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-memory-heap.md @@ -1,13 +1,5 @@ # 堆内存管理 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [使用场景](#使用场景) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [结果验证](#结果验证) ## 基本概念 @@ -18,21 +10,21 @@ 堆内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。OpenHarmony LiteOS-A堆内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: -**图1** 小型系统动态内存核心算法 -![zh-cn_image_0000001146437734](figures/zh-cn_image_0000001146437734.png) + **图1** 小型系统动态内存核心算法 + ![zh-cn_image_0000001146437734](figures/zh-cn_image_0000001146437734.png) -$$根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[2^{7}$, 2^{31}$],如上图size class所示: +根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[27, 231],如上图size class所示: -1. 对[4,127]区间的内存进行等分,如图1下半部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。[4,127]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 +1. 对[4,127]区间的内存进行等分,如上图下半部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。[4,127]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 -2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见图1上半部分的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。 +2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见上图上半部分的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。 例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间[40,43],第10个空闲链表,位图标记的第10比特位。把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间[2^9,2^9+2^6],第31+2\*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。 -内存管理结构如图2所示: +内存管理结构如下图所示: -**图2** 小型系统动态内存管理结构图 -![zh-cn_image_0000001180855455](figures/zh-cn_image_0000001180855455.png) + **图2** 小型系统动态内存管理结构图 + ![zh-cn_image_0000001180855455](figures/zh-cn_image_0000001180855455.png) - 内存池池头部分 内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。 @@ -53,22 +45,15 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 OpenHarmony LiteOS-A的堆内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 -**表1** 堆内存管理接口 - -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 初始化和删除内存池 | LOS_MemInit | 初始化一块指定的动态内存池,大小为size | -| | LOS_MemDeInit |删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效| -| 申请、释放动态内存 | LOS_MemAlloc | 从指定动态内存池中申请size长度的内存 | -| | LOS_MemFree |释放从指定动态内存中申请的内存| -| | LOS_MemRealloc |按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块| -| | LOS_MemAllocAlign |从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存| -| 获取内存池信息 | LOS_MemPoolSizeGet | 获取指定动态内存池的总大小 | -| | LOS_MemTotalUsedGet |获取指定动态内存池的总使用量大小| -| | LOS_MemInfoGet |获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小| -| | LOS_MemPoolList |打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效| -| 获取内存块信息 | LOS_MemFreeNodeShow | 打印指定内存池的空闲内存块的大小及数量 | -| 检查指定内存池的完整性 | LOS_MemIntegrityCheck | 对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效 | + **表1** 堆内存管理接口 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 初始化和删除内存池 | - LOS_MemInit:初始化一块指定的动态内存池,大小为size
- LOS_MemDeInit:删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效 | +| 申请、释放动态内存 | - LOS_MemAlloc:从指定动态内存池中申请size长度的内存
- LOS_MemFree:释放从指定动态内存中申请的内存
- LOS_MemRealloc:
- 按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块
- LOS_MemAllocAlign:从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存 | +| 获取内存池信息 | - LOS_MemPoolSizeGet:获取指定动态内存池的总大小
- LOS_MemTotalUsedGet:获取指定动态内存池的总使用量大小
- LOS_MemInfoGet:获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小
- LOS_MemPoolList:打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效 | +| 获取内存块信息 | LOS_MemFreeNodeShow:打印指定内存池的空闲内存块的大小及数量 | +| 检查指定内存池的完整性 | LOS_MemIntegrityCheck:对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > - 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS_SYS_MEM_SIZE的大小。 @@ -106,6 +91,7 @@ OpenHarmony LiteOS-A的堆内存管理主要为用户提供以下功能,接口 示例代码如下: + ``` #include "los_memory.h" @@ -176,6 +162,7 @@ UINT32 ExampleDynMemEntry(VOID) 输出结果如下: + ``` Mem init success! Mem alloc success! diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-memory-physical.md b/zh-cn/device-dev/kernel/kernel-small-basic-memory-physical.md index cdcb103fe76dfdf3a0f20817d5863f9024f5bc7c..55792a35546745f8b8fd06e2d145c4684e49ae71 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-memory-physical.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-memory-physical.md @@ -1,12 +1,5 @@ # 物理内存管理 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [结果验证](#结果验证) ## 基本概念 @@ -17,22 +10,24 @@ 如下图所示,LiteOS-A内核的物理内存使用分布视图,主要由内核镜像、内核堆及物理页组成。内核堆部分见堆内存管理一节。 -**图1** 物理内存使用分布图 -![zh-cn_image_0000001179140185](figures/zh-cn_image_0000001179140185.png) + **图1** 物理内存使用分布图 + + ![zh-cn_image_0000001222655518](figures/zh-cn_image_0000001222655518.png) 伙伴算法把所有空闲页帧分成9个内存块组,每组中内存块包含2的幂次方个页帧,例如:第0组的内存块包含2的0次方个页帧,即1个页帧;第8组的内存块包含2的8次方个页帧,即256个页帧。相同大小的内存块挂在同一个链表上进行管理。 - 申请内存 系统申请12KiB内存,即3个页帧时,9个内存块组中索引为3的链表挂着一块大小为8个页帧的内存块满足要求,分配出12KiB内存后还剩余20KiB内存,即5个页帧,将5个页帧分成2的幂次方之和,即4跟1,尝试查找伙伴进行合并。4个页帧的内存块没有伙伴则直接插到索引为2的链表上,继续查找1个页帧的内存块是否有伙伴,索引为0的链表上此时有1个,如果两个内存块地址连续则进行合并,并将内存块挂到索引为1的链表上,否则不做处理。 - **图2** 内存申请示意图 - ![zh-cn_image_0000001189778871](figures/zh-cn_image_0000001189778871.png) + **图2** 内存申请示意图 + ![zh-cn_image_0000001189778871](figures/zh-cn_image_0000001189778871.png) - 释放内存 系统释放12KiB内存,即3个页帧,将3个页帧分成2的幂次方之和,即2跟1,尝试查找伙伴进行合并,索引为1的链表上有1个内存块,若地址连续则合并,并将合并后的内存块挂到索引为2的链表上,索引为0的链表上此时也有1个,如果地址连续则进行合并,并将合并后的内存块挂到索引为1的链表上,此时继续判断是否有伙伴,重复上述操作。 - **图3** 内存释放示意图 - ![zh-cn_image_0000001143739220](figures/zh-cn_image_0000001143739220.png) + **图3** 内存释放示意图 + + ![zh-cn_image_0000001143739220](figures/zh-cn_image_0000001143739220.png) ## 开发指导 @@ -40,18 +35,13 @@ ### 接口说明 -**表1** 物理内存管理模块接口 + **表1** 物理内存管理模块接口 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 申请物理内存 | LOS_PhysPageAlloc | 申请一个物理页 | -| | LOS_PhysPagesAlloc |申请物理页并挂在对应的链表上| -| | LOS_PhysPagesAllocContiguous |申请多页地址连续的物理内存| -| 释放物理内存 | LOS_PhysPageFree | 释放一个物理页 | -| | LOS_PhysPagesFree |释放挂在链表上的物理页| -| | LOS_PhysPagesFreeContiguous |释放多页地址连续的物理内存| -| 查询地址 | LOS_VmPageGet | 根据物理地址获取其对应的物理页结构体指针 | -| | LOS_PaddrToKVaddr |根据物理地址获取其对应的内核虚拟地址| +| 功能分类 | 接口描述 | +| -------- | -------- | +| 申请物理内存 | - LOS_PhysPageAlloc:申请一个物理页
- LOS_PhysPagesAlloc:申请物理页并挂在对应的链表上
- LOS_PhysPagesAllocContiguous:申请多页地址连续的物理内存 | +| 释放物理内存 | - LOS_PhysPageFree:释放一个物理页
- LOS_PhysPagesFree:释放挂在链表上的物理页
- LOS_PhysPagesFreeContiguous:释放多页地址连续的物理内存 | +| 查询地址 | - LOS_VmPageGet:根据物理地址获取其对应的物理页结构体指针
- LOS_PaddrToKVaddr:根据物理地址获取其对应的内核虚拟地址 | ### 开发流程 @@ -70,6 +60,7 @@ 编程示例主要是调用申请、释放接口对内存进行操作,包括申请一个页以及多个页的示例。 + ``` #include "los_vm_phys.h" @@ -176,6 +167,7 @@ UINT32 ExamplePhyMemCaseEntry(VOID) 编译运行得到的结果为: + ``` LOS_PhysPagesAllocContiguous success LOS_PhysPagesAlloc success diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-memory-virtual.md b/zh-cn/device-dev/kernel/kernel-small-basic-memory-virtual.md index 51d6be2faf4739b132c878a90f9d737aed72923b..384d678154192b74b87f5ca4dae1aaa6c51960d9 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-memory-virtual.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-memory-virtual.md @@ -1,10 +1,5 @@ # 虚拟内存管理 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) ## 基本概念 @@ -12,7 +7,7 @@ 系统将虚拟内存分割为称为虚拟页的内存块,大小一般为4KiB或64KiB,LiteOS-A内核默认的页的大小是4KiB,根据需要可以对MMU(Memory Management Units)进行配置。虚拟内存管理操作的最小单位就是一个页,LiteOS-A内核中一个虚拟地址区间region包含地址连续的多个虚拟页,也可只有一个页。同样,物理内存也会按照页大小进行分割,分割后的每个内存块称为页帧。虚拟地址空间划分:内核态占高地址3GiB(0x40000000 ~ 0xFFFFFFFF),用户态占低地址1GiB(0x01000000 ~ 0x3F000000),具体见下表,详细可以查看或配置los_vm_zone.h。 -**表1** 内核态地址规划: + **表1** 内核态地址规划: | Zone名称 | 描述 | 属性 | | -------- | -------- | -------- | @@ -20,7 +15,7 @@ | Normal zone | 加载内核代码段、数据段、堆和栈的地址区间。 | Cache | | high mem zone | 可以分配连续的虚拟内存,但其所映射的物理内存不一定连续。 | Cache | -**表2** 用户态虚地址规划: + **表2** 用户态虚地址规划: | Zone名称 | 描述 | 属性 | | -------- | -------- | -------- | @@ -38,8 +33,9 @@ - CPU访问的虚拟地址所在的页,如V2,没有与具体的物理页做映射,系统会触发缺页异常,系统申请一个物理页,并把相应的信息拷贝到物理页中,并且把物理页的起始地址更新到页表条目中。此时CPU重新执行访问虚拟内存的指令便能够访问到具体的代码或数据。 -**图1** 内存映射示意图 -![zh-cn_image_0000001179142959](figures/zh-cn_image_0000001179142959.png) + **图1** 内存映射示意图 + + ![zh-cn_image_0000001179142959](figures/zh-cn_image_0000001179142959.png) ## 开发指导 @@ -47,46 +43,73 @@ ### 接口说明 -**表3** 虚拟内存管理模块接口 + **表3** 获取进程空间系列接口 | 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | -| 获取进程空间系列接口 | LOS_CurrSpaceGet | 获取当前进程空间结构体指针 | -| | LOS_SpaceGet |获取虚拟地址对应的进程空间结构体指针| -| | LOS_GetKVmSpace |获取内核进程空间结构体指针| -| | LOS_GetVmallocSpace |获取vmalloc空间结构体指针| -| | LOS_GetVmSpaceList |获取进程空间链表指针| -| 虚拟地址区间region相关的操作 | LOS_RegionFind | 在进程空间内查找并返回指定地址对应的虚拟地址区间 | -| | LOS_RegionRangeFind |在进程空间内查找并返回指定地址范围对应的虚拟地址区间| -| | LOS_IsRegionFileValid |判断虚拟地址区间region是否与文件关联映射| -| | LOS_RegionAlloc |申请空闲的虚拟地址区间| -| | LOS_RegionFree |释放进程空间内特定的region| -| | LOS_RegionEndAddr |获取指定地址区间region的结束地址| -| | LOS_RegionSize |获取region的大小| -| | LOS_IsRegionTypeFile |判断是否为文件内存映射| -| | LOS_IsRegionPermUserReadOnly |判断地址区间是否是用户空间只读属性| -| | LOS_IsRegionFlagPrivateOnly |判断地址区间是否是具有私有属性| -| | LOS_SetRegionTypeFile |设置文件内存映射属性| -| | LOS_IsRegionTypeDev |判断是否为设备内存映射| -| | LOS_SetRegionTypeDev |设置设备内存映射属性| -| | LOS_IsRegionTypeAnon |判断是否为匿名映射| -| | LOS_SetRegionTypeAnon |设置匿名映射属性| -| 地址校验 | LOS_IsUserAddress | 判断地址是否在用户态空间 | -| | LOS_IsUserAddressRange |判断地址区间是否在用户态空间| -| | LOS_IsKernelAddress |判断地址是否在内核空间| -| | LOS_IsKernelAddressRange |判断地址区间是否在内核空间| -| | LOS_IsRangeInSpace |判断地址区间是否在进程空间内| -| vmalloc操作 | LOS_VMalloc | vmalloc申请内存 | -| | LOS_VFree |vmalloc释放内存| -| | LOS_IsVmallocAddress |判断地址是否是通过vmalloc申请的| -| 内存申请系列接口 | LOS_KernelMalloc | 当申请的内存小于16KiB时,系统从堆内存池分配内存;当申请的内存超过16KiB时,系统分配多个连续物理页用于内存分配 | -| | LOS_KernelMallocAlign |申请具有对齐属性的内存,申请规则同LOS_KernelMalloc接口| -| | LOS_KernelFree |释放由LOS_KernelMalloc和LOS_KernelMallocAlign接口申请的内存| -| | LOS_KernelRealloc |重新分配由LOS_KernelMalloc和LOS_KernelMallocAlign接口申请的内存| -| 其他 | LOS_PaddrQuery | 根据虚拟地址获取对应的物理地址 | -| | LOS_VmSpaceFree |释放进程空间,包括虚拟内存区间、页表等信息| -| | LOS_VmSpaceReserve |在进程空间中预留一块内存空间| -| | LOS_VaddrToPaddrMmap |将指定长度的物理地址区间与虚拟地址区间做映射,需提前申请物理地址区间| +| LOS_CurrSpaceGet | 获取当前进程空间结构体指针 | +| LOS_SpaceGet | 获取虚拟地址对应的进程空间结构体指针 | +| LOS_GetKVmSpace | 获取内核进程空间结构体指针 | +| LOS_GetVmallocSpace | 获取vmalloc空间结构体指针 | +| LOS_GetVmSpaceList | 获取进程空间链表指针 | + + + **表4** 虚拟地址区间region相关的操作 + +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_RegionFind | 在进程空间内查找并返回指定地址对应的虚拟地址区间 | +| LOS_RegionRangeFind | 在进程空间内查找并返回指定地址范围对应的虚拟地址区间 | +| LOS_IsRegionFileValid | 判断虚拟地址区间region是否与文件关联映射 | +| LOS_RegionAlloc | 申请空闲的虚拟地址区间 | +| LOS_RegionFree | 释放进程空间内特定的region | +| LOS_RegionEndAddr | 获取指定地址区间region的结束地址 | +| LOS_RegionSize | 获取region的大小 | +| LOS_IsRegionTypeFile | 判断是否为文件内存映射 | +| LOS_IsRegionPermUserReadOnly | 判断地址区间是否是用户空间只读属性 | +| LOS_IsRegionFlagPrivateOnly | 判断地址区间是否是具有私有属性 | +| LOS_SetRegionTypeFile | 设置文件内存映射属性 | +| LOS_IsRegionTypeDev | 判断是否为设备内存映射 | +| LOS_SetRegionTypeDev | 设置设备内存映射属性 | +| LOS_IsRegionTypeAnon | 判断是否为匿名映射 | +| LOS_SetRegionTypeAnon | 设置匿名映射属性 | + + **表5** 地址校验 + +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_IsUserAddress | 判断地址是否在用户态空间 | +| LOS_IsUserAddressRange | 判断地址区间是否在用户态空间 | +| LOS_IsKernelAddress | 判断地址是否在内核空间 | +| LOS_IsKernelAddressRange | 判断地址区间是否在内核空间 | +| LOS_IsRangeInSpace | 判断地址区间是否在进程空间内 | + + **表6** vmalloc操作 + +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_VMalloc | vmalloc申请内存 | +| LOS_VFree | vmalloc释放内存 | +| LOS_IsVmallocAddress | 判断地址是否是通过vmalloc申请的 | + + **表7** 内存申请系列接口 + +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_KernelMalloc | 当申请的内存小于16KiB时,系统从堆内存池分配内存;当申请的内存超过16KiB时,系统分配多个连续物理页用于内存分配 | +| LOS_KernelMallocAlign | 申请具有对齐属性的内存,申请规则同LOS_KernelMalloc接口 | +| LOS_KernelFree | 释放由LOS_KernelMalloc和LOS_KernelMallocAlign接口申请的内存 | +| LOS_KernelRealloc | 重新分配由LOS_KernelMalloc和LOS_KernelMallocAlign接口申请的内存 | + + **表8** 其他 + +| | | +| -------- | -------- | +| **接口名称** | **描述** | +| LOS_PaddrQuery | 根据虚拟地址获取对应的物理地址 | +| LOS_VmSpaceFree | 释放进程空间,包括虚拟内存区间、页表等信息 | +| LOS_VmSpaceReserve | 在进程空间中预留一块内存空间 | +| LOS_VaddrToPaddrMmap | 将指定长度的物理地址区间与虚拟地址区间做映射,需提前申请物理地址区间 | ### 开发流程 diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-memory.md b/zh-cn/device-dev/kernel/kernel-small-basic-memory.md index 20c76afadf55e0a3f815be9320bde43a93b45e9d..0f99bb05bdd461d19d3e527915419e7bda7621c5 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-memory.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-memory.md @@ -1,6 +1,7 @@ # 内存管理 + - **[堆内存管理](kernel-small-basic-memory-heap.md)** - **[物理内存管理](kernel-small-basic-memory-physical.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-process-process.md b/zh-cn/device-dev/kernel/kernel-small-basic-process-process.md index 42ce52464fc75475b6265a306696d7e4b1a424d6..388c81166d1afafb8a86dda0a59567394985ae90 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-process-process.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-process-process.md @@ -1,10 +1,5 @@ # 进程 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) ## 基本概念 @@ -34,8 +29,9 @@ - 僵尸(Zombies):进程运行结束,等待父进程回收其控制块资源。 -**图1** 进程状态迁移示意图 -![zh-cn_image_0000001219007317](figures/zh-cn_image_0000001219007317.png) + **图1** 进程状态迁移示意图 + + ![zh-cn_image_0000001219007317](figures/zh-cn_image_0000001219007317.png) **进程状态迁移说明:** @@ -72,8 +68,9 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离, 进程只是资源管理单元,实际运行是由进程内的各个线程完成的,不同进程内的线程相互切换时会进行进程空间的切换。 -**图2** 进程管理示意图 -![zh-cn_image_0000001199736949](figures/zh-cn_image_0000001199736949.png) + **图2** 进程管理示意图 + + ![zh-cn_image_0000001199736949](figures/zh-cn_image_0000001199736949.png) ## 开发指导 @@ -81,22 +78,16 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离, ### 接口说明 -**表1** 进程管理模块接口 - -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 进程调度参数控制 | LOS_GetProcessScheduler | 获取指定进程的调度策略 | -| | LOS_SetProcessScheduler |设置指定进程的调度参数,包括优先级和调度策略| -| | LOS_GetProcessPriority |获取指定进程的优先级| -| | LOS_SetProcessPriority |设置指定进程的优先级| -| 等待回收子进程 | LOS_Wait | 等待子进程结束并回收子进程 | -| 进程组 | LOS_GetProcessGroupID | 获取指定进程的进程组ID | -| | LOS_GetCurrProcessGroupID |获取当前进程的进程组ID| -| 获取进程ID | LOS_GetCurrProcessID | 获取当前进程的进程ID | -| 用户及用户组 | LOS_GetUserID | 获取当前进程的用户ID | -| | LOS_GetGroupID |获取当前进程的用户组ID| -| | LOS_CheckInGroups |检查指定用户组ID是否在当前进程的用户组内| -| 系统支持的最大进程数 | LOS_GetSystemProcessMaximum | 获取系统支持的最大进程数目 | + **表1** 进程管理模块接口 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 进程调度参数控制 | - LOS_GetProcessScheduler:获取指定进程的调度策略
- LOS_SetProcessScheduler:设置指定进程的调度参数,包括优先级和调度策略 | +| 等待回收子进程 | LOS_Wait:等待子进程结束并回收子进程 | +| 进程组 | - LOS_GetProcessGroupID:获取指定进程的进程组ID
- LOS_GetCurrProcessGroupID:获取当前进程的进程组ID | +| 获取进程ID | LOS_GetCurrProcessID:获取当前进程的进程ID | +| 用户及用户组 | - LOS_GetUserID:获取当前进程的用户ID
- LOS_GetGroupID:获取当前进程的用户组ID
- LOS_CheckInGroups:检查指定用户组ID是否在当前进程的用户组内 | +| 系统支持的最大进程数 | LOS_GetSystemProcessMaximum:获取系统支持的最大进程数目 | ### 开发流程 diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-process-scheduler.md b/zh-cn/device-dev/kernel/kernel-small-basic-process-scheduler.md index 880cc6a7527a12f24c4ad910d0409e90fdd703f7..8a6609d70d616c72d24a878e9adecde79bb16ca6 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-process-scheduler.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-process-scheduler.md @@ -1,10 +1,5 @@ # 调度器 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) ## 基本概念 @@ -21,13 +16,14 @@ OpenHarmony 调度的最小单元为线程。 OpenHarmony 采用进程优先级队列+线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。 -**图1** 调度优先级桶队列示意图 -![zh-cn_image_0000001199705711](figures/zh-cn_image_0000001199705711.png) + **图1** 调度优先级桶队列示意图 + + ![zh-cn_image_0000001199705711](figures/zh-cn_image_0000001199705711.png) OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中创建的进程或线程会被加入到调度队列,系统根据进程和线程的优先级及线程的时间片消耗情况选择最优的线程进行调度运行,线程一旦调度到就会从调度队列上删除,线程在运行过程中发生阻塞,会被加入到对应的阻塞队列中并触发一次调度,调度其它线程运行。如果调度队列上没有可以调度的线程,则系统就会选择KIdle进程的线程进行调度运行。 -**图2** 调度流程示意图 -![zh-cn_image_0000001199706239](figures/zh-cn_image_0000001199706239.png) + **图2** 调度流程示意图 + ![zh-cn_image_0000001199706239](figures/zh-cn_image_0000001199706239.png) ## 开发指导 @@ -35,7 +31,7 @@ OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中 ### 接口说明 -| 功能分类 | 接口**名称** | 描述 | + | 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | | 触发系统调度 | LOS_Schedule | 触发系统调度 | diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md b/zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md index 1041d75552b1f5981f8d2331880b29d1cb17cd7e..e5dc3baad0229fbd450390a8391f3f333f6d2f89 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md @@ -1,11 +1,5 @@ # 任务 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -33,8 +27,9 @@ OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0 - 退出(Exit):任务运行结束,等待父任务回收其控制块资源。 -**图1** 任务状态迁移示意图 -![zh-cn_image_0000001173399977](figures/zh-cn_image_0000001173399977.png) + **图1** 任务状态迁移示意图 + + ![zh-cn_image_0000001173399977](figures/zh-cn_image_0000001173399977.png) **任务状态迁移说明:** @@ -72,29 +67,16 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起 ### 接口说明 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 任务的创建和删除 | LOS_TaskCreateOnly | 创建任务,并使该任务进入Init状态,不执行任务调度 | -| | LOS_TaskCreate |创建任务,并使该任务进入Ready状态,并调度| -| | LOS_TaskDelete |删除指定的任务| -| 任务状态控制 | LOS_TaskResume | 恢复挂起的任务 | -| | LOS_TaskSuspend |挂起指定的任务| -| | LOS_TaskJoin |挂起当前任务,等待指定任务运行结束并回收其任务控制块资源| -| | LOS_TaskDetach |修改任务的joinable属性为detach属性,detach属性的任务运行结束会自动回收任务控制块资源| -| | LOS_TaskDelay |任务延时等待| -| | LOS_TaskYield |显式放权,调整调用任务优先级的任务调度顺序| -| 任务调度的控制 | LOS_TaskLock | 锁任务调度 | -| | LOS_TaskUnlock |解锁任务调度| -| 任务优先级的控制 | LOS_CurTaskPriSet | 设置当前任务的优先级 | -| | LOS_TaskPriSet |设置指定任务的优先级| -| | LOS_TaskPriGet |获取指定任务的优先级| -| 任务信息获取 | LOS_CurTaskIDGet | 获取当前任务的ID | -| | LOS_TaskInfoGet |获取指定任务的信息| -| 任务绑核操作 | LOS_TaskCpuAffiSet | 绑定指定任务到指定cpu上运行,仅在多核下使用 | -| | LOS_TaskCpuAffiGet |获取指定任务的绑核信息,仅在多核下使用| -| 任务调度参数的控制 | LOS_GetTaskScheduler | 获取指定任务的调度策略 | -| | LOS_SetTaskScheduler |设置指定任务的调度参数,包括优先级和调度策略| -| 系统支持的最大任务数 | LOS_GetSystemTaskMaximum | 获取系统支持的最大任务数目 | + | 功能分类 | 接口描述 | +| -------- | -------- | +| 任务的创建和删除 | - LOS_TaskCreate:创建任务,并使该任务进入Init状态,不执行任务调度
- LOS_TaskDelete:创建任务,并使该任务进入Ready状态,并调度
- LOS_TaskDelete:删除指定的任务 | +| 任务状态控制 | - LOS_TaskResume:恢复挂起的任务
- LOS_TaskSuspend:挂起指定的任务
- LOS_TaskJoin:挂起当前任务,等待指定任务运行结束并回收其任务控制块资源
- LOS_TaskDetach:修改任务的joinable属性为detach属性,detach属性的任务运行结束会自动回收任务控制块资源
- LOS_TaskDelay:任务延时等待
- LOS_TaskYield:显式放权,调整调用任务优先级的任务调度顺序 | +| 任务调度的控制 | - LOS_TaskLock:锁任务调度
- LOS_TaskUnlock:解锁任务调度 | +| 任务优先级的控制 | - LOS_CurTaskPriSet:设置当前任务的优先级
- LOS_TaskPriSet:设置指定任务的优先级
- LOS_TaskPriGet:获取指定任务的优先级 | +| 任务信息获取 | - LOS_CurTaskIDGet:获取当前任务的ID
- LOS_TaskInfoGet:获取指定任务的信息 | +| 任务绑核操作 | - LOS_TaskCpuAffiSet:绑定指定任务到指定cpu上运行,仅在多核下使用
- LOS_TaskCpuAffiGet:获取指定任务的绑核信息,仅在多核下使用 | +| 任务调度参数的控制 | - LOS_GetTaskScheduler:获取指定任务的调度策略
- LOS_SetTaskScheduler:设置指定任务的调度参数,包括优先级和调度策略 | +| 系统支持的最大任务数 | LOS_GetSystemTaskMaximum | ### 开发流程 @@ -123,6 +105,7 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起 代码实现如下: + ``` UINT32 g_taskLoID; UINT32 g_taskHiID; @@ -225,6 +208,7 @@ UINT32 ExampleTaskCaseEntry(VOID) 编译运行得到的结果为: + ``` LOS_TaskLock() Success! ExampleTaskHi create Success! diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-process.md b/zh-cn/device-dev/kernel/kernel-small-basic-process.md index e3cb98c2854a6dd480426425e8caf641f88e0c3a..fafdd834963248fdd46ecdcd09bb5e82996a17fb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-process.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-process.md @@ -1,6 +1,7 @@ # 进程管理 + - **[进程](kernel-small-basic-process-process.md)** - **[任务](kernel-small-basic-process-thread.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-softtimer.md b/zh-cn/device-dev/kernel/kernel-small-basic-softtimer.md index 54fa23cdeb00f08a715c9238debe5682e7f4892e..230c1bd90b092e73b4885b1700997be80b604254 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-softtimer.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-softtimer.md @@ -1,11 +1,5 @@ # 软件定时器 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -63,15 +57,13 @@ OpenHarmony系统的软件定时器提供三类定时器机制: OpenHarmony LiteOS-A内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 软件定时器接口说明 + **表1** 软件定时器接口说明 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 创建、删除定时器 | LOS_SwtmrCreate | 创建软件定时器 | -| | LOS_SwtmrDelete |删除软件定时器| -| 启动、停止定时器 | LOS_SwtmrStart | 启动软件定时器 | -| | LOS_SwtmrStop |停止软件定时器| -| 获得软件定时剩余Tick数 | LOS_SwtmrTimeGet | 获得软件定时器剩余Tick数 | +| 功能分类 | 接口描述 | +| -------- | -------- | +| 创建、删除定时器 | LOS_SwtmrCreate:创建软件定时器
LOS_SwtmrDelete:删除软件定时器 | +| 启动、停止定时器 | LOS_SwtmrStart:启动软件定时器
LOS_SwtmrStop:停止软件定时器 | +| 获得软件定时剩余Tick数 | LOS_SwtmrTimeGet:获得软件定时器剩余Tick数 | ### 开发流程 @@ -117,7 +109,8 @@ OpenHarmony LiteOS-A内核的软件定时器模块提供下面几种功能,接 - 配置好OS_SWTMR_HANDLE_QUEUE_SIZE软件定时器队列最大长度。 -**编程示例** + **编程示例** + ``` #include "los_swtmr.h" @@ -183,6 +176,7 @@ void Timer_example(void) **运行结果** + ``` create Timer1 success start Timer1 success diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-time.md b/zh-cn/device-dev/kernel/kernel-small-basic-time.md index 7991f2a1133c29c13ffbb258aefbb3418d20e9d8..b378ef425340cd8c5f667c5e8dd42d1bfd58ffa6 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-time.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-time.md @@ -1,10 +1,5 @@ # 时间管理 -- [基本概念](#基本概念) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -30,14 +25,12 @@ OpenHarmony系统的时间管理模块提供时间转换、统计、延迟功能 OpenHarmony LiteOS-A内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 -**表1** 时间管理相关接口说明 + **表1** 时间管理相关接口说明 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 时间转换 | LOS_MS2Tick | 毫秒转换成Tick | -| | LOS_Tick2MS |Tick转换成毫秒| -| 时间统计 | LOS_TickCountGet | 获取当前Tick数 | -| | LOS_CyclePerTickGet |每个Tick的cycle数| +| 功能分类 | 接口描述 | +| -------- | -------- | +| 时间转换 | LOS_MS2Tick:毫秒转换成Tick
LOS_Tick2MS:Tick转换成毫秒 | +| 时间统计 | LOS_TickCountGet:获取当前Tick数
LOS_CyclePerTickGet:每个Tick的cycle数 | ### 开发流程 @@ -64,7 +57,8 @@ OpenHarmony LiteOS-A内核的时间管理提供下面几种功能,接口详细 **示例代码** -时间转换: + 时间转换: + ``` VOID Example_TransformTime(VOID) { @@ -79,6 +73,7 @@ VOID Example_TransformTime(VOID) 时间统计和时间延迟: + ``` VOID Example_GetTime(VOID) { @@ -111,6 +106,7 @@ VOID Example_GetTime(VOID) 时间转换: + ``` uwTick = 10000 uwMs = 100 @@ -118,6 +114,7 @@ uwMs = 100 时间统计和时间延迟: + ``` LOS_CyclePerTickGet = 49500 LOS_TickCountGet = 5042 diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md index ee8d3eec26df29b7815c2aa3ea43a88af7928f0f..a1d647c2a1fc841cd3242a0b760ea43629c17725 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md @@ -1,16 +1,5 @@ # 事件 -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [事件控制块](#事件控制块) - - [事件运作原理](#事件运作原理) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [编程示例](#编程示例) - - [结果验证](#结果验证) ## 基本概念 @@ -42,6 +31,7 @@ OpenHarmony LiteOS-A的事件模块提供的事件,具有如下特点: ### 事件控制块 + ``` /** * 事件控制块数据结构 @@ -73,8 +63,8 @@ typedef struct tagEvent { **事件销毁**:销毁指定的事件控制块。 -**图1** 小型系统事件运作原理图 -![zh-cn_image_0000001180952545](figures/zh-cn_image_0000001180952545.png) + **图1** 小型系统事件运作原理图 + ![zh-cn_image_0000001180952545](figures/zh-cn_image_0000001180952545.png) ## 开发指导 @@ -84,16 +74,15 @@ typedef struct tagEvent { OpenHarmony LiteOS-A内核的事件模块提供下面几种功能。 -**表1** 事件模块接口 + **表1** 事件模块接口 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 初始化事件 | LOS_EventInit | 初始化一个事件控制块 | -| 读/写事件 | LOS_EventRead | 读取指定事件类型,超时时间为相对时间:单位为Tick | -| | LOS_EventWrite |写指定的事件类型| -| 清除事件 | LOS_EventClear | 清除指定的事件类型 | -| 校验事件掩码 | LOS_EventPoll | 根据用户传入的事件ID、事件掩码及读取模式,返回用户传入的事件是否符合预期 | -| 销毁事件 | LOS_EventDestroy | 销毁指定的事件控制块 | +| 功能分类 | 接口描述 | +| -------- | -------- | +| 初始化事件 | LOS_EventInit:初始化一个事件控制块 | +| 读/写事件 | - LOS_EventRead:读取指定事件类型,超时时间为相对时间:单位为Tick
- LOS_EventWrite:写指定的事件类型 | +| 清除事件 | LOS_EventClear:清除指定的事件类型 | +| 校验事件掩码 | - LOS_EventPoll:根据用户传入的事件ID、事件掩码及读取模式,返回用户传入的事件是否符合预期
- LOS_EventDestroy:销毁指定的事件控制块 | +| 销毁事件 | LOS_EventDestroy:销毁指定的事件控制块 | ### 开发流程 @@ -140,6 +129,7 @@ OpenHarmony LiteOS-A内核的事件模块提供下面几种功能。 示例代码如下: + ``` #include "los_event.h" #include "los_task.h" @@ -224,6 +214,7 @@ UINT32 Example_EventEntry(VOID) 编译运行得到的结果为: + ``` Example_Event wait event 0x1 Example_TaskEntry write event. diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md index 7733c14375fa9d75b03bf6ad9147b0ebb4b1b794..8bebc6f1cbb3bf8b0a9ab3825a62169561ac215d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md @@ -1,11 +1,5 @@ # 互斥锁 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -40,8 +34,8 @@ 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 -**图1** 小型系统互斥锁运作示意图 -![zh-cn_image_0000001177654887](figures/zh-cn_image_0000001177654887.png) + **图1** 小型系统互斥锁运作示意图 + ![zh-cn_image_0000001177654887](figures/zh-cn_image_0000001177654887.png) ## 开发指导 @@ -49,26 +43,14 @@ ### 接口说明 -**表1** 互斥锁模块接口 - -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 初始化和销毁互斥锁 | LOS_MuxInit | 互斥锁初始化 | -| | LOS_MuxDestroy |销毁指定的互斥锁| -| 互斥锁的申请和释放 | LOS_MuxLock | 申请指定的互斥锁 | -| | LOS_MuxTrylock |尝试申请指定的互斥锁,不阻塞| -| | LOS_MuxUnlock |释放指定的互斥锁| -| 校验互斥锁 | LOS_MuxIsValid | 判断互斥锁释放有效 | -| 初始化和销毁互斥锁属性 | LOS_MuxAttrInit | 互斥锁属性初始化 | -| | LOS_MuxAttrDestroy |销毁指定的互斥锁属性| -| 设置和获取互斥锁属性 | LOS_MuxAttrGetType | 获取指定互斥锁属性的类型属性 | -| | LOS_MuxAttrSetType |设置指定互斥锁属性的类型属性| -| | LOS_MuxAttrGetProtocol |获取指定互斥锁属性的协议属性| -| | LOS_MuxAttrSetProtocol |设置指定互斥锁属性的协议属性| -| | LOS_MuxAttrGetPrioceiling |获取指定互斥锁属性的优先级上限属性| -| | LOS_MuxAttrSetPrioceiling |设置指定互斥锁属性的优先级上限属性| -| | LOS_MuxGetPrioceiling |获取互斥锁优先级上限属性| -| | LOS_MuxSetPrioceiling |设置互斥锁优先级上限属性| + **表1** 互斥锁模块接口 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 初始化和销毁互斥锁 | - LOS_MuxInit:互斥锁初始化
- LOS_MuxDestroy:销毁指定的互斥锁 | +| 互斥锁的申请和释放 | - LOS_MuxLock:申请指定的互斥锁
- LOS_MuxTrylock:尝试申请指定的互斥锁,不阻塞
- LOS_MuxUnlock:释放指定的互斥锁 | +| 校验互斥锁 | - LOS_MuxIsValid:判断互斥锁释放有效
- LOS_MuxAttrDestroy:销毁指定的互斥锁属性 | +| 设置和获取互斥锁属性 | - LOS_MuxAttrGetType:获取指定互斥锁属性的类型属性
- LOS_MuxAttrSetType:设置指定互斥锁属性的类型属性
- LOS_MuxAttrGetProtocol:获取指定互斥锁属性的协议属性
- LOS_MuxAttrSetProtocol:设置指定互斥锁属性的协议属性
- LOS_MuxAttrGetPrioceiling:获取指定互斥锁属性的优先级上限属性
- LOS_MuxAttrSetPrioceiling:设置指定互斥锁属性的优先级上限属性
- LOS_MuxGetPrioceiling:获取互斥锁优先级上限属性
- LOS_MuxSetPrioceiling:设置互斥锁优先级上限属性 | ### 开发流程 @@ -121,6 +103,7 @@ 示例代码如下: + ``` #include #include "los_mux.h" @@ -226,6 +209,7 @@ UINT32 Example_MutexEntry(VOID) 编译运行得到的结果为: + ``` task1 try to get mutex, wait 10 ticks. task2 try to get mutex, wait forever. diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md index bb7baf57ea7a5f580689dd86f80223b06eb4c62c..cdf3f64c4fa5a7d9c7df3d71481568661c23d1bb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md @@ -1,245 +1,233 @@ -# 消息队列 - -- [基本概念](#基本概念) -- [运行机制](#运行机制) - - [队列控制块](#队列控制块) - - [队列运作原理](#队列运作原理) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) -- [编程实例](#编程实例) - - [实例描述](#实例描述) - - [编程示例](#编程示例) - - [结果验证](#结果验证) - -## 基本概念 - -队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 - -任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 - -可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 - -消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: - -- 消息以先进先出的方式排队,支持异步读写。 - -- 读队列和写队列都支持超时机制。 - -- 每读取一条消息,就会将该消息节点设置为空闲。 - -- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 - -- 一个任务能够从任意一个消息队列接收和发送消息。 - -- 多个任务能够从同一个消息队列接收和发送消息。 - -- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 - - -## 运行机制 - - -### 队列控制块 - -``` -/** - * 队列控制块数据结构 - */ -typedef struct { - UINT8 *queueHandle; /**< Pointer to a queue handle */ - UINT16 queueState; /**< Queue state */ - UINT16 queueLen; /**< Queue length */ - UINT16 queueSize; /**< Node size */ - UINT32 queueID; /**< queueID */ - UINT16 queueHead; /**< Node head */ - UINT16 queueTail; /**< Node tail */ - UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable */ - LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */ - LOS_DL_LIST memList; /**< Pointer to the memory linked list */ -} LosQueueCB; -``` - -每个队列控制块中都含有队列状态,表示该队列的使用情况: - -- OS_QUEUE_UNUSED:队列未被使用。 - -- OS_QUEUE_INUSED:队列被使用中。 - - -### 队列运作原理 - -- 创建队列时,创建队列成功会返回队列ID。 - -- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 - -- 写队列时,根据readWriteableCnt[1]判断队列是否可以写入,不能对已满(readWriteableCnt[1]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 - -- 读队列时,根据readWriteableCnt[0]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt[0]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 - -- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 - -**图1** 队列读写数据操作示意图 -![zh-cn_image_0000001132875772](figures/zh-cn_image_0000001132875772.png) - -上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 - - -## 开发指导 - - -### 接口说明 - -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 创建/删除消息队列 | LOS_QueueCreate | 创建一个消息队列,由系统动态申请队列空间 | -| | LOS_QueueDelete |根据队列ID删除一个指定队列| -| 读/写队列(不带拷贝) | LOS_QueueRead | 读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址) | -| | LOS_QueueWrite |向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)| -| | LOS_QueueWriteHead |向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)| -| 读/写队列(带拷贝) | LOS_QueueReadCopy | 读取指定队列头节点中的数据 | -| | LOS_QueueWriteCopy |向指定队列尾节点中写入入参bufferAddr中保存的数据| -| | LOS_QueueWriteHeadCopy |向指定队列头节点中写入入参bufferAddr中保存的数据| -| 获取队列信息 | LOS_QueueInfoGet | 获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务 | - - -### 开发流程 - -1. 用LOS_QueueCreate创建队列。创建成功后,可以得到队列ID。 - -2. 通过LOS_QueueWrite或者LOS_QueueWriteCopy写队列。 - -3. 通过LOS_QueueRead或者LOS_QueueReadCopy读队列。 - -4. 通过LOS_QueueInfoGet获取队列信息。 - -5. 通过LOS_QueueDelete删除队列。 - -> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> - 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 -> -> - 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 -> -> - 队列接口函数中的入参timeOut是相对时间。 -> -> - LOS_QueueReadCopy和LOS_QueueWriteCopy及LOS_QueueWriteHeadCopy是一组接口,LOS_QueueRead和LOS_QueueWrite及LOS_QueueWriteHead是一组接口,每组接口需要配套使用。 -> -> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 -> +# 消息队列 + + +## 基本概念 + +队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 + +任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 + +可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 + +消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: + +- 消息以先进先出的方式排队,支持异步读写。 + +- 读队列和写队列都支持超时机制。 + +- 每读取一条消息,就会将该消息节点设置为空闲。 + +- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 + +- 一个任务能够从任意一个消息队列接收和发送消息。 + +- 多个任务能够从同一个消息队列接收和发送消息。 + +- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 + + +## 运行机制 + + +### 队列控制块 + + +``` +/** + * 队列控制块数据结构 + */ +typedef struct { + UINT8 *queueHandle; /**< Pointer to a queue handle */ + UINT16 queueState; /**< Queue state */ + UINT16 queueLen; /**< Queue length */ + UINT16 queueSize; /**< Node size */ + UINT32 queueID; /**< queueID */ + UINT16 queueHead; /**< Node head */ + UINT16 queueTail; /**< Node tail */ + UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable */ + LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */ + LOS_DL_LIST memList; /**< Pointer to the memory linked list */ +} LosQueueCB; +``` + +每个队列控制块中都含有队列状态,表示该队列的使用情况: + +- OS_QUEUE_UNUSED:队列未被使用。 + +- OS_QUEUE_INUSED:队列被使用中。 + + +### 队列运作原理 + +- 创建队列时,创建队列成功会返回队列ID。 + +- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 + +- 写队列时,根据readWriteableCnt[1]判断队列是否可以写入,不能对已满(readWriteableCnt[1]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 + +- 读队列时,根据readWriteableCnt[0]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt[0]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 + +- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 + + **图1** 队列读写数据操作示意图 + + ![zh-cn_image_0000001132875772](figures/zh-cn_image_0000001132875772.png) + +上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 + + +## 开发指导 + + +### 接口说明 + + | 功能分类 | 接口描述 | +| -------- | -------- | +| 创建/删除消息队列 | - LOS_QueueCreate:创建一个消息队列,由系统动态申请队列空间
- LOS_QueueDelete:根据队列ID删除一个指定队列 | +| 读/写队列(不带拷贝) | - LOS_QueueRead:读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)
- LOS_QueueWrite:向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)
- LOS_QueueWriteHead:向指定队列头节点中写入入参bufferAddr的值(即buffer的地址) | +| 读/写队列(带拷贝) | - LOS_QueueReadCopy:读取指定队列头节点中的数据
- LOS_QueueWriteCopy:向指定队列尾节点中写入入参bufferAddr中保存的数据
- LOS_QueueWriteHeadCopy:向指定队列头节点中写入入参bufferAddr中保存的数据 | +| 获取队列信息 | LOS_QueueInfoGet:获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务 | + + +### 开发流程 + +1. 用LOS_QueueCreate创建队列。创建成功后,可以得到队列ID。 + +2. 通过LOS_QueueWrite或者LOS_QueueWriteCopy写队列。 + +3. 通过LOS_QueueRead或者LOS_QueueReadCopy读队列。 + +4. 通过LOS_QueueInfoGet获取队列信息。 + +5. 通过LOS_QueueDelete删除队列。 + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> - 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 +> +> - 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 +> +> - 队列接口函数中的入参timeOut是相对时间。 +> +> - LOS_QueueReadCopy和LOS_QueueWriteCopy及LOS_QueueWriteHeadCopy是一组接口,LOS_QueueRead和LOS_QueueWrite及LOS_QueueWriteHead是一组接口,每组接口需要配套使用。 +> +> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 +> > - LOS_QueueRead和LOS_QueueReadCopy接口的读取长度如果小于消息实际长度,消息将被截断。 -> -> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 - - -## 编程实例 - - -### 实例描述 - -创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 - -1. 通过LOS_TaskCreate创建任务1和任务2。 - -2. 通过LOS_QueueCreate创建一个消息队列。 - -3. 在任务1 SendEntry中发送消息。 - -4. 在任务2 RecvEntry中接收消息。 - -5. 通过LOS_QueueDelete删除队列。 - - -### 编程示例 - -示例代码如下: - -``` -#include "los_task.h" -#include "los_queue.h" -static UINT32 g_queue; -#define BUFFER_LEN 50 - -VOID SendEntry(VOID) -{ - UINT32 ret = 0; - CHAR abuf[] = "test message"; - UINT32 len = sizeof(abuf); - - ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); - if(ret != LOS_OK) { - printf("send message failure, error: %x\n", ret); - } -} - -VOID RecvEntry(VOID) -{ - UINT32 ret = 0; - CHAR readBuf[BUFFER_LEN] = {0}; - UINT32 readLen = BUFFER_LEN; - - //休眠1s - usleep(1000000); - ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); - if(ret != LOS_OK) { - printf("recv message failure, error: %x\n", ret); - } - - printf("recv message: %s\n", readBuf); - - ret = LOS_QueueDelete(g_queue); - if(ret != LOS_OK) { - printf("delete the queue failure, error: %x\n", ret); - } - - printf("delete the queue success!\n"); -} - -UINT32 ExampleQueue(VOID) -{ - printf("start queue example\n"); - UINT32 ret = 0; - UINT32 task1, task2; - TSK_INIT_PARAM_S initParam = {0}; - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; - initParam.usTaskPrio = 9; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - initParam.pcName = "SendQueue"; - - LOS_TaskLock(); - ret = LOS_TaskCreate(&task1, &initParam); - if(ret != LOS_OK) { - printf("create task1 failed, error: %x\n", ret); - return ret; - } - - initParam.pcName = "RecvQueue"; - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; - ret = LOS_TaskCreate(&task2, &initParam); - if(ret != LOS_OK) { - printf("create task2 failed, error: %x\n", ret); - return ret; - } - - ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); - if(ret != LOS_OK) { - printf("create queue failure, error: %x\n", ret); - } - - printf("create the queue success!\n"); - LOS_TaskUnlock(); - return ret; -} -``` - - -### 结果验证 - -编译运行得到的结果为: - -``` -start test example -create the queue success! -recv message: test message -delete the queue success! -``` +> +> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 + + +## 编程实例 + + +### 实例描述 + +创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 + +1. 通过LOS_TaskCreate创建任务1和任务2。 + +2. 通过LOS_QueueCreate创建一个消息队列。 + +3. 在任务1 SendEntry中发送消息。 + +4. 在任务2 RecvEntry中接收消息。 + +5. 通过LOS_QueueDelete删除队列。 + + +### 编程示例 + +示例代码如下: + + +``` +#include "los_task.h" +#include "los_queue.h" +static UINT32 g_queue; +#define BUFFER_LEN 50 + +VOID SendEntry(VOID) +{ + UINT32 ret = 0; + CHAR abuf[] = "test message"; + UINT32 len = sizeof(abuf); + + ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); + if(ret != LOS_OK) { + printf("send message failure, error: %x\n", ret); + } +} + +VOID RecvEntry(VOID) +{ + UINT32 ret = 0; + CHAR readBuf[BUFFER_LEN] = {0}; + UINT32 readLen = BUFFER_LEN; + + //休眠1s + usleep(1000000); + ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); + if(ret != LOS_OK) { + printf("recv message failure, error: %x\n", ret); + } + + printf("recv message: %s\n", readBuf); + + ret = LOS_QueueDelete(g_queue); + if(ret != LOS_OK) { + printf("delete the queue failure, error: %x\n", ret); + } + + printf("delete the queue success!\n"); +} + +UINT32 ExampleQueue(VOID) +{ + printf("start queue example\n"); + UINT32 ret = 0; + UINT32 task1, task2; + TSK_INIT_PARAM_S initParam = {0}; + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; + initParam.usTaskPrio = 9; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + initParam.pcName = "SendQueue"; + + LOS_TaskLock(); + ret = LOS_TaskCreate(&task1, &initParam); + if(ret != LOS_OK) { + printf("create task1 failed, error: %x\n", ret); + return ret; + } + + initParam.pcName = "RecvQueue"; + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; + ret = LOS_TaskCreate(&task2, &initParam); + if(ret != LOS_OK) { + printf("create task2 failed, error: %x\n", ret); + return ret; + } + + ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); + if(ret != LOS_OK) { + printf("create queue failure, error: %x\n", ret); + } + + printf("create the queue success!\n"); + LOS_TaskUnlock(); + return ret; +} +``` + + +### 结果验证 + +编译运行得到的结果为: + + +``` +start test example +create the queue success! +recv message: test message +delete the queue success! +``` diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-rwlock.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-rwlock.md index be796b6ac529e6a24140aa10d057bab37812b07a..9794444f83321b09b8f0963b2ed96ea469c1f89c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-rwlock.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-rwlock.md @@ -1,10 +1,5 @@ # 读写锁 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) ## 基本概念 @@ -37,18 +32,15 @@ ### 接口说明 -**表1** 读写锁模块接口 - -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 读写锁的创建和删除 | LOS_RwlockInit | 创建读写锁 | -| | LOS_RwlockDestroy |删除指定的读写锁| -| 读模式下的锁的申请 | LOS_RwlockRdLock | 申请指定的读模式下的锁 | -| | LOS_RwlockTryRdLock |尝试申请指定的读模式下的锁| -| 写模式下的锁的申请 | LOS_RwlockWrLock | 申请指定的写模式下的锁 | -| | LOS_RwlockTryWrLock |尝试申请指定的写模式下的锁| -| 读写锁的释放 | LOS_RwlockUnLock | 释放指定读写锁 | -| 读写锁有效性判断 | LOS_RwlockIsValid | 判断读写锁有效性 | + **表1** 读写锁模块接口 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 读写锁的创建和删除 | - LOS_RwlockInit:创建读写锁
- LOS_RwlockDestroy:删除指定的读写锁 | +| 读模式下的锁的申请 | - LOS_RwlockRdLock:申请指定的读模式下的锁
- LOS_RwlockTryRdLock:尝试申请指定的读模式下的锁 | +| 写模式下的锁的申请 | - LOS_RwlockWrLock:申请指定的写模式下的锁
- LOS_RwlockTryWrLock:尝试申请指定的写模式下的锁 | +| 读写锁的释放 | LOS_RwlockUnLock:释放指定读写锁 | +| 读写锁有效性判断 | LOS_RwlockIsValid:判断读写锁有效性 | ### 开发流程 diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md index fb78120cfaa905d8824d928870e91dfe5f6bb112..2ab8ebb7631d97c44596c1b29a5b0e2edb2fb068 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md @@ -1,14 +1,5 @@ # 信号量 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) - - [实例描述](#实例描述) - - [编程示例](#编程示例) - - [结果验证](#结果验证) ## 基本概念 @@ -31,8 +22,18 @@ **信号量控制块** + ``` -/** * 信号量控制块数据结构*/typedefstruct { UINT16 semStat; /*信号量状态 */ UINT16 semType; /*信号量类型 */ UINT16 semCount; /*信号量计数 */ UINT16 semId; /*信号量索引号 */ LOS_DL_LIST semList; /*用于插入阻塞于信号量的任务 */} LosSemCB; +/** + * 信号量控制块数据结构 + */ +typedef struct { + UINT16 semStat; /* 信号量状态 */ + UINT16 semType; /* 信号量类型 */ + UINT16 semCount; /* 信号量计数 */ + UINT16 semId; /* 信号量索引号 */ + LOS_DL_LIST semList; /* 用于插入阻塞于信号量的任务 */ +} LosSemCB; ``` **信号量运作原理** @@ -56,8 +57,8 @@ 运行示意图如下图所示: -**图1** 小型系统信号量运作示意图 -![zh-cn_image_0000001132774752](figures/zh-cn_image_0000001132774752.png) + **图1** 小型系统信号量运作示意图 + ![zh-cn_image_0000001132774752](figures/zh-cn_image_0000001132774752.png) ## 开发指导 @@ -65,15 +66,20 @@ ### 接口说明 -**表1** 信号量模块接口 + **表1** 创建/删除信号量 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 创建/删除信号量 | LOS_SemCreate | 创建信号量,返回信号量ID | -| | LOS_BinarySemCreate |创建二值信号量,其计数值最大为1| -| | LOS_SemDelete |删除指定的信号量| -| 申请/释放信号量 | LOS_SemPend | 申请指定的信号量,并设置超时时间 | -| | LOS_SemPost |释放指定的信号量| +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_SemCreate | 创建信号量,返回信号量ID | +| LOS_BinarySemCreate | 创建二值信号量,其计数值最大为1 | +| LOS_SemDelete | 删除指定的信号量 | + + **表2** 申请/释放信号量 + +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_SemPend | 申请指定的信号量,并设置超时时间 | +| LOS_SemPost | 释放指定的信号量 | ### 开发流程 @@ -112,6 +118,7 @@ 示例代码如下: + ``` #include "los_sem.h" #include "securec.h" @@ -230,6 +237,7 @@ UINT32 ExampleSem(VOID) 编译运行得到的结果为: + ``` ExampleSemTask2 try get sem g_semId wait forever. ExampleSemTask2 get sem g_semId and then delay 20 ticks. diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-mutex.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-mutex.md index 73d28d8a975a1c8260c92d6ad024a918f3f83cb4..3c70d1195c576bb7fcae13a046042496908ea2b4 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-mutex.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-mutex.md @@ -1,7 +1,5 @@ # 用户态快速互斥锁 -- [基本概念](#基本概念) -- [运行机制](#运行机制) ## 基本概念 @@ -18,14 +16,14 @@ Futex(Fast userspace mutex,用户态快速互斥锁)是内核提供的一种 当前哈希桶共有80个,0~63号桶用于存放私有锁(以虚拟地址进行哈希),64~79号桶用于存放共享锁(以物理地址进行哈希),私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。 -**图1** Futex设计图 -![zh-cn_image_0000001127535690](figures/zh-cn_image_0000001127535690.jpg) + **图1** Futex设计图 + ![zh-cn_image_0000001127535690](figures/zh-cn_image_0000001127535690.jpg) 如图1,每个futex哈希桶中存放被futex_list串联起来的哈希值相同的futex node,每个futex node对应一个被挂起的task,node中key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。 Futex有以下三种操作: -**表1** Futex模块接口 + **表1** Futex模块接口 | 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-signal.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-signal.md index 52054b10868d1d959691a15a72ef8704fb1bfc3e..a2f3244ecbfe50f54b0eb9808f580a1afd716d22 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-signal.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-signal.md @@ -1,7 +1,5 @@ # 信号 -- [基本概念](#基本概念) -- [运行机制](#运行机制) ## 基本概念 @@ -12,24 +10,21 @@ 信号的运作流程分为三个部分,如表1: -**表1** 信号的运作流程及相关接口(用户态接口) + **表1** 信号的运作流程及相关接口(用户态接口) -| 功能分类 | 接口**名称** | 描述 | +| 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | -| 注册信号回调函数 | signal | 注册信号总入口及注册和去注册某信号的回调函数。 | -| | sigaction |功能同signal,但增加了信号发送相关的配置选项,目前仅支持SIGINFO结构体中的部分参数。| -| 发送信号 | kill | 发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。 | -| |pthread_kill|发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。| -| |raise|发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。| -| |alarm|发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。| -| |abort|发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。| -| 触发回调 | 无 | 由系统调用与中断触发,内核态与用户态切换前会先进入用户态指定函数并处理完相应回调函数,再回到原用户态程序继续运行。 | +| 注册信号回调函数 | signal: | 注册信号总入口及注册和去注册某信号的回调函数。 | +| 注册信号回调函数 | sigaction | 功能同signal,但增加了信号发送相关的配置选项,目前仅支持SIGINFO结构体中的部分参数。 | +| 发送信号 | kill
pthread_kill
raise
alarm
abort | 发送信号给某个进程或进程内发送消息给某线程,为某进程下的线程设置信号标志位。 | +| 触发回调 | 无 | 由系统调用与中断触发,内核态与用户态切换前会先进入用户态指定函数并处理完相应回调函数,再回到原用户态程序继续运行。 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 信号机制为提供给用户态程序进程间通信的能力,故推荐使用上表1列出的用户态POSIX相关接口。 > > 注册回调函数: > +> > ``` > void *signal(int sig, void (*func)(int))(int); > ``` @@ -40,6 +35,7 @@ > > 注册回调函数: > +> > ``` > int sigaction(int, const struct sigaction *__restrict, struct sigaction *__restrict); > ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-basic-trans.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans.md index 02753beea7c4584f51c8ecfeee5e674758066555..afc58c98bcacdc67e98716ba4bcc702409b91bc3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-trans.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-trans.md @@ -1,6 +1,7 @@ # 内核通信机制 + - **[事件](kernel-small-basic-trans-event.md)** - **[信号量](kernel-small-basic-trans-semaphore.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-basics.md b/zh-cn/device-dev/kernel/kernel-small-basics.md index 7cbf099b1f35eab78db7c8041b779b34015c2afb..319f395fc04e2c945092d4cfec8ca666d22fe691 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basics.md +++ b/zh-cn/device-dev/kernel/kernel-small-basics.md @@ -1,6 +1,7 @@ # 基础内核 + - **[中断及异常处理](kernel-small-basic-interrupt.md)** - **[进程管理](kernel-small-basic-process.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-new.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-new.md index a3ee6348aaee45d6140c2a4a0a3285101b79be8a..aae333b1512f8231818b953574d12cd2efe8de69 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-new.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-new.md @@ -1,14 +1,11 @@ # 适配新的文件系统 -- [基本概念](#基本概念) -- [适配Mount接口](#适配mount接口) -- [适配Lookup接口](#适配lookup接口) -- [适配总结和注意事项](#适配总结和注意事项) ## 基本概念 所谓对接VFS层,其实就是指实现VFS层定义的若干接口函数,可根据文件系统的特点和需要适配其中部分接口。一般情况下,支持文件读写,最小的文件系统适配看起来是这样的: + ``` struct MountOps g_yourFsMountOps = { .Mount = YourMountMethod, @@ -38,12 +35,14 @@ FSMAP_ENTRY(yourfs_fsmap, "your fs name", g_yourFsMountOps, TRUE, TRUE); // 注 Mount是文件系统第一个被调用的接口,该接口一般会读取驱动的参数,根据配置对文件系统的进行初始化,最后生成文件系统的root节点。Mount接口的定义如下: + ``` int (*Mount)(struct Mount *mount, struct Vnode *blkDriver, const void *data); ``` 其中,第一个参数struct Mount \*mount是Mount点的信息,适配时需要填写的是下面的变量: + ``` struct Mount { const struct MountOps *ops; /* Mount相关的函数钩子 */ @@ -56,7 +55,8 @@ struct Mount { 第三个参数const void \*data是mount命令传入的数据,可以根据文件系统的需要处理。 -下面以JFFS2为例,详细看一下mount接口是如何适配的: + 下面以JFFS2为例,详细看一下mount接口是如何适配的: + ``` int VfsJffs2Bind(struct Mount *mnt, struct Vnode *blkDriver, const void *data) { @@ -137,6 +137,7 @@ const struct MountOps jffs_operations = { Lookup是查找文件的接口,它的函数原型是: + ``` int (*Lookup)(struct Vnode *parent, const char *name, int len, struct Vnode **vnode); ``` @@ -145,6 +146,7 @@ int (*Lookup)(struct Vnode *parent, const char *name, int len, struct Vnode **vn 这个接口适配起来思路很清晰,给了父节点的信息和文件名,实现从父目录中查询名字为name的文件这个功能,同样以JFFS2为例: + ``` int VfsJffs2Lookup(struct Vnode *parentVnode, const char *path, int len, struct Vnode **ppVnode) { diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-fat.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-fat.md index c7e5b7b67d5b0d9a1371e133a8b74f0b37555bce..0233f2c1532f29b6a6b4531d50b69295375b08b7 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-fat.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-fat.md @@ -1,9 +1,5 @@ # FAT -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [开发流程](#开发流程) ## 基本概念 @@ -30,6 +26,7 @@ SD卡或MMC的设备名为mmcblk[x]p[y],文件系统类型为“vfat”。 示例: + ``` mount("/dev/mmcblk0p0", "/mnt", "vfat", 0, NULL); ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-jffs2.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-jffs2.md index 150b22264680e6bea63abf6952035be93abdec97..6610d2cf6b94af8bddb62846195c9df2b48455e6 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-jffs2.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-jffs2.md @@ -1,8 +1,5 @@ # JFFS2 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) ## 基本概念 @@ -38,11 +35,12 @@ OpenHarmony内核的JFFS2主要应用于NOR FLASH闪存,其特点是:可读 使用mkfs.jffs2工具,制作镜像默认命令如下。页大小默认为4KiB,eraseblock大小默认64KiB。若实际参数与下面不同时,修改相应参数。 + ``` ./mkfs.jffs2 -d rootfs/ -o rootfs.jffs2 ``` -**表1** 指令含义表(更详细的介绍可以通过mkfs.jffs2 --help来查看) + **表1** 指令含义表(更详细的介绍可以通过mkfs.jffs2 --help来查看) | 指令 | 含义 | | -------- | -------- | @@ -62,12 +60,14 @@ OpenHarmony内核的JFFS2主要应用于NOR FLASH闪存,其特点是:可读 运行命令: + ``` OHOS # mount /dev/spinorblk1 /jffs1 jffs2 ``` 将从串口得到如下回应信息,表明挂载成功。 + ``` OHOS # mount /dev/spinorblk1 /jffs1 jffs2 mount OK @@ -81,12 +81,14 @@ mount OK 运行命令: + ``` OHOS # umount /jffs1 ``` 将从串口得到如下回应信息,表明卸载成功。 + ``` OHOS # umount /jffs1 umount ok diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-nfs.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-nfs.md index 92dd330d587f2feb9c41ebf2bfde419976362099..82be64d4b9553ef68c4734acea92947ecaf0406d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-nfs.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-nfs.md @@ -1,8 +1,5 @@ # NFS -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) ## 基本概念 @@ -24,12 +21,14 @@ OpenHarmony LiteOS-A内核的NFS文件系统指的是NFS的客户端,NFS客户 设置好Ubuntu系统的下载源,保证网络连接好的情况下执行: + ``` sudo apt-get install nfs-kernel-server ``` - 创建用于挂载的目录并设置完全权限 + ``` mkdir -p /home/sqbin/nfs sudo chmod 777 /home/sqbin/nfs @@ -39,6 +38,7 @@ sudo chmod 777 /home/sqbin/nfs 修改NFS配置文件/etc/exports,添加如下一行: + ``` /home/sqbin/nfs *(rw,no_root_squash,async) ``` @@ -47,17 +47,19 @@ sudo chmod 777 /home/sqbin/nfs 执行以下命令启动NFS server: + ``` sudo /etc/init.d/nfs-kernel-server start ``` 执行以下命令重启NFS server: + ``` sudo /etc/init.d/nfs-kernel-server restart ``` -1. 设置单板为NFS客户端 +2. 设置单板为NFS客户端 本指导中的NFS客户端指运行OpenHarmony内核的设备。 @@ -71,6 +73,7 @@ OpenHarmony内核设备上的IP信息可通过ifconfig命令查看。 启动以太网或者其他类型网络,使用ping命令检查到服务器的网络是否通畅。 + ``` OHOS # ping 10.67.212.178 [0]Reply from 10.67.212.178: time=1ms TTL=63 @@ -83,6 +86,7 @@ OHOS # ping 10.67.212.178 客户端NFS初始化,运行命令: + ``` OHOS # mkdir /nfs OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 @@ -90,6 +94,7 @@ OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 将从串口得到如下回应信息,表明初始化NFS客户端成功。 + ``` OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000 @@ -103,6 +108,7 @@ Mount nfs finished. > > mount命令的格式为: > +> > ``` > mount nfs > ``` @@ -111,22 +117,25 @@ Mount nfs finished. > > 如果不想有NFS访问权限限制,可以在Linux命令行将NFS根目录权限设置成777: > +> > ``` > chmod -R 777 /home/sqbin/nfs > ``` > > 至此,NFS客户端设置完毕。NFS文件系统已成功挂载。 -1. 利用NFS共享文件 +3. 利用NFS共享文件 在NFS服务器下新建目录dir,并保存。在OpenHarmony内核下运行ls命令: + ``` OHOS # ls /nfs ``` 则可从串口得到如下回应: + ``` OHOS # ls /nfs Directory /nfs: diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-procfs.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-procfs.md index b266c65f59eecefb270bd044c96e52e2ee68c242..f7612dfdd71cbfec0fa149e8d7544bbb4dcba6e5 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-procfs.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-procfs.md @@ -1,9 +1,5 @@ # Procfs -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [编程实例](#编程实例) ## 基本概念 @@ -30,6 +26,7 @@ procfs文件的创建无法使用一般的文件系统接口,需要使用ProcM 3.当写文件内容时,打印写入的内容 + ``` #include "proc_fs.h" @@ -78,6 +75,7 @@ void HelloWorldInit(void) 启动后在shell输入如下命令 + ``` OHOS # cat /proc/hello/world OHOS # Hello World! diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-ramfs.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-ramfs.md index 81e69a70d98a82efb4bf91b2dac50c0e75e7c857..31faa0ad7646151af5c5d24daaca5332938db73a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-ramfs.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support-ramfs.md @@ -1,8 +1,5 @@ # Ramfs -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) ## 基本概念 @@ -18,24 +15,28 @@ RAMFS文件系统把所有的文件都放在 RAM 中,所以读/写操作发生 挂载: + ``` mount(NULL, "/dev/shm", "ramfs", 0, NULL) ``` 创建目录: + ``` mkdir(pathname, mode) ``` 创建文件: + ``` open(pathname, O_NONBLOCK | O_CREAT | O_RDWR, mode) ``` 读取目录: + ``` dir = opendir(pathname) ptr = readdir(dir) @@ -44,18 +45,21 @@ closedir(dir) 删除文件: + ``` unlink(pathname) ``` 删除目录: + ``` rmdir(pathname) ``` 去挂载: + ``` umount("/dev/shm") ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support.md index 36eda90509d4b98c285a3c8bdd3711dac87917ca..5f2ea549f7be468f4780dd7c4db0c96a8690b4e0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-support.md @@ -1,6 +1,7 @@ # 支持的文件系统 + - **[FAT](kernel-small-bundles-fs-support-fat.md)** - **[JFFS2](kernel-small-bundles-fs-support-jffs2.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-virtual.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-virtual.md index d28ee3a7654aa541292edd54cada43d197854f2b..d4393975c06ef9fc616eea6a35f1b28922650e68 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs-virtual.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs-virtual.md @@ -1,11 +1,5 @@ # 虚拟文件系统 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -31,12 +25,15 @@ OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的, Vnode通过哈希以及LRU机制进行管理。当系统启动后,对文件或目录的访问会优先从哈希链表中查找Vnode缓存,若缓存没有命中,则并从对应文件系统中搜索目标文件或目录,创建并缓存对应的Vnode。当Vnode缓存数量达到上限时,将淘汰长时间未访问的Vnode,其中挂载点Vnode与设备节点Vnode不参与淘汰。当前系统中Vnode的规格默认为512,该规格可以通过LOSCFG_MAX_VNODE_SIZE进行配置。Vnode数量过大,会造成较大的内存占用;Vnode数量过少,则会造成搜索性能下降。下图展示了Vnode的创建流程。 - **图1** Vnode创建流程 - ![zh-cn_image_0000001127393126](figures/zh-cn_image_0000001127393126.png) + **图1** Vnode创建流程 + + ![zh-cn_image_0000001127393126](figures/zh-cn_image_0000001127393126.png) 1. PathCache:PathCache是路径缓存,它通过哈希表存储,利用父节点Vnode的地址和子节点的文件名,可以从PathCache中快速查找到子节点对应的Vnode。下图展示了文件/目录的查找流程。 - **图2** 文件查找流程 - ![zh-cn_image_0000001175795145](figures/zh-cn_image_0000001175795145.png) + + **图2** 文件查找流程 + + ![zh-cn_image_0000001175795145](figures/zh-cn_image_0000001175795145.png) 1. PageCache:PageCache是内核中文件的缓存。当前PageCache仅支持缓存二进制文件,在初次访问文件时通过mmap映射到内存中,下次再访问时,直接从PageCache中读取,可以提升对同一个文件的读写速度。另外基于PageCache可实现以文件为基底的进程间通信。 @@ -57,48 +54,85 @@ OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的, 当前文件系统支持的接口如下表所示,表格中的“×”代表对应文件系统不支持该接口。 -**表1** 支持接口列表 - -| 分类 | 接口**名称** | 功能 | FAT | JFFS2 | NFS | TMPFS | PROCFS | -| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -| 文件操作 | open | 打开文件 | √ | √ | √ | √ | √ | -| | read/pread/readv/preadv | 读取文件 | √ | √ | √ | √ | √ | -| | write/pwrite/writev/pwritev | 写入文件 | √ | √ | √ | √ | √ | -| | lseek | 设置文件偏移 | √ | √ | √ | √ | × | -| | close | 关闭文件 | √ | √ | √ | √ | √ | -| | unlink | 删除文件 | √ | √ | √ | √ | × | -| | fstat | 查询文件信息 | √ | √ | √ | √ | √ | -| | fallocate | 预分配大小 | √ | × | × | × | × | -| | truncate | 文件截断 | √ | √ | × | √ | × | -| | link | 创建硬链接 | × | √ | × | × | × | -| | symlink | 创建软链接 | √ | √ | × | × | × | -| | readlink | 读取软链接 | √ | √ | × | × | × | -| | dup | 复制文件句柄 | √ | √ | √ | √ | √ | -| | fsync | 文件内容刷入设备 | √ | × | × | × | × | -| | ioctl | 设备控制 | × | × | × | √ | × | -| | fcntl | 文件控制操作 | √ | √ | √ | √ | √ | -| 目录操作 | mkdir | 创建目录 | √ | √ | √ | √ | × | -| | opendir | 打开目录 | √ | √ | √ | √ | √ | -| | readdir | 读取目录 | √ | √ | √ | √ | √ | -| | closedir | 关闭目录 | √ | √ | √ | √ | √ | -| | telldir | 获取目录偏移 | √ | √ | √ | √ | √ | -| | seekdir | 设置目录偏移 | √ | √ | √ | √ | √ | -| | rewinddir | 重置目录偏移 | √ | √ | √ | √ | × | -| | scandir | 读取目录数据 | √ | √ | √ | √ | √ | -| | rmdir | 删除目录 | √ | √ | √ | √ | × | -| | chdir | 切换当前路径 | √ | √ | √ | √ | √ | -| | getcwd | 获取当前路径 | √ | √ | √ | √ | √ | -| | realpath | 相对/绝对路径转换 | √ | √ | √ | √ | √ | -| | rename | 文件/目录重命名 | √ | √ | √ | √ | × | -| | chmod | 修改文件/目录属性 | √ | √ | × | × | × | -| | chown | 修改文件/目录所有者 | √ | √ | × | × | × | -| | stat/lstat | 查询文件/目录信息 | √ | √ | √ | √ | √ | -| | access | 查询文件/目录访问权限 | √ | √ | √ | √ | √ | -| 分区操作 | mount | 挂载分区 | √ | √ | √ | √ | √ | -| | umount | 卸载分区 | √ | √ | √ | √ | × | -| | statfs | 查询挂载分区信息 | √ | √ | √ | √ | √ | -| | format | 格式化分区 | √ | × | × | × | × | -| | sync | 分区内容刷入设备 | √ | × | × | × | × | + **表1** 文件操作 + +| 接口**名称** | 功能 | FAT | JFFS2 | NFS | TMPFS | PROCFS | +| -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| open | 打开文件 | √ | √ | √ | √ | √ | +| read/pread/readv/preadv | 读取文件 | √ | √ | √ | √ | √ | +| write/pwrite/writev/pwritev | 写入文件 | √ | √ | √ | √ | √ | +| lseek | 设置文件偏移 | √ | √ | √ | √ | × | +| close | 关闭文件 | √ | √ | √ | √ | √ | +| unlink | 删除文件 | √ | √ | √ | √ | × | +| fstat | 查询文件信息 | √ | √ | √ | √ | √ | +| fallocate | 预分配大小 | √ | × | × | × | × | +| truncate | 文件截断 | √ | √ | × | √ | × | +| link | 创建硬链接 | × | √ | × | × | × | +| symlink | 创建软链接 | √ | √ | × | × | × | +| readlink | 读取软链接 | √ | √ | × | × | × | +| dup | 复制文件句柄 | √ | √ | √ | √ | √ | +| fsync | 文件内容刷入设备 | √ | × | × | × | × | +| ioctl | 设备控制 | × | × | × | √ | × | +| fcntl | 文件控制操作 | √ | √ | √ | √ | √ | +| mkdir | 创建目录 | √ | √ | √ | √ | × | +| opendir | 打开目录 | √ | √ | √ | √ | √ | +| readdir | 读取目录 | √ | √ | √ | √ | √ | +| closedir | 关闭目录 | √ | √ | √ | √ | √ | +| telldir | 获取目录偏移 | √ | √ | √ | √ | √ | +| seekdir | 设置目录偏移 | √ | √ | √ | √ | √ | +| rewinddir | 重置目录偏移 | √ | √ | √ | √ | × | +| scandir | 读取目录数据 | √ | √ | √ | √ | √ | +| rmdir | 删除目录 | √ | √ | √ | √ | × | +| chdir | 切换当前路径 | √ | √ | √ | √ | √ | +| getcwd | 获取当前路径 | √ | √ | √ | √ | √ | +| realpath | 相对/绝对路径转换 | √ | √ | √ | √ | √ | +| rename | 文件/目录重命名 | √ | √ | √ | √ | × | +| chmod | 修改文件/目录属性 | √ | √ | × | × | × | +| chown | 修改文件/目录所有者 | √ | √ | × | × | × | +| stat/lstat | 查询文件/目录信息 | √ | √ | √ | √ | √ | +| access | 查询文件/目录访问权限 | √ | √ | √ | √ | √ | +| mount | 挂载分区 | √ | √ | √ | √ | √ | +| umount | 卸载分区 | √ | √ | √ | √ | × | +| statfs | 查询挂载分区信息 | √ | √ | √ | √ | √ | +| format | 格式化分区 | √ | × | × | × | × | +| sync | 分区内容刷入设备 | √ | × | × | × | × | + + **表2** 目录操作 + +| 接口**名称** | 功能 | FAT | JFFS2 | NFS | TMPFS | PROCFS | +| -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| mkdir | 创建目录 | √ | √ | √ | √ | × | +| opendir | 打开目录 | √ | √ | √ | √ | √ | +| readdir | 读取目录 | √ | √ | √ | √ | √ | +| closedir | 关闭目录 | √ | √ | √ | √ | √ | +| telldir | 获取目录偏移 | √ | √ | √ | √ | √ | +| seekdir | 设置目录偏移 | √ | √ | √ | √ | √ | +| rewinddir | 重置目录偏移 | √ | √ | √ | √ | × | +| scandir | 读取目录数据 | √ | √ | √ | √ | √ | +| rmdir | 删除目录 | √ | √ | √ | √ | × | +| chdir | 切换当前路径 | √ | √ | √ | √ | √ | +| getcwd | 获取当前路径 | √ | √ | √ | √ | √ | +| realpath | 相对/绝对路径转换 | √ | √ | √ | √ | √ | +| rename | 文件/目录重命名 | √ | √ | √ | √ | × | +| chmod | 修改文件/目录属性 | √ | √ | × | × | × | +| chown | 修改文件/目录所有者 | √ | √ | × | × | × | +| stat/lstat | 查询文件/目录信息 | √ | √ | √ | √ | √ | +| access | 查询文件/目录访问权限 | √ | √ | √ | √ | √ | +| mount | 挂载分区 | √ | √ | √ | √ | √ | +| umount | 卸载分区 | √ | √ | √ | √ | × | +| statfs | 查询挂载分区信息 | √ | √ | √ | √ | √ | +| format | 格式化分区 | √ | × | × | × | × | +| sync | 分区内容刷入设备 | √ | × | × | × | × | + + **表3** 分区操作 + +| 接口**名称** | 功能 | FAT | JFFS2 | NFS | TMPFS | PROCFS | +| -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| mount | 挂载分区 | √ | √ | √ | √ | √ | +| umount | 卸载分区 | √ | √ | √ | √ | × | +| statfs | 查询挂载分区信息 | √ | √ | √ | √ | √ | +| format | 格式化分区 | √ | × | × | × | × | +| sync | 分区内容刷入设备 | √ | × | × | × | × | ### 开发流程 @@ -110,6 +144,7 @@ OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的, 代码实现如下: + ``` #include #include @@ -236,6 +271,7 @@ int main(void) 编译运行得到的结果为: + ``` Hello OpenHarmony! ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-fs.md b/zh-cn/device-dev/kernel/kernel-small-bundles-fs.md index 0c7137b5ebffe3240123ca6fc65374f113c530ae..2e2f76434ef012ddfafe053ff53242a9e3a12422 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-fs.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-fs.md @@ -1,18 +1,19 @@ # 文件系统 + 文件系统(File System,或者简称FS),是操作系统中输入输出的一种主要形式,主要负责和内外部的存储设备交互。 文件系统对上通过C库提供的POSIX标准的操作接口,具体可以参考C库的API文档说明。对下,通过内核态的VFS虚拟层,屏蔽了各个具体文件系统的差异。基本架构如下: -**图1** 文件系统的总体结构 -![zh-cn_image_0000001125101908](figures/zh-cn_image_0000001125101908.png) + **图1** 文件系统的总体结构 + + ![zh-cn_image_0000001125101908](figures/zh-cn_image_0000001125101908.png) - **[虚拟文件系统](kernel-small-bundles-fs-virtual.md)** - **[支持的文件系统](kernel-small-bundles-fs-support.md)** -- **[适配新的文件系统](kernel-small-bundles-fs-new.md)** - +- **[适配新的文件系统](kernel-small-bundles-fs-new.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-ipc.md b/zh-cn/device-dev/kernel/kernel-small-bundles-ipc.md index 21f61cb7efe884924e6c4067ec67ee2a52cfd264..a88b52fbe6f9c54ac59f3a1ff83dc440d3a25edd 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-ipc.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-ipc.md @@ -1,9 +1,5 @@ # 轻量级进程间通信 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) ## 基本概念 @@ -22,15 +18,13 @@ LiteIPC中有两个主要概念,一个是ServiceManager,另一个是Service ### 接口说明 -**表1** LiteIPC模块接口(仅LiteOS-A内部使用) + **表1** LiteIPC模块接口(仅LiteOS-A内部使用) -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 模块初始化 | OsLiteIpcInit | 初始化LiteIPC模块 | -| IPC消息内存池 | LiteIpcPoolInit | 初始化进程的IPC消息内存池 | -| | LiteIpcPoolReInit |重新初始化进程的IPC消息内存池| -| | LiteIpcPoolDelete |释放进程的IPC消息内存池| -| Service管理 | LiteIpcRemoveServiceHandle | 删除指定的Service | +| 功能分类 | 接口描述 | +| -------- | -------- | +| 模块初始化 | OsLiteIpcInit:初始化LiteIPC模块 | +| IPC消息内存池 | - LiteIpcPoolInit:初始化进程的IPC消息内存池
- LiteIpcPoolReInit:重新初始化进程的IPC消息内存池
- LiteIpcPoolDelete:释放进程的IPC消息内存池 | +| Service管理 | LiteIpcRemoveServiceHandle:删除指定的Service | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > LiteIPC模块接口都只在LiteOS-A内部使用。 diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-linking.md b/zh-cn/device-dev/kernel/kernel-small-bundles-linking.md index d0d9e4768af3505aa71d1b3b028cf6e9b56eca2c..b82577accf4e2a79da7eb0563d3f103a663b3cad 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-linking.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-linking.md @@ -1,10 +1,5 @@ # 动态加载与链接 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) ## 基本概念 @@ -21,8 +16,8 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 ## 运行机制 -**图1** 动态加载流程 -![zh-cn_image_0000001133104502](figures/zh-cn_image_0000001133104502.png) + **图1** 动态加载流程 + ![zh-cn_image_0000001133104502](figures/zh-cn_image_0000001133104502.png) 1. 内核将应用程序ELF文件的PT_LOAD段信息映射至进程空间。对于ET_EXEC类型的文件,根据PT_LOAD段中p_vaddr进行固定地址映射;对于ET_DYN类型(位置无关的可执行程序,通过编译选项“-fPIE”得到)的文件,内核通过mmap接口选择base基址进行映射(load_addr = base + p_vaddr)。 @@ -30,8 +25,8 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 3. 动态链接器自举并查找应用程序依赖的所有共享库并对导入符号进行重定位,最后跳转至应用程序的e_entry(或base + e_entry),开始运行应用程序。 -**图2** 程序执行流程 -![zh-cn_image_0000001133264664](figures/zh-cn_image_0000001133264664.png) + **图2** 程序执行流程 + ![zh-cn_image_0000001133264664](figures/zh-cn_image_0000001133264664.png) 1. 加载器与链接器调用mmap映射PT_LOAD段; @@ -49,7 +44,7 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 ### 接口说明 -**表1** 内核加载器模块接口 + **表1** 内核加载器模块接口 | 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-share.md b/zh-cn/device-dev/kernel/kernel-small-bundles-share.md index 326d2761fa6f26dfa737ab5d2f01f6f37f4abe52..5049f8883af54c553de6def88f3fedbb39f96798 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-share.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-share.md @@ -1,7 +1,5 @@ # 虚拟动态共享库 -- [基本概念](#基本概念) -- [运行机制](#运行机制) ## 基本概念 @@ -20,8 +18,8 @@ VDSO总体可分为数据页与代码页两部分: - 代码页提供屏蔽系统调用的主要逻辑; -**图1** VDSO系统设计 -![zh-cn_image_0000001173586763](figures/zh-cn_image_0000001173586763.jpg) + **图1** VDSO系统设计 + ![zh-cn_image_0000001173586763](figures/zh-cn_image_0000001173586763.jpg) 如图1所示,当前VDSO机制有以下几个主要步骤: diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles-system.md b/zh-cn/device-dev/kernel/kernel-small-bundles-system.md index da585ebaa0698f0e241206588ed6f5c74fd2636a..4b75ad05591aac01d8bdcf3957702469a4e70d2c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-system.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-system.md @@ -1,10 +1,5 @@ # 系统调用 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -13,9 +8,11 @@ OpenHarmony LiteOS-A实现了用户态与内核态的区分隔离,用户态程 ## 运行机制 -如图1所示,用户程序通过调用System API(系统API,通常是系统提供的POSIX接口)进行内核资源访问与交互请求,POSIX接口内部会触发SVC/SWI异常,完成系统从用户态到内核态的切换,然后对接到内核的Syscall Handler(系统调用统一处理接口)进行参数解析,最终分发至具体的内核处理函数。 -**图1** 系统调用示意图 -![zh-cn_image_0000001132856572](figures/zh-cn_image_0000001132856572.png) + 如图1所示,用户程序通过调用System API(系统API,通常是系统提供的POSIX接口)进行内核资源访问与交互请求,POSIX接口内部会触发SVC/SWI异常,完成系统从用户态到内核态的切换,然后对接到内核的Syscall Handler(系统调用统一处理接口)进行参数解析,最终分发至具体的内核处理函数。 + + **图1** 系统调用示意图 + + ![zh-cn_image_0000001132856572](figures/zh-cn_image_0000001132856572.png) Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA32SyscallHandle函数,在进入系统软中断异常时会调用此函数,并且按照kernel/liteos_a/syscall/syscall_lookup.h中的清单进行系统调用的入参解析,执行各系统调用最终对应的内核处理函数。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** @@ -45,7 +42,8 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 **示例代码**: 1. 在LibC库syscall.h.in中新增系统调用号 - 如下所示,其中__NR_new_syscall_sample为新增系统调用号: + 如下所示,其中__NR_new_syscall_sample为新增系统调用号: + ``` ... /* 当前现有的系统调用清单 */ @@ -74,6 +72,7 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 ``` 2. 在LibC库中新增用户态接口的声明与实现 + ``` #include "stdio_impl.h" #include "syscall.h" @@ -90,6 +89,7 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 3. 在内核系统调用头文件中新增系统调用号 如下所示,在third_party/musl/porting/liteos_a/kernel/include/bits/syscall.h文件中,__NR_new_syscall_sample为新增系统调用号。 + ``` ... /* 当前现有的系统调用清单 */ @@ -119,6 +119,7 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 在kernel/liteos_a/syscall/syscall_lookup.h中,增加一行SYSCALL_HAND_DEF(__NR_new_syscall_sample, SysNewSyscallSample, void, ARG_NUM_1): + ``` ... /* 当前现有的系统调用清单 */ @@ -136,6 +137,7 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 4. 在内核中新增内核该系统调用对应的处理函数 如下所示,在kernel/liteos_a/syscall/los_syscall.h中,SysNewSyscallSample为新增系统调用的内核处理函数声明: + ``` ... /* 当前现有的系统调用内核处理函数声明清单 */ @@ -150,7 +152,8 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 ... ``` - 新增的系统调用的内核处理函数实现如下: + 新增的系统调用的内核处理函数实现如下: + ``` include "los_printf.h" ... @@ -169,6 +172,7 @@ Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA3 用户态程序调用newSyscallSample(10)接口,得到输出结果如下: + ``` /* 用户态接口与内核态接口均有输出,证明系统调用已使能 */ user mode: num = 10 diff --git a/zh-cn/device-dev/kernel/kernel-small-bundles.md b/zh-cn/device-dev/kernel/kernel-small-bundles.md index 50c911fead432246494acc4101aea55ffed99db2..068a5740d9b4338a13d6ff5e29a99b7e47e0a49c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles.md @@ -1,6 +1,7 @@ # 扩展组件 + - **[系统调用](kernel-small-bundles-system.md)** - **[动态加载与链接](kernel-small-bundles-linking.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-memory-corrupt.md b/zh-cn/device-dev/kernel/kernel-small-debug-memory-corrupt.md index 55d6f8edc591aa83c14a88095a9210f0ed45f969..11da1497e3478b2207bada0f8ee52728eaa577eb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-memory-corrupt.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-memory-corrupt.md @@ -1,10 +1,5 @@ # 踩内存检测 -- [基础概念](#基础概念) -- [功能配置](#功能配置) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基础概念 @@ -50,6 +45,7 @@ LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK:开关宏,默认关闭;若打开这 代码实现如下: + ``` #include #include @@ -74,6 +70,7 @@ void MemIntegrityTest(void) 编译运行输出log如下: + ``` [ERR][OsMemMagicCheckPrint], 2028, memory check error! memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md b/zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md index da1704adc611539be30c02a1140832389ad0f3c7..29281d54b2486a737a7efccd1d66ebfd6ae14e4b 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md @@ -1,10 +1,5 @@ # 内存信息统计 -- [基础概念](#基础概念) -- [功能配置](#功能配置) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基础概念 @@ -29,6 +24,7 @@ LOSCFG_MEM_WATERLINE:开关宏,默认关闭;若需要打开这个功能, 关键结构体介绍: + ``` typedef struct { UINT32 totalUsedSize; // 内存池的内存使用量 @@ -61,7 +57,8 @@ typedef struct { **示例代码** -代码实现如下: + 代码实现如下: + ``` #include #include @@ -109,6 +106,7 @@ int MemTest(void) 编译运行输出的结果如下: + ``` usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md b/zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md index c565c5d007d1062c2b05eff6029a055e9bdf78a9..e7c75955c37d6e9c643124d8d0b7c8a712fe3e49 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md @@ -1,10 +1,5 @@ # 内存泄漏检测 -- [基础概念](#基础概念) -- [功能配置](#功能配置) -- [开发指导](#开发指导) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基础概念 @@ -34,6 +29,7 @@ 调用LOS_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 + ``` node size LR[0] LR[1] LR[2] 0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 @@ -68,7 +64,6 @@ node size LR[0] LR[1] LR[2] 代码实现如下: - ``` #include #include @@ -90,7 +85,6 @@ void MemLeakTest(void) 编译运行输出log如下: - ``` node size LR[0] LR[1] LR[2] 0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc @@ -112,7 +106,6 @@ node size LR[0] LR[1] LR[2] 对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: - ``` 0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 @@ -121,7 +114,6 @@ node size LR[0] LR[1] LR[2] 部分汇编文件如下: - ``` MemLeakTest: 0x80041d4: 0xb510 PUSH {R4, LR} diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-memory.md b/zh-cn/device-dev/kernel/kernel-small-debug-memory.md index 91c812783b0dc4749278a3a07c03af39af269e19..59b1e7daf798410f256c524d32054f93324a4c67 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-memory.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-memory.md @@ -1,6 +1,7 @@ # 内核态内存调测 + - **[内存信息统计](kernel-small-debug-memory-info.md)** - **[内存泄漏检测](kernel-small-debug-memory-leak.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-other.md b/zh-cn/device-dev/kernel/kernel-small-debug-other.md index 36811a2558a665ac812cbc971b500cf19687f0aa..53b5883e968e858707fbf725c5845b64aee7255a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-other.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-other.md @@ -1,6 +1,7 @@ # 其他内核调测手段 + - **[临终遗言](kernel-small-debug-trace-other-lastwords.md)** -- **[常见问题定位方法](kernel-small-debug-trace-other-faqs.md)** \ No newline at end of file +- **[常见问题](kernel-small-debug-trace-other-faqs.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md b/zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md index 6213940dd4c7efd00f46aae2d371a323facd18a6..89a46e053ec053321e9f667ba59d74c1f8013b56 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md @@ -1,11 +1,5 @@ -# CPU占用率 +# 进程调测 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [开发指导](#开发指导) - - [接口说明](#接口说明) - - [开发流程](#开发流程) - - [编程实例](#编程实例) ## 基本概念 @@ -54,15 +48,15 @@ OpenHarmony 提供以下四种CPU占用率的信息查询: ### 接口说明 -**表1** CPUP模块接口 + **表1** CPUP模块接口 -| 功能分类 | 接口**名称** | 描述 | +| 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | -| 系统CPU占用率 | LOS_HistorySysCpuUsage | 获取系统历史CPU占用率 | -| 进程CPU占用率 | LOS_HistoryProcessCpuUsage | 获取指定进程历史CPU占用率 | -| | LOS_GetAllProcessCpuUsage |获取系统所有进程的历史CPU占用率| -| 任务CPU占用率 | LOS_HistoryTaskCpuUsage | 获取指定任务历史CPU占用率 | -| 中断CPU占用率 | LOS_GetAllIrqCpuUsage | 获取系统所有中断的历史CPU占用率 | +| 系统CPU占用率 | LOS_HistorySysCpuUsage | 获取系统历史CPU占用率 | +| 进程CPU占用率 | LOS_HistoryProcessCpuUsage | 获取指定进程历史CPU占用率 | +| 进程CPU占用率 | LOS_GetAllProcessCpuUsage | 获取系统所有进程的历史CPU占用率 | +| 任务CPU占用率 | LOS_HistoryTaskCpuUsage | 获取指定任务历史CPU占用率 | +| 中断CPU占用率 | LOS_GetAllIrqCpuUsage | 获取系统所有中断的历史CPU占用率 | ### 开发流程 @@ -110,6 +104,7 @@ CPU占用率的典型开发流程: 代码实现如下: + ``` #include "los_task.h" #include "los_cpup.h" @@ -156,6 +151,7 @@ UINT32 ItCpupTest(VOID) 编译运行得到的结果为: + ``` entry cpup test example the history system cpu usage in all time: 3.0 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-build.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-build.md index 546449c66a146cd363485c0d34855d7fdfbed4f5..62fdd05c80ed52585f3e62fa194c3fdf052e20ad 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-build.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-build.md @@ -1,10 +1,5 @@ # Shell命令编程实例 -- [实例描述](#实例描述) -- [静态注册方式](#静态注册方式) -- [静态注册编程实例](#静态注册编程实例) -- [动态注册方式](#动态注册方式) -- [动态注册编程实例](#动态注册编程实例) ## 实例描述 @@ -27,6 +22,7 @@ ## 静态注册编程实例 1. 定义命令所要调用的函数cmd_test: + ``` #include "shell.h" #include "shcmd.h" @@ -38,6 +34,7 @@ ``` 2. 新增命令项: + ``` SHELLCMD_ENTRY(test_shellcmd, CMD_TYPE_EX, "test", 0, (CMD_CBK_FUNC)cmd_test); ``` @@ -46,11 +43,13 @@ 在liteos_tables_ldflags.mk文件的LITEOS_TABLES_LDFLAGS项下添加-utest_shellcmd。 4. 重新编译代码: + ``` make clean;make ``` 5. 用help命令查看当前系统所有的注册命令,可以发现test命令已经注册。(以下命令集合仅供参考,以实际编译运行情况为准。) + ``` OHOS # help ***shell commands:* @@ -77,6 +76,7 @@ ## 动态注册编程实例 1. 在用户应用函数中调用osCmdReg函数动态注册命令。 + ``` #include "shell.h" #include "shcmd.h" @@ -95,11 +95,13 @@ ``` 2. 重新编译代码: + ``` make clean;make ``` 3. 用help命令查看当前系统所有的注册命令,可以发现test命令已经注册。 + ``` OHOS # help ***shell commands:* diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md index 8f5d4734d302f61764f22edada0bac0e308ea912..f5f8df2f9c69e0c500b665bf5cadf7a5a2681895 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-cpup.md @@ -1,11 +1,5 @@ # cpup -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ cpup [_mode_] [_taskID_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -43,7 +37,8 @@ cpup [_mode_] [_taskID_] ## 输出说明 -**示例**:指令输出结果 + **示例**:指令输出结果 + ``` OHOS # cpup 1 5pid 5 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md index d05bcc3e4736a577d5bba7e28a410f9a6d45f99d..164bbb70804ba1fb045824fab116f9e3f6c763d0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-date.md @@ -1,11 +1,5 @@ # date -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -25,7 +19,7 @@ date命令用于查询系统日期和时间。 ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -52,6 +46,7 @@ date命令用于查询系统日期和时间。 示例:按指定格式打印系统日期 + ``` OHOS:/$ date +%Y--%m--%d 1970--01--01 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md index 1a262cc86997c48723fa9e5bb8177a08d683e5cf..5c1bc4e332ecd4df168a47b267df834236156738 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-dmesg.md @@ -1,11 +1,5 @@ # dmesg -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -27,7 +21,7 @@ dmesg > [_fileA_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -59,7 +53,8 @@ dmesg > [_fileA_] ## 输出说明 -**示例**:dmesg重定向到文件 + **示例**:dmesg重定向到文件 + ``` OHOS # dmesg > dmesg.log Dmesg write log to dmesg.log success diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-exec.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-exec.md index 53b5151643204846443ada6272d5af6aaaceca3a..0777cb4fd2de7c68e72594b70d8fa0f8d0af03eb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-exec.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-exec.md @@ -1,11 +1,5 @@ # exec -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ exec <_executable-file_> ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -40,6 +34,7 @@ exec <_executable-file_> ## 输出说明 + ``` OHOS # exec helloworld OHOS # hello world! diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md index 18c5b5cce54ffa4b54facc34606ce4757b6e620e..d66ac6c1d2ebfbd69210d17278f0e74c5e5054bc 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-free.md @@ -1,11 +1,5 @@ # free -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ free [_-b | -k | -m | -g | -t_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -44,6 +38,7 @@ free [_-b | -k | -m | -g | -t_] ## 输出说明 + ``` OHOS:/$ free total used free shared buffers @@ -62,7 +57,7 @@ Mem: 2 2 0 0 0 Swap: 0 0 0 ``` -**表2** 输出说明 + **表2** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md index 164b3c8fb42a190436fa2199d84959459413ec06..47847e242506a858499ebd7cef7c8f285740f3f9 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-help.md @@ -1,11 +1,5 @@ # help -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -36,6 +30,7 @@ help用于显示当前操作系统内所有操作指令。 查看系统内所有操作指令。 + ``` After shell prompt "OHOS # ": Use ` [args ...]` to run built-in shell commands listed above. diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-hwi.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-hwi.md index 7e260a4715e35f55fc0c555755c84c48aee4aa81..f184a21da0189920c0ae1aaff5639d548334cd9c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-hwi.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-hwi.md @@ -1,11 +1,5 @@ # hwi -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -37,6 +31,7 @@ hwi ## 输出说明 - 显示中断信息(LOSCFG_CPUP_INCLUDE_IRQ关闭) + ``` OHOS # hwi InterruptNo Count Name @@ -74,6 +69,7 @@ hwi ``` - 显示中断信息(LOSCFG_CPUP_INCLUDE_IRQ打开) + ``` OHOS # hwi InterruptNo Count ATime(us) CPUUSE CPUUSE10s CPUUSE1s Mode Name @@ -110,7 +106,7 @@ hwi 102: 0 0 0.0 0.0 0.0 normal SPI_HI35XX ``` - **表1** 输出说明 + **表1** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md index 3fc9e2fe3f784837b5833861f8b1688a8152d56d..c29953e112a2961fb15490b7033d689afb00f159 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-kill.md @@ -1,11 +1,5 @@ # kill -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -43,6 +37,7 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ ## 使用实例 - 查看当前进程列表,查看需要杀死的进程PID(42)。 + ``` OHOS:/$ ps allCpu(%): 4.67 sys, 195.33 idle @@ -55,6 +50,7 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ 6 1 6 0 Pending 0x688000 0x137000 0x11bca0 0.0 media_server 7 1 7 0 Pending 0x9d2000 0x103000 0xa1cdf 0.88 wms_server 8 1 8 2 Pending 0x1f5000 0x48000 0x47dc2 0.2 mksh + 10 5 5 101 Pending 0x11ec000 0x2f9000 0x206047 0.93 com.example.launcher 12 1 12 0 Pending 0x4d4000 0x112000 0xe0882 0.0 deviceauth_service 13 1 13 0 Pending 0x34f000 0xbd000 0x51799 0.0 sensor_service 14 1 14 2 Pending 0x34e000 0xb3000 0x52184 0.0 ai_server @@ -64,6 +60,7 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ ``` - 发送信号9(SIGKILL默认行为为立即终止进程)给42号进程test_demo(用户态进程):kill -s 9 42(kill -9 42效果相同),并查看当前进程列表,42号进程已终止。 + ``` OHOS:/$ kill -s 9 42 OHOS:/$ @@ -79,6 +76,7 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ 6 1 6 0 Pending 0x688000 0x137000 0x11c1ba 0.0 media_server 7 1 7 0 Pending 0x9d2000 0x103000 0xa21f9 0.89 wms_server 8 1 8 2 Pending 0x1f5000 0x48000 0x482dc 0.2 mksh + 10 5 5 101 Pending 0x11ec000 0x2f9000 0x206561 0.93 com.example.launcher 12 1 12 0 Pending 0x4d4000 0x112000 0xe0d9c 0.0 deviceauth_service 13 1 13 0 Pending 0x34f000 0xbd000 0x51cb3 0.0 sensor_service 14 1 14 2 Pending 0x34e000 0xb3000 0x5269e 0.0 ai_server @@ -95,6 +93,7 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ **示例 1** 发送信号给指定进程 + ``` OHOS:/$ kill -s 9 42 OHOS:/$ @@ -105,6 +104,7 @@ OHOS:/$ **示例 2** 信号发送失败 + ``` OHOS:/$ kill -100 31 kill: Unknown signal '(null)' diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md index 58c39c76254164e2b58357f76902a51f225bfd37..35b30bd90fece1cfa45b25efce7fbdb524a56778 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-log.md @@ -1,11 +1,5 @@ # log -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ log level [_levelNum_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -60,6 +54,7 @@ log level [_levelNum_] **示例**:设置当前日志打印级别为3 + ``` OHOS # log level 3 Set current log level WARN diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md index a27fa6a6229d60716427efced39d8389dfb819d2..6edb6f2c18540ac1c42e2b15c44bdedd4ea72ef4 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-memcheck.md @@ -1,11 +1,5 @@ # memcheck -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -40,13 +34,15 @@ memcheck ## 输出说明 -**示例1:**当前没有内存越界 + **示例1**:当前没有内存越界 + ``` OHOS # memcheck system memcheck over, all passed! ``` -**示例2:**出现内存越界 + **示例2**:出现内存越界 + ``` [L0S DLnkCheckMenl 349, memory check stFreeNodeInfo.pstPrev:0x7e0d31f3 is out of legal mem range[0x80ba5f40, 0х83d00000] diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md index 79680602c69b8a2892af1c4cfdaa3a618721f628..c7c4a19f652e2f66a40844cd78271d8763c71618 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-oom.md @@ -1,11 +1,5 @@ # oom -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -27,7 +21,7 @@ oom -h | --help ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -39,7 +33,7 @@ oom -h | --help ## 使用指南 -参数缺省时,显示oom功能当前配置信息。 + 参数缺省时,显示oom功能当前配置信息。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 当系统内存不足时,会打印出内存不足的提示信息。 @@ -57,6 +51,7 @@ oom -h | --help **示例1:**oom缺省打印配置信息 + ``` OHOS:/$ oom [oom] oom loop task status: enabled @@ -67,6 +62,7 @@ OHOS:/$ oom 系统内存不足时打印提示信息 + ``` T:20 Enter:IT MEM 00M 001 [oom] OS is in low memory state @@ -116,13 +112,14 @@ traceback 5 -- 1r = 0x20c4df50 fp = 0хb0b0b0b 1r in /1ib/libc.so - -> 0x62f50 **示例2**:设置 oom 线程任务检查的时间间隔 + ``` OHOS:/$ oom -i 100 [oom] set oom check interval (100)ms successful ``` -**表2** 输出说明 + **表2** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md index 542993c710319e212adf9b843a0bc663c1f5a2ee..639152773cef118341b0199db113eba959b46967 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-pmm.md @@ -1,11 +1,5 @@ # pmm -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -34,7 +28,8 @@ Debug版本才具备的命令。 ## 输出说明 -**示例:**查看物理页使用情况 + **示例:**查看物理页使用情况 + ``` OHOS # pmm phys_seg base size free_pages @@ -60,7 +55,7 @@ Vnode number = 67 Vnode memory size = 10720(B) ``` -**表1** 输出说明 + **表1** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reboot.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reboot.md index 6fbd707bb869f3d826d72981d5545bc7d2f83b10..b81be050fa28a9ff6745707050fe3dda78cd268c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reboot.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reboot.md @@ -1,11 +1,5 @@ # reboot -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reset.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reset.md index e0eb5fe6409bb8ab4cd123a4cf26cba28ee21c14..bac39a77df20e2169506d9b62b87977b6e5f9675 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reset.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-reset.md @@ -1,11 +1,5 @@ # reset -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md index e0b1c8c6ae90ee2fd995fe560b42be3fd8f60915..78725d748293c1818f84e1dfef14fe06d15983e2 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sem.md @@ -1,11 +1,5 @@ # sem -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ sem [_ID__ / fulldata_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -46,7 +40,8 @@ sem [_ID__ / fulldata_] ## 输出说明 -**示例1**:查询所有在用的信号量信息 + **示例1**:查询所有在用的信号量信息 + ``` OHOS # sem SemID Count @@ -72,7 +67,7 @@ OHOS # sem 0x00000006 0 ``` -**表2** 输出说明 + **表2** 输出说明 | 输出 | 说明 | | -------- | -------- | @@ -84,7 +79,8 @@ OHOS # sem > > ● sem命令的ID参数在[0, 1023]范围内时,返回对应ID的信号量的状态(如果对应ID的信号量未被使用则进行提示);其他取值时返回参数错误的提示。 -**示例2:**查询所有在用的信号量信息 + **示例2:**查询所有在用的信号量信息 + ``` OHOS # sem fulldata Used Semaphore List: @@ -117,7 +113,7 @@ Used Semaphore List: 0x38 0x1 0x1 0x404978fc 0x395 ``` -**表3** 输出说明 + **表3** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md index 4f1c7ff7e050d18738c11c68cfd2823bdcbbcd4a..c8a872c90c992abb05771fcc702425c4e92c1a78 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-stack.md @@ -1,11 +1,5 @@ # stack -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -34,7 +28,8 @@ stack ## 输出说明 -**示例:**系统堆栈使用情况 + **示例:**系统堆栈使用情况 + ``` OHOS # stack stack name cpu id stack addr total size used size @@ -45,7 +40,7 @@ OHOS # stack exc_stack 0 0x405c9000 0x1000 0x0 ``` -**表1** 输出说明 + **表1** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md index 47ff47672ac0d1301524e3663064157f897a6698..6465bb4c8826ddb0e55de2b2740e5f5e6fefe795 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-su.md @@ -1,11 +1,5 @@ # su -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ su [_uid_] [_gid_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -43,7 +37,8 @@ su [_uid_] [_gid_] ## 输出说明 -**示例:**切换到为uid为1000,gid为1000的用户 + **示例:**切换到为uid为1000,gid为1000的用户 + ``` OHOS # ls Directory /data/system/param: diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md index 6b8e0697408a518ea967ced71aed0f4796076cf5..73d7c12d49fc311131f6792497b63fdea4167752 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-swtmr.md @@ -1,11 +1,5 @@ # swtmr -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ swtmr [_ID_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -44,7 +38,8 @@ swtmr [_ID_] ## 输出说明 -**示例1:**查询所有软件定时器相关信息 + **示例1:**查询所有软件定时器相关信息 + ``` OHOS # swtmr SwTmrID State Mode Interval Count Arg handlerAddr @@ -64,7 +59,8 @@ SwTmrID State Mode Interval Count Arg handlerAddr 0x00000079 Ticking NSD 30000 1749 0x406189d8 0x40160e1c ``` -**示例2:**查询对应 ID 的软件定时器信息 + **示例2:**查询对应 ID 的软件定时器信息 + ``` OHOS # swtmr 1 SwTmrID State Mode Interval Count Arg handlerAddr @@ -72,7 +68,7 @@ SwTmrID State Mode Interval Count Arg handlerAddr 0x00000001 Ticking Period 1000 841 0x00000000 0x4037fc04 ``` -**表2** 输出说明 + **表2** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md index 832a60701d072f45d52fe35ae0e9ddeed763dbe8..b272a957851ccdabe3e17305c2c7fabe18a626d9 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-sysinfo.md @@ -1,11 +1,5 @@ # systeminfo -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -34,7 +28,8 @@ systeminfo ## 输出说明 -**示例:**查看系统资源使用情况 + **示例:**查看系统资源使用情况 + ``` OHOS:/$ systeminfo Module Used Total Enabled @@ -45,7 +40,7 @@ OHOS:/$ systeminfo SwTmr 20 1024 YES ``` -**表1** 输出说明 + **表1** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md index b169474cf33f6046b49dd8cec51a74cb66d8cfec..2babe2adc87c2249f0e935ec83f5b01394e2e7c3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-task.md @@ -1,11 +1,5 @@ # task -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ task/task -a ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -40,6 +34,7 @@ task/task -a **示例:**查询任务部分信息 + ``` OHOS # task allCpu(%): 3.54 sys, 196.46 idle @@ -52,6 +47,7 @@ OHOS # task 6 1 6 0 Pending 0x688000 0x137000 0x11c518 0.0 media_server 7 1 7 0 Pending 0x9d2000 0x103000 0xa1ddf 0.89 wms_server 8 1 1 1000 Running 0x2bf000 0x8f000 0x2a8c6 0.0 shell + 9 5 5 101 Pending 0x11ea000 0x2f9000 0x20429d 0.97 com.example.launcher 11 1 11 0 Pending 0x4d4000 0x112000 0xe0ad7 0.0 deviceauth_service 12 1 12 0 Pending 0x34f000 0xbd000 0x519ee 0.0 sensor_service 13 1 13 2 Pending 0x34e000 0xb3000 0x523d9 0.0 ai_server @@ -65,7 +61,7 @@ OHOS # task 7 2 0x3 -1 Pending 0x4e20 0xa5c 0.0 0 PlatformWorkerThread ``` -**表2** 输出说明 + **表2** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md index 4507fc19cc3e57cecf66ec0d2e138b27474de1b5..41d77ab903df37265daf6e82421d6fd390ee589f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-top.md @@ -1,11 +1,5 @@ # top -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ top [_-a_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 缺省值 | 取值范围 | | -------- | -------- | -------- | -------- | @@ -39,7 +33,8 @@ top [_-a_] ## 输出说明 -**示例1** top 命令显示详情 + **示例1** top 命令显示详情 + ``` OHOS:/$ top allCpu(%): 4.68 sys, 195.32 idle @@ -83,7 +78,7 @@ OHOS:/$ top 64 2 0x3 -1 Pending 0x4000 0x244 0.0 0 USB_NGIAN_BULK_TasK ``` -**表2** 输出元素说明 + **表2** 输出元素说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md index 0279282d1f36122a41222ab1973cf424594bddd6..751e98cd71e0dc448080120cd85aeacba4c595fb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-uname.md @@ -1,10 +1,5 @@ # uname -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -16,7 +11,7 @@ uname命令用于显示当前操作系统的名称,版本创建时间,系统 uname [_-a | -s | -r | -m | -n | -v | --help_] -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | | -------- | -------- | @@ -50,14 +45,16 @@ uname [_-a | -s | -r | -m | -n | -v | --help_] **示例1:** 查看系统信息 + ``` OHOS:/$ uname -a -LiteOS hisilicon 2.0.0.37 Huawei LiteOS 2.0.0.37 Oct 21 2021 17:39:32 Cortex-A7 +LiteOS hisilicon 2.0.0.37 LiteOS 2.0.0.37 Oct 21 2021 17:39:32 Cortex-A7 OHOS:/$ ``` **示例2:** 只查看操作系统名称和系统架构名称 + ``` OHOS:/$ uname -ms LiteOS Cortex-A7 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md index f9203eba0687973ae2cdd6a572c6812fe3b4427e..ec2d40a5dac31cd51dcbad680eb1f1d10e934de8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-vmm.md @@ -1,11 +1,5 @@ # vmm -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -21,7 +15,7 @@ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -42,7 +36,8 @@ ## 输出说明 -**示例:**PID为3的进程虚拟内存使用信息 + **示例:**PID为3的进程虚拟内存使用信息 + ``` OHOS # vmm 3 PID aspace name base size pages @@ -67,7 +62,7 @@ OHOS # vmm 3 0x408c3ce0 /lib/libc++.so 0x23cb0000 0x00001000 CH US RD WR 1 1 ``` -**表2** 进程基本信息 + **表2** 进程基本信息 | 输出 | 说明 | | -------- | -------- | @@ -78,7 +73,7 @@ OHOS # vmm 3 | size | 虚拟内存大小 | | pages | 已使用的物理页数量 | -**表3** 虚拟内存区间信息 + **表3** 虚拟内存区间信息 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md index 559d76ec8558e5e75fb9ab4d3592bf76d42bdbe1..c80ea6b3bda3332915997a8426762fc3c0c7d313 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd-watch.md @@ -1,11 +1,5 @@ # watch -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -21,7 +15,7 @@ watch命令用于周期性的监视一个命令的运行结果。 ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 缺省值 | 取值范围 | | -------- | -------- | -------- | -------- | @@ -44,7 +38,8 @@ watch -n 2 -c 6 task ## 输出说明 -**示例**:每隔2秒运行一次task命令,一共运行6次 + **示例**:每隔2秒运行一次task命令,一共运行6次 + ``` OHOS # watch -n 2 -c 6 task Thu Jan 1 23:57:13 1970 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd.md index 679c2b5d16bdfcc172ad4938097b0d598750d513..e0d2c6da955a7bdbfcc626a3749d346d87a1396d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-cmd.md @@ -1,6 +1,7 @@ # 系统命令 + - **[cpup](kernel-small-debug-shell-cmd-cpup.md)** - **[date](kernel-small-debug-shell-cmd-date.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-details.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-details.md index fb349660da25de3c979526890650daea2cece120..a81c2fd29885a67260ed56d7ef87cd1a230ae36a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-details.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-details.md @@ -1,5 +1,6 @@ # Shell命令使用详解 + 本章节介绍了系统关键命令的功能、格式、参数范围、使用指南和使用实例。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-error.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-error.md index 70b6dd5d2e840614cb6a9e0c855aafdc809219f5..34af47ddab683a3427fcf5508be3f6fe5fb7e73f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-error.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-error.md @@ -1,8 +1,10 @@ # 用户态异常信息说明 + 用户态在运行过程中,可能由于各种原因出现用户态系统异常,异常信息如下所示: + ``` ##################excFrom: User!#################### prefetch_abort fault fsr:0x5, far:0x00000000 @@ -64,6 +66,7 @@ system memcheck over, all passed! 1. 用户态异常基本信息: + ``` prefetch_abort fault fsr:0x5, far:0x00000000 Translation fault, section @@ -77,6 +80,7 @@ system memcheck over, all passed! ``` 2. 寄存器相关信息。 + ``` pc = 0x0 ulr = 0x2000424 in /bin/shell ---> 0x424 @@ -98,12 +102,14 @@ system memcheck over, all passed! ``` 3. 调用栈信息。 + ``` ***backtrace begin*** traceback 0 -- lr = 0x229123a4 fp = 0x0 lr in /lib/libc.so --> 0x213a4 ``` 4. 进程线程基本信息。 + ``` PID PPID PGID UID Status CPUUSE CPUUSE10s CPUUSE1s Policy Priority MTID TaskTotal Mode PName 1 -1 1 0 Ready 0.0 0.0 0.0 RR 28 16 1 user init diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md index e0c9dbd150d91c0efb4fc5ca6a18178f82bd76a2..1d3dbee27da897e5cce4e27c69cf0a1d177a8563 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md @@ -1,11 +1,5 @@ # cat -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ cat [_pathname_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -33,13 +27,14 @@ cat用于显示文本文件的内容。 ## 使用实例 -举例:cat hello-harmony.txt +举例:cat hello-openharmony.txt ## 输出说明 -**示例**:查看 hello-harmony.txt 文件的信息 + **示例**:查看 hello-openharmony.txt 文件的信息 + ``` -OHOS # cat hello-harmony.txt -OHOS # Hello Harmony ;) +OHOS # cat hello-openharmony.txt +OHOS # Hello openharmony ;) ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md index d3498566ed2e04ddc93870f330aa569ef09a4518..6e46ea2069167e6d56ebc60ef5d083772b4c81a0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cd.md @@ -1,11 +1,5 @@ # cd -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ cd [_path_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -50,6 +44,7 @@ cd [_path_] **示例**:显示结果如下 + ``` OHOS:/nfs$ cd ../ OHOS:/$ ls diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md index 26b96436f0650d62bc264e8a00221536ca5e9b35..ba5c5f55f149d8fd85a600a3179b9bd9c177c118 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chgrp.md @@ -1,11 +1,5 @@ # chgrp -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ chgrp [_group_] [_pathname_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -41,7 +35,8 @@ chgrp [_group_] [_pathname_] ## 输出说明 -**示例:**修改 dev/目录下testfile 文件的群组为100 + **示例:**修改 dev/目录下testfile 文件的群组为100 + ``` OHOS:/dev$ ll testfile -rw-r--r-- 0 0 0 0 1970-01-01 00:00 testfile diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md index 918dc9f36c4fdf7bcd13bc0ebfbf9feef2e0d3ad..f20dadc5251d4ce611a07af7fce7553d6f45c1fc 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chmod.md @@ -1,11 +1,5 @@ # chmod -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ chmod [_mode_] [_filename_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -36,18 +30,19 @@ chmod [_mode_] [_filename_] ## 使用实例 -举例:修改hello-harmony.txt 文件权限为644和777。 +举例:修改hello-openharmony.txt 文件权限为644和777。 ## 输出说明 -**示例:**修改/dev目录下 hello-harmony.txt 文件的权限 +**示例:**修改/dev目录下 hello-openharmony.txt 文件的权限 + ``` -OHOS:/dev$ chmod 644 hello-harmony.txt -OHOS:/dev$ ll hello-harmony.txt --rw-r--r-- 0 0 0 0 1970-01-01 00:00 hello-harmony.txt -OHOS:/dev$ chmod 777 hello-harmony.txt -OHOS:/dev$ ll hello-harmony.txt --rwxrwxrwx 0 0 0 0 1970-01-01 00:00 hello-harmony.txt +OHOS:/dev$ chmod 644 hello-openharmony.txt +OHOS:/dev$ ll hello-openharmony.txt +-rw-r--r-- 0 0 0 0 1970-01-01 00:00 hello-openharmony.txt +OHOS:/dev$ chmod 777 hello-openharmony.txt +OHOS:/dev$ ll hello-openharmony.txt +-rwxrwxrwx 0 0 0 0 1970-01-01 00:00 hello-openharmony.txt ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chown.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chown.md index 4a4e73f448dc9a26d0a0e9093f26afba1ebbbb5e..78c19d79a09dda19c07945a8d19a4ae25b3db2c3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chown.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-chown.md @@ -1,11 +1,5 @@ # chown -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ chown [_owner_] [_pathname_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -41,6 +35,7 @@ chown [_owner_] [_pathname_] 示例 1 修改 /dev下的testfile 文件的uid为100 + ``` OHOS:/dev$ touch testfile OHOS:/dev$ ll testfile diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md index 2e69107f50f01a739ac6c5f6db7031d157a590c5..e61e8c673a1d77ed2c35d14e557520f673f4b0ff 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cp.md @@ -1,11 +1,5 @@ # cp -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ cp [_SOURCEFILE_] [_DESTFILE_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -48,22 +42,23 @@ cp [_SOURCEFILE_] [_DESTFILE_] ## 使用实例 -举例:cp hello-OHOS.txt hello-harmony.txt ./tmp/ +举例:cp hello-OHOS.txt hello-openharmony.txt ./tmp/ ## 输出说明 **示例:**同时拷贝两个文件至指定目录 + ``` OHOS:/$ ls bin hello-OHOS.txt proc system vendor -dev hello-harmony.txt sdcard userdata +dev hello-openharmony.txt sdcard userdata etc lib storage usr OHOS:/$ mkdir tmp -OHOS:/$ cp hello-OHOS.txt hello-harmony.txt tmp/ +OHOS:/$ cp hello-OHOS.txt hello-openharmony.txt tmp/ OHOS:/$ ll tmp total 0 -rwxrwxrwx 1 0 0 0 1979-12-31 00:00 hello-OHOS.txt* --rwxrwxrwx 1 0 0 0 1979-12-31 00:00 hello-harmony.txt* +-rwxrwxrwx 1 0 0 0 1979-12-31 00:00 hello-openharmony.txt* ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md index 2d589fb8b937d8d332b1f5e12d2663969eb386d2..b891546e73f8657e8998c7a1f3927cf48677167a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-du.md @@ -1,11 +1,5 @@ # du -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ du [_-kKmh_] [_file..._] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -47,7 +41,8 @@ du [_-kKmh_] [_file..._] **示例:**显示结果如下 + ``` -OHOS:/$ du-h testfile +OHOS:/$ du -h testfile 1.8K testfile ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md index e998feb1b16287240f5fa4bf7779938c1e0fca4b..36b0a095b14c99dc859845b3beb754782bb4a7e8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-format.md @@ -1,11 +1,5 @@ # format -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,13 +13,13 @@ format <_dev_inodename_> <_sectors_> <_option_> [_label_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | | -------- | -------- | | dev_inodename | 设备名。 | | sectors | 分配的单元内存或扇区大小,如果输入0表示参数为空。(取值必须为0或2的幂,fat32下最大值为128,取值0表示自动选择合适的簇大小,不同size的分区,可用的簇大小范围不同,错误的簇大小指定可能导致格式化失败)。 | -| option | 格式化选项,用来选择文件系统的类型,有如下几种参数选择:
- 0x01:FMT_FAT
- 0x02:FMT_FAT32
- 0x07:FMT_ANY
- 0x08:FMT_ERASE (USB不支持该选项)
传入其他值皆为非法值,将由系统自动选择格式化方式。若格式化U盘时低格位为 1,会出现错误打印。 | +| option |   格式化选项,用来选择文件系统的类型,有如下几种参数选择:
- 0x01:FMT_FAT
- 0x02:FMT_FAT32
- 0x07:FMT_ANY
- 0x08:FMT_ERASE (USB不支持该选项)
传入其他值皆为非法值,将由系统自动选择格式化方式。若格式化U盘时低格位为 1,会出现错误打印。 | | label | 该参数为可选参数,输入值应为字符串,用来指定卷标名。当输入字符串"null"时,则把之前设置的卷标名清空。 | @@ -47,6 +41,7 @@ format <_dev_inodename_> <_sectors_> <_option_> [_label_] **示例**:格式化mmc卡 + ``` OHOS # format /dev/mmcblk1 128 2 Format to FAT32, 128 sectors per cluster. diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md index aed513028d5d20f18ac4275ca8c3994d4c32c0fa..e3dbbbf23be397f5f4cd7e3685516feca1805a19 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-ls.md @@ -1,11 +1,5 @@ # ls -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -22,7 +16,7 @@ ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] ## 参数说明 -**表1** 展示功能参数说明 + **表1** 展示功能参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -42,7 +36,7 @@ ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] | -Z | 安全上下文。 | N/A | | path | path为空时,显示当前目录的内容。
path为无效文件名时,显示失败,提示:
ls error: No such directory。
path为有效目录路径时,会显示对应目录下的内容。 | 1.为空。
2.有效的目录路径 | -**表2** 输出格式参数说明 + **表2** 输出格式参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -58,7 +52,7 @@ ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] | -ll | 文件的时间属性显示纳秒。 | N/A | | --color | 彩色打印。 | 默认配置为:device=yellow symlink=turquoise/red dir=blue socket=purple files: exe=green suid=red suidfile=redback stickydir=greenback=auto means detect if output is a tty. | -**表3** 排序参数说明(默认为按首字母排序) + **表3** 排序参数说明(默认为按首字母排序) | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -70,7 +64,7 @@ ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] ## 使用指南 -无 + 无 > ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** > fatfs的文件节点信息继承其父节点,父节点号为0。故在hi3516dv300开发板上ls -i显示的文件节点号全为0。 @@ -88,6 +82,7 @@ ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] **示例1:**ls命令查看当前路径下的内容 + ``` OHOS:/$ ls bin etc nfs sdcard system usr @@ -96,6 +91,7 @@ dev lib proc storage userdata vendor **示例2:**ll命令查看当前路径下的内容 + ``` OHOS:/$ ll total 20 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md index 0e80d339eb2a65b50b855d9b7108c5b5148a4831..c3d5fb687598b1fa670e95cd6e7fa690a3b16e37 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-lsfd.md @@ -1,10 +1,5 @@ # lsfd -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -30,6 +25,7 @@ lsfd命令显示当前已经打开文件的fd号以及文件的名字。 **示例:**lsfd输出说明 + ``` OHOS # lsfd fd filename diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mkdir.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mkdir.md index 65c54877ff54c1971a0cc6df42915d72b2a13dec..0686dd2e46f17493d3f465919b1b79663f127c54 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mkdir.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mkdir.md @@ -1,11 +1,5 @@ # mkdir -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ mkdir [_-vp_] [_-m mode_] [_dirname..._] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -51,6 +45,7 @@ mkdir [_-vp_] [_-m mode_] [_dirname..._] ## 输出说明 + ``` OHOS:/tmp$ mkdir testpath OHOS:/tmp$ ll @@ -60,6 +55,7 @@ drwxrwxrwx 1 0 0 2048 1979-12-31 00:00 testpath/ 示例 2 创建指定mode的目录 + ``` OHOS:/tmp$ mkdir -m 777 testpath OHOS:/tmp$ ll @@ -69,6 +65,7 @@ drwxrwxrwx 1 0 0 2048 1979-12-31 00:00 testpath/ 示例 3 逐级创建目录 + ``` OHOS:/tmp$ mkdir -pv testpath01/testpath02/testpath03 mkdir: created directory 'testpath01' diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md index 83ee18743d09407e0d5c242fd7a60599ee874a48..d2ddc4f1aad519df0ef512c263727c8b1bfd9b29 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mount.md @@ -1,11 +1,5 @@ # mount -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ mount [_-f_] [_-t TYPE_] [_-o OPTION,_] [[_DEVICE_] _DIR_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -45,6 +39,7 @@ mount后加需要挂载的设备信息、指定目录以及设备文件格式, **示例:**将服务器端nfs目录192.168.1.3:/nfs挂载到当前系统下新建的/nfs目录: + ``` OHOS:/$ mkdir nfs OHOS:/$ mount -t nfs 192.168.1.3:/nfs nfs diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md index abbd83e9ecf3cd45b08121fb868c7d29f47185c9..f3d42a9f3526ca00aef505034e10d8e6d86881c3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-mv.md @@ -1,11 +1,5 @@ # mv -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ mv [_-fivn_] _SOURCE... DEST_ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -56,6 +50,7 @@ mv [_-fivn_] _SOURCE... DEST_ **示例 1** 显示结果如下 + ``` OHOS:/$ touch test.txt OHOS:/$ mkdir testpath @@ -78,6 +73,7 @@ dev lib sdcard system testpath usr **示例 2** 通配符使用 + ``` OHOS:/$ ls bin etc proc storage test.txt testA.txt testpath usr diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md index 15e1680b8b6a2df228b53eaa3cede49ed7538655..30013e2e9bb817d1e224f7320131dbc749f82d9a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partinfo.md @@ -1,11 +1,5 @@ # partinfo -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ partinfo <_dev_inodename_> ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -40,6 +34,7 @@ partinfo <_dev_inodename_> **示例**:查看系统分区信息 + ``` OHOS # partinfo /dev/mmcblk0p0 part info : diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partition.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partition.md index a7d0c1e6a288b86d1ecbe5035c2f4e5f17df3cb9..17ad5db556ce953664f49e3f97177c2b047e4d45 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partition.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-partition.md @@ -1,11 +1,5 @@ # partition -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ partition [_nand / spinor_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -43,6 +37,7 @@ partition [_nand / spinor_] 查看spinor flash分区信息 + ``` OHOS # partition spinor spinor partition num:0, blkdev name:/dev/spinorblk0, mountpt:/, startaddr:0x00500000, length:0x00a00000 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md index b5d77d67c7ce5e19d736b75336aa0aa843ee9903..7e57659bf2be360b01ccefd018e18be50083b860 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-pwd.md @@ -1,11 +1,5 @@ # pwd -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -36,6 +30,7 @@ pwd 命令将当前目录的全路径名称(从根目录)写入标准输出 **示例**:查看当前路径 + ``` OHOS:/sdcard/nfs$ pwd /sdcard/nfs diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md index c6d29a3f5ef3cff86b1c346fd582cf5406755cbf..19d5bac19ba2aa389c410c0bf71181d1bc54c0ef 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rm.md @@ -1,11 +1,5 @@ # rm -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ rm [_-fv_] _FILE or rm_ [_-rv_] [_PATH_ | _filename_]... ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -51,6 +45,7 @@ rm [_-fv_] _FILE or rm_ [_-rv_] [_PATH_ | _filename_]... **示例 1** 用 rm 命令删除文件 testfile + ``` OHOS:/$ ls bin etc proc storage testfile usr @@ -63,6 +58,7 @@ dev lib sdcard system usr **示例 2** 用 rm -r 删除非空目录 testpath + ``` OHOS:/$ ls bin etc proc storage testpath usr diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md index a889240396fff5caae08785863b3fc5f57359237..0318f2a9221697832a928751be4725299ffd7c88 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-rmdir.md @@ -1,11 +1,5 @@ # rmdir -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ rmdir [_-p_] [_dirname..._] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -47,6 +41,7 @@ rmdir [_-p_] [_dirname..._] **示例:**删除一个名为 dir 的目录 + ``` OHOS:/test$ mkdir dir OHOS:/test$ ls diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md index c84a645400a553a665b3c2425f9c800432e29cc5..cd875e681672ec126a356327c38dab4cf5f47c4b 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-statfs.md @@ -1,10 +1,5 @@ # statfs -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) ## 命令功能 @@ -18,7 +13,7 @@ statfs [_directory_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -36,7 +31,8 @@ statfs [_directory_] statfs /nfs -**示例**:statfs输出说明 + **示例**:statfs输出说明 + ``` OHOS # statfs ./nfs statfs got: diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-sync.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-sync.md index d019481a30e3e6511949152d329b9dfdf1c4c4b8..942e3e5b88ede73f6a869a191c5f6ac8866da7f3 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-sync.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-sync.md @@ -1,11 +1,5 @@ # sync -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md index 6b6984cda48511e9192d20b2dd8fb38639426df9..5f818737286794ea690a381f2ea7e4d8c62e93cf 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-touch.md @@ -1,11 +1,5 @@ # touch -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -21,7 +15,7 @@ touch [_filename_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -51,6 +45,7 @@ touch [_filename_] **示例 1** 创建一个名为 file.c 的文件 + ``` OHOS:/tmp$ ls OHOS:/tmp$ touch file.c @@ -63,6 +58,7 @@ total 0 **示例 2** 同时创建三个文件 + ``` *OHOS:/tmp$ OHOS:/tmp$ touch testfile1 testfile2 testfile3 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md index 1a759d5c751ac7dfded14c355f4b0c122d41acd0..de3e13e5605974b836fbe1ac172bcc69031bbb34 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-umount.md @@ -1,11 +1,5 @@ # umount -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ umount [_-a [-t TYPE]_] [_dir_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -49,6 +43,7 @@ umount后加上需要卸载的指定文件系统的目录,即将指定文件 **示例 1** umount输出示例 + ``` OHOS:/$ umount ./nfs/ umount ok @@ -56,7 +51,8 @@ umount ok **示例 2** 卸载所有已挂载的nfs类型的目录 + ``` -OHOS:/$ umount -a-t nfs +OHOS:/$ umount -a -t nfs umount ok ``` diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-write.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-write.md index c7ab7fcf662761c9e7539089e530a4c3e5d1d661..6987c4571e6332e1c495d0cd07408e810f146df0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-write.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-write.md @@ -1,11 +1,5 @@ # writeproc -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ writeproc <_data_> >> /proc/<_filename_> ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file.md index fad2fc2cf657897c3c0146390a281bb80f94cd51..cac598650b304dda9b641d48666b773f63fc1b8e 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-file.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file.md @@ -1,6 +1,7 @@ # 文件命令 + - **[cat](kernel-small-debug-shell-file-cat.md)** - **[cd](kernel-small-debug-shell-file-cd.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-guide.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-guide.md index b25733026d13c21ebd0c57e3a9f32405580a9aa7..86bc42460e8ae9ae9ae5128543cc64c36d43d4f8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-guide.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-guide.md @@ -1,6 +1,5 @@ # Shell命令开发指导 -- [开发指导](#开发指导) ## 开发指导 @@ -8,6 +7,7 @@ 1. 包含如下头文件: + ``` #include "shell.h" #include "shcmd.h" @@ -20,11 +20,12 @@ 1. 通过宏的方式注册。 这个宏的原型为: + ``` SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) ``` - **表1** SHELLCMD_ENTRY参数详解 + **表1** SHELLCMD_ENTRY参数详解 | 参数 | 描述 | | -------- | -------- | @@ -36,6 +37,7 @@ 如: + ``` SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) ``` @@ -45,11 +47,12 @@ 注册函数原型: + ``` UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) ``` - **表2** UINT32 osCmdReg参数详解 + **表2** UINT32 osCmdReg参数详解 | 参数 | 描述 | | -------- | -------- | @@ -60,6 +63,7 @@ 如: + ``` osCmdReg(CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) ``` @@ -71,11 +75,12 @@ 3. 添加内置命令函数原型。 + ``` UINT32 osShellCmdLs(UINT32 argc, CHAR **argv) ``` - **表3** osShellCmdLs参数说明 + **表3** osShellCmdLs参数说明 | 参数 | 参数描述 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-magickey.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-magickey.md index b7b694b4bcb2fd6dc80b3cc68ff576fd06a32861..e79ea3ebd25704c991e212a4b3f9a1d58819c43d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-magickey.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-magickey.md @@ -1,7 +1,5 @@ # 魔法键使用方法 -- [使用场景](#使用场景) -- [使用方法](#使用方法) ## 使用场景 @@ -16,7 +14,7 @@ 魔法键依赖于宏LOSCFG_ENABLE_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”: -Debug ---> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 + Debug ---> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 1. 可以在menuconfig中,将光标移动到LOSCFG_ENABLE_MAGICKEY上,输入“?”,查看帮助信息。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md index 24cee72fb42297956b88ea8ad1f1896693bf47f9..d8609af2b50f366eb20f65406a02c5660df3fdd0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-arp.md @@ -1,10 +1,5 @@ # arp -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) ## 命令功能 @@ -22,7 +17,7 @@ arp [_-i IF_] -d _IPADDR_ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -45,14 +40,15 @@ arp [_-i IF_] -d _IPADDR_ 输入arp -**示例:**打印整个 ARP 缓存表 + **示例:**打印整个 ARP 缓存表 + ``` OHOS # arp Address HWaddress Iface Type 192.168.1.10 E6:2B:99:2C:4B:20 eth0 static ``` -**表2** 参数说明 + **表2** 参数说明 | 参数 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md index fe91b3e69780dfd91266d0926377d53677565ace..869fc72a0b4a3ba3c14d3488f477529e906f830e 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-dhclient.md @@ -1,10 +1,5 @@ # dhclient -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) ## 命令功能 @@ -20,7 +15,7 @@ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -42,6 +37,7 @@ **示例1:**启动网卡eth0的dhcp请求 + ``` OHOS:/$ dhclient eth0 OHOS:/$ ifconfig @@ -57,6 +53,7 @@ OHOS:/$ **示例2:**关闭网卡eth0的dhcp请求 + ``` OHOS:/$ dhclient -x eth0 NetifStatusCallback(eth0): nsc event: 0xf0 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md index 47cf1a1ecba58465ba8cc79414069febca947c95..62b3650b5163641da96cc4e79cdc006fd0eedf4c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ifconfig.md @@ -1,11 +1,5 @@ # ifconfig -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -33,7 +27,7 @@ option: ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -72,6 +66,7 @@ option: ## 输出说明 - **示例1:**设置网络参数 + ``` OHOS:/$ ifconfig eth0 192.168.100.31 netmask 255.255.255.0 gateway 192.168.100.1 hw ether 00:49:cb:6c:a1:31 OHOS:/$ ifconfig @@ -84,7 +79,7 @@ option: 输出的各参数说明如下表所示: - **表2** 参数说明 + **表2** 参数说明 | 参数 | 说明 | | -------- | -------- | @@ -98,6 +93,7 @@ option: | Link UP/Down | 网卡连接状态。 | - **示例2:**获取协议栈统计信息 + ``` OHOS # ifconfig -a RX packets:6922 errors:0 ip dropped:4312 link dropped:67 overrun:0 bytes:0 (0.0 B) @@ -108,7 +104,7 @@ option: 输出的各参数说明如下表所示: - **表3** ifconfig -a 参数说明 + **表3** ifconfig -a 参数说明 | 参数 | 说明 | | -------- | -------- | @@ -124,6 +120,7 @@ option: | TX bytes | IP层已正常发送或者转发的数据包的总长度。 | - **示例3**:设置IPv6的地址信息 + ``` OHOS:/$ ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d NetifStatusCallback(eth0): nsc event: 0x8 @@ -143,6 +140,7 @@ option: ``` - **示例4**:删除IPv6的地址信息 + ``` OHOS:/$ ifconfig eth0 inet6 del 2001:a:b:c:d:e:f:d NetifStatusCallback(eth0): nsc event: 0x200 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md index 21a6344fcab3f278bd0bc06d125a5b48f33ed999..20346dea9982f997bb3a421a2079f59204643c8d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ipdebug.md @@ -1,9 +1,5 @@ # ipdebug -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [使用示例](#使用示例) -- [输出说明](#输出说明) ## 命令功能 @@ -22,7 +18,8 @@ ipdebug ## 输出说明 -**示例:**ipdebug打印信息如下: + **示例:**ipdebug打印信息如下: + ``` OHOS # ipdebug ================= diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md index 9bdae8e0b8411bb977b71d361b06b92502e97edc..bf466ca6c04f6836245e2fe42432152d4087c2ac 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-netstat.md @@ -1,11 +1,5 @@ # netstat -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -34,7 +28,8 @@ netstat ## 输出说明 -**示例:**netstat 打印信息 + **示例:**netstat 打印信息 + ``` OHOS # netstat ========== total sockets 128 ====== unused sockets 119 ========== @@ -51,7 +46,7 @@ udp 0 0 127.0.0.1:62180 127.0.0.1:62179 udp 0 0 127.0.0.1:62178 127.0.0.1:62177 ``` -**表1** 输出说明 + **表1** 输出说明 | 输出 | 说明 | | -------- | -------- | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ntpdate.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ntpdate.md index be948a9348579b9a180a9889f2f39af89f09e477..635a4e46aa7a219141f89cc9d7c079715c917ca7 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ntpdate.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ntpdate.md @@ -1,11 +1,5 @@ # ntpdate -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ ntpdate [_SERVER_IP1_] [_SERVER_IP2_]... ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -38,6 +32,7 @@ ntpdate [_SERVER_IP1_] [_SERVER_IP2_]... ## 输出说明 + ``` OHOS # ntpdate 192.168.1.3 time server 192.168.1.3: Mon Jun 13 09:24:25 2016 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md index cde5341cbd8b17888dd843ac7eea8805b6ebe336..111cadec60a336585ffdd2a4f700035f7948f6e6 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping.md @@ -1,11 +1,5 @@ # ping -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ ping _[-4] [-c cnt] [-f] [-i interval] [-q] [-s size] <IP>_ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -51,7 +45,8 @@ ping _[-4] [-c cnt] [-f] [-i interval] [-q] [-s size] <IP>_ ## 输出说明 -**示例:**ping tftp 服务器地址 + **示例:**ping tftp 服务器地址 + ``` OHOS:/$ ping 192.168.1.3 Ping 192.168.1.3 (192.168.1.3): 56(84) bytes. diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping6.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping6.md index aaf2c26060707b24206a5410a54e0811e0ba3fb0..16a6843b1e363085372cdb7d072e85c18d98003c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping6.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-ping6.md @@ -1,11 +1,5 @@ # ping6 -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -52,6 +46,7 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ## 输出说明 1. 输入ping6 2001:a:b:c:d:e:f:b + ``` OHOS # ping6 2001:a:b:c:d:e:f:b PING 2001:A:B:C:D:E:F:B with 56 bytes of data. 56 bytes from 2001:A:B:C:D:E:F:B : icmp_seq=1 time<1 ms @@ -64,6 +59,7 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ``` 2. 输入 ping6 -c 3 2001:a:b:c:d:e:f:b 指定3次进行网络测试 + ``` OHOS # ping6 -c 3 2001:a:b:c:d:e:f:b PING 2001:A:B:C:D:E:F:B with 56 bytes of data. 56 bytes from 2001:A:B:C:D:E:F:B : icmp_seq=1 time<1 ms @@ -75,6 +71,7 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ``` 3. 输入 ping6 -I eth0 2001:a:b:c:d:e:f:b 使用指定网卡接口eth0测试IPv6。 + ``` OHOS # ping6 -I eth0 2001:a:b:c:d:e:f:b PING 2001:A:B:C:D:E:F:B with 56 bytes of data. 56 bytes from 2001:A:B:C:D:E:F:B : icmp_seq=1 time=10 ms @@ -86,6 +83,7 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ``` 4. 输入 ping6 -I 2001:a:b:c:d:e:f:d 2001:a:b:c:d:e:f:b 使用指定的源IPv6地址2001:a:b:c:d:e:f:d进行测试。 + ``` OHOS # ping6 -I 2001:a:b:c:d:e:f:d 2001:a:b:c:d:e:f:b PING 2001:A:B:C:D:E:F:B with 56 bytes of data. 56 bytes from 2001:A:B:C:D:E:F:B : icmp_seq=1 time<1 ms diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md index 208968d164b81c765870f89e6dcbf168b2383e73..7a72745d7044b98cf4b63d63b89ac78dafcce29c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-telnet.md @@ -1,11 +1,5 @@ # telnet -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -19,7 +13,7 @@ telnet [_on | off_] ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -45,6 +39,7 @@ telnet [_on | off_] **示例:**输入 telnet on + ``` OHOS # telnet on OHOS # start telnet server successfully, waiting for connection. diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-tftp.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-tftp.md index 7a343193bfa87fc6d1195e2e4e0555f43cc7f74a..5772a7a8053d05d21885ed5aff065a463e0d9bfb 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-tftp.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net-tftp.md @@ -1,11 +1,5 @@ # tftp -- [命令功能](#命令功能) -- [命令格式](#命令格式) -- [参数说明](#参数说明) -- [使用指南](#使用指南) -- [使用实例](#使用实例) -- [输出说明](#输出说明) ## 命令功能 @@ -21,7 +15,7 @@ tftp命令可以从TFTP服务器上下载文件。 ## 参数说明 -**表1** 参数说明 + **表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -49,6 +43,7 @@ tftp命令可以从TFTP服务器上下载文件。 ## 输出说明 + ``` OHOS # ./bin/tftp -g -l /nfs/out -r out 192.168.1.2 TFTP transfer finish diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net.md index a3d24f0cac561cdce4342ccfc883f0bd010984c7..c03efbc94ebbf5e9f530c104a45c64eba1003fbe 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-net.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-net.md @@ -1,6 +1,7 @@ # 网络命令 + - **[arp](kernel-small-debug-shell-net-arp.md)** - **[dhclient](kernel-small-debug-shell-net-dhclient.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell-overview.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-overview.md index 0b9e6fb087ca61fce954f8602539da94dd53999e..68d4da526e156f1201933b58c9e5d3421e5e6777 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell-overview.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell-overview.md @@ -1,6 +1,5 @@ # Shell介绍 -- [注意事项](#注意事项) OpenHarmony内核提供的Shell支持调试常用的基本功能,包含系统、文件、网络和动态加载相关命令。同时OpenHarmony内核的Shell支持添加新的命令,可以根据需求来进行定制。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-shell.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell.md index f07325ca6758363709635ada7fff9f110389ac4b..99c849aa2a13dec93ba0f7d04544956fef239b9a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-shell.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-shell.md @@ -1,6 +1,7 @@ # Shell + - **[Shell介绍](kernel-small-debug-shell-overview.md)** - **[Shell命令开发指导](kernel-small-debug-shell-guide.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-faqs.md b/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-faqs.md index c78cd368ba9309d3eee530d34098d4ff91dd7dba..525b873132507c485fdaa3245ee2cd3031692e61 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-faqs.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-faqs.md @@ -1,15 +1,12 @@ -# 常见问题定位方法 +# 常见问题 -- [通过异常信息定位问题](#通过异常信息定位问题) -- [内存池完整性验证](#内存池完整性验证) -- [全局变量踩内存定位方法](#全局变量踩内存定位方法) ## 通过异常信息定位问题 系统异常被挂起后,会在串口看到一些关键寄存器的信息,如图1所示。可通过这些信息定位到异常所在函数和其调用栈关系,为原因分析提供第一手资料。 -**图1** 异常信息 -![zh-cn_image_0000001153823524](figures/zh-cn_image_0000001153823524.png) + **图1** 异常信息 + ![zh-cn_image_0000001153823524](figures/zh-cn_image_0000001153823524.png) 上图中的异常信息主要解释4个标签: diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-lastwords.md b/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-lastwords.md index c74d2a8661cbb5d2c4b09bcdca96a6019072dfe7..c1beaf2512e897a7abb0ef1c95bd49c84b51d7db 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-lastwords.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-trace-other-lastwords.md @@ -1,9 +1,5 @@ # 临终遗言 -- [使用场景](#使用场景) -- [功能说明](#功能说明) -- [参数说明](#参数说明) -- [开发流程](#开发流程) ## 使用场景 @@ -14,7 +10,6 @@ 该调测功能提供了一种用于保存系统异常时打印信息到不丢失存储介质中的机制,用户可自行注册读写异常时打印信息的钩子函数,实现在不同存储介质上保存异常信息的能力,这样方便无串口的设备的问题定位。接口名为LOS_ExcInfoRegHook,该函数声明在los_config.h中,函数原型: - ``` typedef VOID (*log_read_write_fn)(UINT32 startAddr, UINT32 space, UINT32 rwFlag, CHAR *buf); ...... @@ -24,23 +19,23 @@ VOID LOS_ExcInfoRegHook(UINT32 startAddr, UINT32 space, CHAR *buf, log_read_writ ## 参数说明 -**表1** LOS_ExcInfoRegHook 参数说明 + **表1** LOS_ExcInfoRegHook 参数说明 -| 参数 | 参数说明 | +| 参数 | 参数说明 | | -------- | -------- | -| startAddr | 存取异常信息的物理介质起始地址 | -| space | 存取的空间大小 | -| buf | 存取异常信息的内存缓冲区 | -| log_read_write_fn | 存取异常信息的函数 | +| startAddr | 存取异常信息的物理介质起始地址 | +| space | 存取的空间大小 | +| buf | 存取异常信息的内存缓冲区 | +| log_read_write_fn | 存取异常信息的函数 | -**表2** log_read_write_fn 参数说明 + **表2** log_read_write_fn 参数说明 -| 参数 | 参数说明 | +| 参数 | 参数说明 | | -------- | -------- | -| startAddr | 存取异常信息的物理介质起始地址 | -| space | 存取的空间大小 | -| rwFlag | 读写标记,0为写,1为读 | -| buf | 存取异常信息的内存缓冲区 | +| startAddr | 存取异常信息的物理介质起始地址 | +| space | 存取的空间大小 | +| rwFlag | 读写标记,0为写,1为读 | +| buf | 存取异常信息的内存缓冲区 | ## 开发流程 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-trace.md b/zh-cn/device-dev/kernel/kernel-small-debug-trace.md index 07e975b0d0e2eadaae5916b69fe974bc6b6d3a50..86694be5dc3329d6541409138f9538bc7b64f2bf 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-trace.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-trace.md @@ -1,15 +1,5 @@ -# Trace - -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) - - [内核态](#内核态) - - [用户态](#用户态) -- [开发指导](#开发指导) - - [内核态开发流程](#内核态开发流程) -- [内核态编程实例](#内核态编程实例) -- [内核态示例代码](#内核态示例代码) -- [结果验证](#结果验证) +# Trace调测 + ## 基本概念 @@ -38,19 +28,15 @@ Trace提供2种工作模式,离线模式和在线模式。 LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_trace.h)参考。 -**表1** Trace模块接口说明 + **表1** Trace模块接口说明 -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 启停控制 | LOS_TraceStart | 启动Trace | -| | LOS_TraceStop |停止Trace| -| 操作Trace记录的数据 | LOS_TraceRecordDump | 输出Trace缓冲区数据 | -| | LOS_TraceRecordGet |获取Trace缓冲区的首地址| -| | LOS_TraceReset |清除Trace缓冲区中的事件| -| 过滤Trace记录的数据 | LOS_TraceEventMaskSet | 设置事件掩码,仅记录某些模块的事件 | -| 屏蔽某些中断号事件 | LOS_TraceHwiFilterHookReg | 注册过滤特定中断号事件的钩子函数 | -| 插桩函数 | LOS_TRACE_EASY | 简易插桩 | -| | LOS_TRACE |标准插桩| +| 功能分类 | 接口描述 | +| -------- | -------- | +| 启停控制 | LOS_TraceStart:启动Trace
LOS_TraceStop:停止Trace | +| 操作Trace记录的数据 | LOS_TraceRecordDump:输出Trace缓冲区数据
LOS_TraceRecordGet:获取Trace缓冲区的首地址
LOS_TraceReset:清除Trace缓冲区中的事件 | +| 过滤Trace记录的数据 | LOS_TraceEventMaskSet:设置事件掩码,仅记录某些模块的事件 | +| 屏蔽某些中断号事件 | LOS_TraceHwiFilterHookReg:注册过滤特定中断号事件的钩子函数 | +| 插桩函数 | LOS_TRACE_EASY:简易插桩
LOS_TRACE:标准插桩 | - 当用户需要针对自定义事件进行追踪时,可按规则在目标源代码中进行插桩,系统提供如下2种插桩接口: - LOS_TRACE_EASY(TYPE, IDENTITY, params...) 简易插桩。 @@ -58,7 +44,8 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - TYPE有效取值范围为[0, 0xF],表示不同的事件类型,不同取值表示的含义由用户自定义。 - IDENTITY类型UINTPTR,表示事件操作的主体对象。 - Params类型UINTPTR,表示事件的参数。 - 示例: + 示例: + ``` 假设需要新增对文件(fd1、fd2)读写操作的简易插桩, 自定义读操作为type:1, 写操作为type:2,则 @@ -75,7 +62,8 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - 相比简易插桩,支持动态过滤事件和参数裁剪,但使用上需要用户按规则来扩展。 - TYPE用于设置具体的事件类型,可以在头文件los_trace.h中的enum LOS_TRACE_TYPE中自定义事件类型。定义方法和规则可以参考其他事件类型。 - IDENTITY和Params的类型及含义同简易插桩。 - 示例: + 示例: + ``` 1.在enum LOS_TRACE_MASK中定义事件掩码,即模块级别的事件类型。 定义规范为TRACE_#MOD#_FLAG,#MOD#表示模块名。 @@ -98,7 +86,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 LOS_TRACE(FS_READ, fp, fd, flag, size); // 读文件的代码桩, #TYPE#之后的入参就是上面3中的FS_READ_PARAMS函数的入参 ``` - + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 预置的Trace事件及参数均可以通过上述方式进行裁剪,参数详见kernel\include\los_trace.h。 @@ -111,7 +99,8 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - Trace的典型操作流程为:LOS_TraceStart、 LOS_TraceStop、 LOS_TraceRecordDump. - 针对中断事件的Trace, 提供中断号过滤,用于解决某些场景下特定中断号频繁触发导致其他事件被覆盖的情况,用户可自定义中断过滤的规则, - 示例如下: + 示例如下: + ``` BOOL Example_HwiNumFilter(UINT32 hwiNum) { @@ -136,6 +125,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - ioctl: 用户态Trace控制操作,包括 + ``` #define TRACE_IOC_MAGIC 'T' #define TRACE_START _IO(TRACE_IOC_MAGIC, 1) @@ -166,8 +156,8 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 | LOSCFG_RECORDER_MODE_OFFLINE | Trace work mode ->Offline mode | Trace工作模式为离线模式 | YES/NO | | LOSCFG_RECORDER_MODE_ONLINE | Trace work mode ->Online mode | Trace工作模式为在线模式 | YES/NO | | LOSCFG_TRACE_CLIENT_INTERACT | Enable Trace Client Visualization and Control | 使能与Trace IDE (dev tools)的交互,包括数据可视化和流程控制 | YES/NO | - | LOSCFG_TRACE_FRAME_CORE_MSG | Enable Record more extended content ->Record cpuid, hardware interrupt status, task lock status | 记录CPUID、中断状态、锁任务状态 | YES/NO | - | LOSCFG_TRACE_FRAME_EVENT_COUNT | Enable Record more extended content ->Record event count, which indicate the sequence of happend events | 记录事件的次序编号 | YES/NO | + | LOSCFG_TRACE_FRAME_CORE_MSG | Enable Record more extended content -
>Record cpuid, hardware interrupt
 status, task lock status | 记录CPUID、中断状态、锁任务状态 | YES/NO | + | LOSCFG_TRACE_FRAME_EVENT_COUNT | Enable Record more extended content
 ->Record event count,
 which indicate the sequence of happend events | 记录事件的次序编号 | YES/NO | | LOSCFG_TRACE_FRAME_MAX_PARAMS | Record max params | 配置记录事件的最大参数个数 | INT | | LOSCFG_TRACE_BUFFER_SIZE | Trace record buffer size | 配置Trace的缓冲区大小 | INT | @@ -215,6 +205,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 实例代码如下: + ``` #include "los_trace.h" UINT32 g_traceTestTaskId; @@ -266,6 +257,7 @@ LOS_MODULE_INIT(Example_Trace_test, LOS_INIT_LEVEL_KMOD_EXTENDED); 输出结果如下: + ``` ***TraceInfo begin*** clockFreq = 50000000 @@ -294,6 +286,7 @@ Index Time(cycles) EventType CurTask Identity params 下面以序号为0的输出项为例,进行说明。 + ``` Index Time(cycles) EventType CurTask Identity params 0 0x366d5e88 0x45 0x1 0x0 0x1f 0x4 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md index e77727e14ba3251557ea34073d83c6da903bf298..a7cc077a34da0c5e059666ac8b2e746dcecd4c5a 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-concept.md @@ -1,5 +1,6 @@ # 基本概念 + Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、踩内存分析以及backtrace功能等维测手段,可以提高用户态内存相关问题的定位效率。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md index d6d754fcaf907474615249b4b138bceadb14bdf9..ada7ba2316eea4b95ad92e0d2f7c2ca7e4f02f23 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-faqs.md @@ -1,4 +1,5 @@ -# 常见问题场景 +# 常见问题 + ## UAF(Use after free) @@ -27,6 +28,7 @@ Double free时,用户程序将会异常退出。 - 申请小块内存(不大于0x1c000) 堆内存节点被踩时,用户程序将会异常退出,并输出破坏被踩节点的可能的堆内存申请调用栈,对于野指针踩内存情况无法校验出来。例如用户程序mem_check中存在堆内存越界踩的情况,利用命令行方式可以获得踩内存的可能的具体位置。 + ``` OHOS # ./mem_check --mwatch OHOS # diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md index 3955e8ae2208343a320340a12a035ee2f680e554..98cd4ab5979703259d5ae8ab50fb13cb76322a1d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-function.md @@ -1,8 +1,5 @@ # 运行机制 -- [内存泄漏检查](#内存泄漏检查) -- [堆内存统计](#堆内存统计) -- [内存完整性检查](#内存完整性检查) ## 内存泄漏检查 @@ -12,13 +9,15 @@ 释放内存时:根据需要释放的内存地址匹配内存节点控制块并将该控制块删除。 -**图1** 堆内存节点信息链表 -![zh-cn_image_0000001165890158](figures/zh-cn_image_0000001165890158.png) + **图1** 堆内存节点信息链表 + + ![zh-cn_image_0000001165890158](figures/zh-cn_image_0000001165890158.png) 申请内存时,返回地址会被保存到LR寄存器中。进程运行过程中,系统会在内存节点控制块中添加疑似泄漏点对应的lr等信息。如下图所示: -**图2** 堆内存节点信息 -![zh-cn_image_0000001165890518](figures/zh-cn_image_0000001165890518.png) + **图2** 堆内存节点信息 + + ![zh-cn_image_0000001165890518](figures/zh-cn_image_0000001165890518.png) 其中,TID表示线程ID;PID表示进程ID;ptr表示申请的内存地址;size表示申请的内存大小;lr[n]表示函数调用栈地址,变量n可以根据具体场景的需要进行配置。 @@ -26,13 +25,14 @@ 用户通过串口或文件等方式,将各个进程内存调测信息导出,利用addr2line工具将导出的信息转换成导致内存泄漏的代码行,便可以解决内存泄露问题。 -**图3** 泄漏点代码行定位流程 -![zh-cn_image_0000001165730464](figures/zh-cn_image_0000001165730464.png) + **图3** 泄漏点代码行定位流程 + + ![zh-cn_image_0000001165730464](figures/zh-cn_image_0000001165730464.png) ## 堆内存统计 -用户态线程堆内存使用统计具有一定的实际意义,统计线程申请的堆内存占比,为用户程序的内存使用优化提供数据支持。用户态堆内存统计模块主要涉及的接口为malloc和free。如图1所示,每个进程维护128个链表,链表索引即线程ID,申请内存时系统将ptr和size信息记录在内存节点控制块中并将节点控制块挂在以线程ID为头信息的链表上,堆内存释放时根据ptr从对应的链表上移除相应的堆内存块信息;同时计算出当前线程所持有的堆内存总的使用量,并更新当前进程的堆内存使用量和堆内存使用峰值。 +用户态线程堆内存使用统计具有一定的实际意义,统计线程申请的堆内存占比,为用户程序的内存使用优化提供数据支持。用户态堆内存统计模块主要涉及的接口为malloc和free。如上图所示,每个进程维护128个链表,链表索引即线程ID,申请内存时系统将ptr和size信息记录在内存节点控制块中并将节点控制块挂在以线程ID为头信息的链表上,堆内存释放时根据ptr从对应的链表上移除相应的堆内存块信息;同时计算出当前线程所持有的堆内存总的使用量,并更新当前进程的堆内存使用量和堆内存使用峰值。 ## 内存完整性检查 @@ -40,16 +40,19 @@ - 使用malloc申请内存(小于等于0x1c000bytes时通过堆分配算法分配) 用户程序申请堆内存时,在堆内存节点处添加校验值等信息,如果校验值异常,则很有可能是前一块堆内存使用越界导致的(目前无法识别校验值被野指针破坏的场景)。在内存申请、释放时校验内存节点校验值的正确性,若内存节点被破坏,校验失败时则输出tid、pid及当前被踩节点前一块堆内存申请时保存的调用栈信息,通过addr2line工具可获得具体的代码行信息,辅助用户解决问题。 - **图4** node节点头信息添加校验值 - ![zh-cn_image_0000001211449151](figures/zh-cn_image_0000001211449151.png) + **图4** node节点头信息添加校验值 + + ![zh-cn_image_0000001211449151](figures/zh-cn_image_0000001211449151.png) free堆内存时,不会立即把该内存块释放掉,而是在内存中写入魔术数字0xFE,并放到free队列中(保证在一定时间内不会再被malloc函数分配),当有野指针或use-after-free的情况对该内存进行读取的操作时,能够发现数据异常,但是对于写操作则无法判断出来。 - **图5** free流程图 - ![zh-cn_image_0000001165890904](figures/zh-cn_image_0000001165890904.png) + **图5** free流程图 + + ![zh-cn_image_0000001165890904](figures/zh-cn_image_0000001165890904.png) - 使用malloc申请内存(大于0x1c000bytes时通过mmap申请) 当malloc通过mmap申请大块内存时,在返回给用户使用的内存区间头和尾分别多申请一个页,一个页PAGE_SIZE当前为0x1000,这两个页分别通过mprotect接口设置权限为PROT_NONE(无可读可写权限),可以有效防止内存越界读写问题:越界读写数据时由于无读写权限而导致用户程序异常,根据异常调用栈信息可找到相应的代码逻辑。 - **图6** malloc通过mmap机制申请内存的内存布局 - ![zh-cn_image_0000001211130993](figures/zh-cn_image_0000001211130993.png) + **图6** malloc通过mmap机制申请内存的内存布局 + + ![zh-cn_image_0000001211130993](figures/zh-cn_image_0000001211130993.png) diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md index 8b1e87c4083c79a02d9e2dc25883ddd4723197b4..bc58fd98e7ce3edd11fca333ae681151b0c224a8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-api.md @@ -1,13 +1,23 @@ # 接口说明 -**表1** 内存调测模块接口 - -| 功能分类 | 接口名 | 描述 | -| -------- | -------- | -------- | -| 内存调测功能 | mem_check_init | 初始化内存检测模块。 | -| | watch_mem |获取线程级堆内存使用信息。| -| | check_leak |检查是否有堆内存泄漏。| -| | check_heap_integrity |检查堆内存的完整性。| -| 调用栈回溯功能 | backtrace | 获取调用栈地址信息。 | -| | backtrace_symbols |根据地址信息获取符号信息。| -| | print_trace |输出函数调用栈信息。| + + **表1** 内存调测功能 + +| 接口名 | 描述 | +| -------- | -------- | +| mem_check_init | 初始化内存检测模块。 | +| watch_mem | 获取线程级堆内存使用信息。 | +| check_leak | 检查是否有堆内存泄漏。 | +| check_heap_integrity | 检查堆内存的完整性。 | +| backtrace | 获取调用栈地址信息。 | +| backtrace_symbols | 根据地址信息获取符号信息。 | +| print_trace | 输出函数调用栈信息。 | + + + **表2** 调用栈回溯功能 + +| 接口名 | 描述 | +| -------- | -------- | +| backtrace | 获取调用栈地址信息。 | +| backtrace_symbols | 根据地址信息获取符号信息。 | +| print_trace | 输出函数调用栈信息。 | diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md index d09659aa3f9e116f2514ee56b09d0b9f39f2e56e..0bc9bd0d64149f4d68b7ff779c66ffeeccde9f59 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-api.md @@ -1,14 +1,11 @@ # 接口调用方式 -- [示例代码](#示例代码) -- [编译](#编译) -- [调测信息](#调测信息) -- [调用栈解析](#调用栈解析) ## 示例代码 代码功能:显式调用调测模块的相关接口对用户代码进行内存校验。 + ``` #include #include @@ -40,6 +37,7 @@ int main() ## 编译 + ``` $ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos --sysroot=/home//directory/out/hispark_taurus/ipcamera_hispark_taurus/sysroot $(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a) ``` @@ -61,6 +59,7 @@ $ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp ## 调测信息 + ``` OHOS # ./mem_check OHOS # @@ -115,12 +114,14 @@ Check heap integrity ok! 提供parse_mem_info.sh脚本可以对调用栈进行解析,解析脚本存放的路径:kernel/liteos_a/tools/scripts/parse_memory/parse_mem_info.sh。利用脚本可以将相应的调测信息转换成具体的源码行号,如下命令所示,mem_debug.txt保存的是内存调测信息,elf1、elf2等文件是需要解析的elf文件。 + ``` $ ./parse_mem_info.sh mem_debug.txt elf1 elf2 elf3 ... ``` 例如: + ``` $ ./parse_mem_info.sh mem_debug.txt mem_check Compiler is [gcc/llvm]: llvm diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md index 8c3ef15472688c9f2cf74b3c6bef1f54b9de4f17..de589cc837ad7c71a38a3d15c34b6c617673b090 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use-cli.md @@ -1,14 +1,8 @@ # 命令行参数方式 -- [示例代码](#示例代码) -- [编译](#编译) -- [使用mwatch参数命令](#使用mwatch参数命令) -- [调用栈解析](#调用栈解析) -- [使用mrecord参数命令](#使用mrecord参数命令) 对用户态进程进行内存相关的检查时,除了接口调用方式还可以通过命令行方式进行内存统计、内存泄漏或内存完整性检查。 - ``` --mwatch:初始化内存调测功能,注册信号。内存调测信息将从串口输出; --mrecord :初始化内存调测功能,注册信号。内存调测信息将保存至f_path文件,若f_path创建失败,则内存调测信息将从串口输出 @@ -17,7 +11,6 @@ 在待调测的进程未退出时可使用信号机制获取对应信息: - ``` kill -35 # 查看线程级堆内存占用 kill -36 # 检查是否存在堆内存泄漏 @@ -29,6 +22,7 @@ kill -37 # 检查堆内存头节点是否完整 代码功能:构造内存问题利用命令行方式进行内存调测。 + ``` #include #include @@ -58,6 +52,7 @@ int main() ## 使用mwatch参数命令 + ``` OHOS # ./mem_check --mwatch // 利用task命令可以查到mem_check进程的pid为4 OHOS # @@ -99,6 +94,7 @@ Check heap integrity ok! 将调测信息保存至test.txt文件中,利用脚本进行解析,获取内存泄漏的具体行号。 + ``` $ ./parse_mem_info.sh test.txt mem_check Compiler is [gcc/llvm]: llvm @@ -125,11 +121,13 @@ Now using addr2line ... ## 使用mrecord参数命令 1. 执行用户程序并指定记录内存调测信息的文件路径 + ``` OHOS # ./mem_check --mrecord /storage/check.txt ``` 2. 利用kill -35 <pid>统计内存信息,该信息将会输出到文件中,使用cat命令查看 + ``` OHOS # kill -35 4 OHOS # Memory statistics information saved in /storage/pid(4)_check.txt @@ -146,6 +144,7 @@ Now using addr2line ... ``` 3. 利用kill -36 <pid>校验内存完整性,该信息将会输出到文件中,使用cat命令查看 + ``` OHOS # kill -36 4 OHOS # Leak check information saved in /storage/pid(4)_check.txt @@ -178,6 +177,7 @@ Now using addr2line ... ``` 4. 利用kill -9 <pid>杀掉当前进程,进程退出后会默认校验内存完整性,该信息将会输出到文件中,使用cat命令查看 + ``` OHOS # kill -9 4 OHOS # Leak check information saved in /storage/pid(4)_check.txt diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md index b479e7a9c3ed6867f2e0c0d78512258727710972..86e48d4ebe489fac44953b4c75495c9c8ff8ef59 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide-use.md @@ -1,5 +1,6 @@ # 使用说明 + 编译OpenHarmony工程时默认编译的是debug版本,即libc库已经集成内存调测相关的接口实现,用户可以根据具体需要决定是否使能内存调测功能。 @@ -17,5 +18,4 @@ - **[接口调用方式](kernel-small-debug-user-guide-use-api.md)** -- **[命令行参数方式](kernel-small-debug-user-guide-use-cli.md)** - +- **[命令行参数方式](kernel-small-debug-user-guide-use-cli.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md index 2a0508628a7d164896638baf2bb3e4e680e33d76..6c62a148e4a583daec0b97e7433f2755a760e5ed 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user-guide.md @@ -1,6 +1,7 @@ # 使用指导 + - **[接口说明](kernel-small-debug-user-guide-api.md)** - **[使用说明](kernel-small-debug-user-guide-use.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-user.md b/zh-cn/device-dev/kernel/kernel-small-debug-user.md index 00f600d1e78d2573e6f1cba54e3c74178e5dc54d..3a57c7c48ce1b8719a750f8b53bf2a01351b8e4f 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user.md @@ -1,10 +1,11 @@ # 用户态内存调测 + - **[基本概念](kernel-small-debug-user-concept.md)** - **[运行机制](kernel-small-debug-user-function.md)** - **[使用指导](kernel-small-debug-user-guide.md)** -- **[常见问题场景](kernel-small-debug-user-faqs.md)** \ No newline at end of file +- **[常见问题](kernel-small-debug-user-faqs.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small-debug.md b/zh-cn/device-dev/kernel/kernel-small-debug.md index 6b615e508e446106590972d8a38c5655f5a38056..e5d8a687e0accc11a23b19636c7cc1b4419ae196 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug.md @@ -1,15 +1,16 @@ # 调测与工具 + - **[Shell](kernel-small-debug-shell.md)** -- **[Trace](kernel-small-debug-trace.md)** +- **[Trace调测](kernel-small-debug-trace.md)** - **[Perf调测](kernel-mini-memory-perf.md)** - **[LMS调测](kernel-small-memory-lms.md)** -- **[进程调测](kernel-small-debug-process.md)** +- **[进程调测](kernel-small-debug-process-cpu.md)** - **[内核态内存调测](kernel-small-debug-memory.md)** diff --git a/zh-cn/device-dev/kernel/kernel-small-memory-lms.md b/zh-cn/device-dev/kernel/kernel-small-memory-lms.md index 63f4e9c69d09d963e50fd1ac52b7f5240dd50a3f..fb15928ce166c78e1083fbc0a4f1a98a0e96a213 100644 --- a/zh-cn/device-dev/kernel/kernel-small-memory-lms.md +++ b/zh-cn/device-dev/kernel/kernel-small-memory-lms.md @@ -1,19 +1,5 @@ # LMS调测 -- [基本概念](#基本概念) -- [运行机制](#运行机制) -- [接口说明](#接口说明) - - [内核态](#内核态) - - [用户态](#用户态) -- [开发指导](#开发指导) - - [内核态开发流程](#内核态开发流程) -- [内核态编程实例](#内核态编程实例) -- [内核态示例代码](#内核态示例代码) - - [内核态结果验证](#内核态结果验证) - - [用户态开发流程](#用户态开发流程) - - [用户态编程实例](#用户态编程实例) - - [用户态示例代码](#用户态示例代码) - - [用户态结果验证](#用户态结果验证) ## 基本概念 @@ -50,7 +36,7 @@ LMS使用影子内存映射标记系统内存的状态,一共可标记为三 OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_lms.h)参考。 -**表1** LMS模块接口说明 + **表1** LMS模块接口说明 | 功能分类 | 接口名 | 描述 | | -------- | -------- | -------- | @@ -75,7 +61,7 @@ OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信 1. 配置LMS模块相关宏。 配置LMS控制宏LOSCFG_KERNEL_LMS,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Lite Memory Sanitizer"中打开YES: - | 宏 | menuconfig选项 | 含义 | 取值 | + | 宏 | menuconfig选项 | 含义 | 取值 | | -------- | -------- | -------- | -------- | | LOSCFG_KERNEL_LMS | Enable Lms Feature | Lms模块的裁剪开关 | YES/NO | | LOSCFG_LMS_MAX_RECORD_POOL_NUM | Lms check pool max num | LMS支持的检测内存池最大个数 | INT | @@ -86,7 +72,8 @@ OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信 2. 在被检测模块的编译脚本中,修改编译选项。 增加LMS检测编译选项-fsanitize=kernel-address。为避免编译器优化,增加-O0编译选项。 - gcc与clang编译选项存在差异,参照如下示例: + gcc与clang编译选项存在差异,参照如下示例: + ``` if ("$ohos_build_compiler_specified" == "gcc") { cflags_c = [ @@ -123,7 +110,8 @@ OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信 ## 内核态示例代码 -实例代码如下: + 实例代码如下: + ``` #define PAGE_SIZE (0x1000U) #define INDEX_MAX 20 @@ -183,7 +171,8 @@ LOS_MODULE_INIT(Example_Lms_test, LOS_INIT_LEVEL_KMOD_EXTENDED); ### 内核态结果验证 -输出结果如下: + 输出结果如下: + ``` ######LmsTestOsmallocOverflow start ###### [ERR][KProcess:LmsTestCaseTask]* Kernel Address Sanitizer Error Detected Start * @@ -270,6 +259,7 @@ str[ 0]=0x 0 在待检测的app编译脚本中,添加如下参数即可, 完整示例可参见/kernel/liteos_a/apps/lms/BUILD.gn。 + ``` if ("$ohos_build_compiler_specified" == "gcc") { cflags_c = [ @@ -323,7 +313,8 @@ if ("$ohos_build_compiler_specified" == "gcc") { ### 用户态示例代码 -实例代码如下: + 实例代码如下: + ``` static void BufWriteTest(void *buf, int start, int end) { @@ -368,7 +359,8 @@ int main(int argc, char * const * argv) ### 用户态结果验证 -输出结果如下: + 输出结果如下: + ``` * Lite Memory Sanitizer Error Detected * Heap buffer overflow error detected! diff --git a/zh-cn/device-dev/kernel/kernel-small-overview.md b/zh-cn/device-dev/kernel/kernel-small-overview.md index 9071dd20c8357d694da0f9a68662d9f44390d963..ad6dafc5098134d4b2bd902b6b33d3629a786aef 100644 --- a/zh-cn/device-dev/kernel/kernel-small-overview.md +++ b/zh-cn/device-dev/kernel/kernel-small-overview.md @@ -1,11 +1,9 @@ # 内核概述 -- [简介](#简介) -- [内核架构](#内核架构) ## 简介 -OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawei LiteOS内核演进发展的新一代内核,包含LiteOS-M和LiteOS-A两类内核。LiteOS-M内核主要应用于轻量系统,面向的MCU一般是百K级内存,可支持MPU隔离,业界类似的内核有FreeRTOS或ThreadX等;LiteOS-A内核主要应用于小型系统,面向设备一般是M级内存,可支持MMU隔离,业界类似的内核有Zircon或Darwin等。 +OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawei LiteOS内核演进发展的新一代内核,包含LiteOS-M和LiteOS-A两类内核。LiteOS-M内核主要应用于轻量系统,面向的MCU(Micro Processor Unit)一般是百K级内存,可支持MPU(Memory Protection Unit)隔离,业界类似的内核有FreeRTOS或ThreadX等;LiteOS-A内核主要应用于小型系统,面向设备一般是M级内存,可支持MMU(Memory Management Unit)隔离,业界类似的内核有Zircon或Darwin等。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > OpenHarmony针对不同量级的系统,分别使用了不同形态的内核,小型系统支持LiteOS和Linux,本开发指南适用于LiteOS-A内核,linux内核的相关操作请参考[Linux内核概述](../kernel/kernel-standard-overview.md)。 @@ -29,8 +27,8 @@ OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawe 轻量级内核主要由基础内核、扩展组件、HDF框架、POSIX接口组成。轻量级内核的文件系统、网络协议等扩展功能(没有像微内核那样运行在用户态)运行在内核地址空间,主要考虑组件之间直接函数调用比进程间通信或远程过程调用要快得多。 -**图1** OpenHarmony LiteOS-A内核架构图 -![zh-cn_image_0000001160018656](figures/zh-cn_image_0000001160018656.png) + **图1** OpenHarmony LiteOS-A内核架构图 + ![zh-cn_image_0000001160018656](figures/zh-cn_image_0000001160018656.png) - 基础内核主要包括内核的基础机制,如调度、内存管理、中断异常等 diff --git a/zh-cn/device-dev/kernel/kernel-small-start-kernel.md b/zh-cn/device-dev/kernel/kernel-small-start-kernel.md index e8c305fcc3fe764a16b6e812c7c199037c28b376..75dab22026d9a5b1eae5aad50dd453e68e1069bf 100644 --- a/zh-cn/device-dev/kernel/kernel-small-start-kernel.md +++ b/zh-cn/device-dev/kernel/kernel-small-start-kernel.md @@ -1,25 +1,22 @@ # 内核态启动 -- [内核启动流程](#内核启动流程) -- [编程样例](#编程样例) - - [实例描述](#实例描述) ## 内核启动流程 内核启动流程包含汇编启动阶段和C语言启动阶段2部分,如图1所示。汇编启动阶段完成CPU初始设置,关闭dcache/icache,使能FPU及neon,设置MMU建立虚实地址映射,设置系统栈,清理bss段,调用C语言main函数等。C语言启动阶段包含OsMain函数及开始调度等,其中如上图所示,OsMain函数用于内核基础初始化和架构、板级初始化等,其整体由内核启动框架主导初始化流程,图中右边区域为启动框架中可接受外部模块注册启动的阶段,各个阶段的说明如下表1所示。 -**图1** 内核启动流程图 -![zh-cn_image_0000001153832492](figures/zh-cn_image_0000001153832492.png) + **图1** 内核启动流程图 + ![zh-cn_image_0000001153832492](figures/zh-cn_image_0000001153832492.png) -**表1** 启动框架层级 + **表1** 启动框架层级 | 层级 | 说明 | | -------- | -------- | | LOS_INIT_LEVEL_EARLIEST | 最早期初始化
说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化
例如:Trace模块 | | LOS_INIT_LEVEL_ARCH_EARLY | 架构早期初始化
说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层 | -| LOS_INIT_LEVEL_PLATFORM_EARLY | 平台早期初始化
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层 | +| LOS_INIT_LEVEL_PLATFORM_EARLY | 平台早期初始化
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层
例如:uart模块 | | LOS_INIT_LEVEL_KMOD_PREVM | 内存初始化前的内核模块初始化
说明:在内存初始化之前需要使能的模块初始化 | | LOS_INIT_LEVEL_VM_COMPLETE | 基础内存就绪后的初始化
说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化
例如:共享内存功能 | | LOS_INIT_LEVEL_ARCH | 架构后期初始化
说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化 | @@ -40,6 +37,7 @@ **示例代码** + ``` /* 内核启动框架头文件 */ #include "los_init.h" @@ -60,6 +58,7 @@ LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED); **结果验证** + ``` main core booting up... OsSampleModInit SUCCESS! diff --git a/zh-cn/device-dev/kernel/kernel-small-start-user.md b/zh-cn/device-dev/kernel/kernel-small-start-user.md index 589d0266666f4f97df1f93c30459c649e982b708..e2841141228838c2b5df130c7fde078db8cf5fe7 100644 --- a/zh-cn/device-dev/kernel/kernel-small-start-user.md +++ b/zh-cn/device-dev/kernel/kernel-small-start-user.md @@ -1,22 +1,20 @@ # 用户态启动 -- [用户态根进程启动](#用户态根进程启动) - - [根进程的启动过程](#根进程的启动过程) - - [根进程的职责](#根进程的职责) -- [用户态程序运行](#用户态程序运行) ## 用户态根进程启动 根进程是系统第一个用户态进程,进程ID为1,它是所有用户态进程的祖先。 -**图1** 进程树示意图 -![zh-cn_image_0000001178108019](figures/zh-cn_image_0000001178108019.png) + **图1** 进程树示意图 + + ![zh-cn_image_0000001178108019](figures/zh-cn_image_0000001178108019.png) ### 根进程的启动过程 使用链接脚本将如下init启动代码放置到系统镜像指定位置。 + ``` #define LITE_USER_SEC_ENTRY __attribute__((section(".user.entry"))) LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args) @@ -40,30 +38,17 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args) - 启动关键系统程序或服务,如交互进程shell。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > 在OpenHarmony 中**init**进程通过读取/etc/init.cfg,根据配置执行指定命令,或启动指定进程(详见:[init启动引导](../subsystems/subsys-boot.md) 。 + > 在OpenHarmony 中**init**进程通过读取/etc/init.cfg,根据配置执行指定命令,或启动指定进程(详见:[init启动引导](../subsystems/subsys-boot-init.md))。 - 监控回收孤儿进程,清理子进程中的僵尸进程。 -## 用户态程序运行 - -用户态程序常见编译方式有如下两种: -1. [利用框架编译用户态进程](../quick-start/quickstart-standard-running-rk3568-create.md)。 - -2. 手动编译 - 实例: - ``` - clang --target=arm-liteos --sysroot=prebuilts/lite/sysroot -o helloworld helloworld.c - ``` - **clang**:参考[LLVM安装指导](../quick-start/quickstart-lite-package-environment.md#安装llvm-仅openharmony_v1-x分支-标签需要-)安装LLVM编译器。 - - **--target**:--target=arm-liteos,指定编译平台为arm-liteos。 - - **--sysroot**:--sysroot=${YOUR_ROOT_PATH}/prebuilts/lite/sysroot,指定头文件以及依赖标准库搜索路径为prebuilts下的指定路径。 +## 用户态程序运行 用户态程序启动有如下常见方式: - shell命令启动进程。 + ``` OHOS $ exec helloworld OHOS $ ./helloworld diff --git a/zh-cn/device-dev/kernel/kernel-small-start.md b/zh-cn/device-dev/kernel/kernel-small-start.md index 486973ced437611eb3048b616f86a561c5dc6785..8acf2bb99a688b90a2f3fa3fcfaed0b323fecb7e 100644 --- a/zh-cn/device-dev/kernel/kernel-small-start.md +++ b/zh-cn/device-dev/kernel/kernel-small-start.md @@ -1,6 +1,7 @@ # 内核启动 + - **[内核态启动](kernel-small-start-kernel.md)** - **[用户态启动](kernel-small-start-user.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/kernel/kernel-small.md b/zh-cn/device-dev/kernel/kernel-small.md index de47769b00db431ec5b3e712b974ec94666ec781..9b0159ad8345f368556842f9c265440d26042e9f 100644 --- a/zh-cn/device-dev/kernel/kernel-small.md +++ b/zh-cn/device-dev/kernel/kernel-small.md @@ -1,6 +1,7 @@ # 小型系统内核 + - **[内核概述](kernel-small-overview.md)** - **[内核启动](kernel-small-start.md)** diff --git a/zh-cn/device-dev/kernel/kernel.md b/zh-cn/device-dev/kernel/kernel.md index 17047169bf665c342af42e11b3350eb948322a56..33c66bfd5d195fd2603cb920ccdee61bdeb10e54 100644 --- a/zh-cn/device-dev/kernel/kernel.md +++ b/zh-cn/device-dev/kernel/kernel.md @@ -1,6 +1,7 @@ # 内核 + - **[轻量系统内核](kernel-mini.md)** - **[小型系统内核](kernel-small.md)** diff --git a/zh-cn/device-dev/porting/Readme-CN.md b/zh-cn/device-dev/porting/Readme-CN.md index 014cfa66bcf060783e552542de6a7f9f859dee8b..ba79eb73d85afc2e935dc637fb1bcc1b2a7426c4 100755 --- a/zh-cn/device-dev/porting/Readme-CN.md +++ b/zh-cn/device-dev/porting/Readme-CN.md @@ -21,15 +21,15 @@ repo init -u https://gitee.com/openharmony-sig/manifest.git -b master -m devboar ## 芯片移植指导 -- [轻量系统芯片移植指导](porting-minichip.md) - - [移植准备](porting-chip-prepare.md) - - [移植须知](oem_transplant_chip_prepare_knows.md) +- 轻量系统芯片移植指导 + - 移植准备 + - [移植须知](porting-chip-prepare-knows.md) - [编译构建适配流程](porting-chip-prepare-process.md) - - [内核移植](porting-chip-kernel.md) + - 内核移植 - [移植概述](porting-chip-kernel-overview.md) - [内核基础适配](porting-chip-kernel-adjustment.md) - [内核移植验证](porting-chip-kernel-verify.md) - - [板级系统移植](porting-chip-board.md) + - 板级系统移植 - [移植概述](porting-chip-board-overview.md) - [板级驱动适配](porting-chip-board-driver.md) - [HAL层实现](porting-chip-board-hal.md) @@ -38,27 +38,26 @@ repo init -u https://gitee.com/openharmony-sig/manifest.git -b master -m devboar - [三方组件适配](porting-chip-board-bundle.md) - [XTS认证](porting-chip-board-xts.md) - [常见问题](porting-chip-faqs.md) -- [小型系统芯片移植指导](porting-smallchip.md) - - [移植准备](porting-smallchip-prepare.md) +- 小型系统芯片移植指导 + - 移植准备 - [移植须知](porting-smallchip-prepare-needs.md) - [编译构建](porting-smallchip-prepare-building.md) - - [移植内核](porting-smallchip-kernel.md) + - 移植内核 - [LiteOS-A内核](porting-smallchip-kernel-a.md) - [Linux内核](porting-smallchip-kernel-linux.md) - - [驱动移植](porting-smallchip-driver.md) + - 驱动移植 - [移植概述](porting-smallchip-driver-overview.md) - [平台驱动移植](porting-smallchip-driver-plat.md) - [器件驱动移植](porting-smallchip-driver-oom.md) -- [标准系统芯片移植指导](standard-system-porting-guide.md) - - [标准系统移植指南](standard-system-porting-guide.md) - - [一种快速移植OpenHarmony Linux内核的方法](porting-linux-kernel.md) -- [轻量和小型系统三方库移植指导](porting-thirdparty.md) - - [概述](porting-thirdparty-overview.md) - - [CMake方式组织编译的库移植](porting-thirdparty-cmake.md) - - [Makefile方式组织编译的库移植](porting-thirdparty-makefile.md) +- 标准系统芯片移植指导 + - [标准系统移植指南](standard-system-porting-guide.md) + - [一种快速移植OpenHarmony Linux内核的方法](porting-linux-kernel.md) +- 轻量和小型系统三方库移植指导 + - [概述](porting-thirdparty-overview.md) + - [CMake方式组织编译的库移植](porting-thirdparty-cmake.md) + - [Makefile方式组织编译的库移植](porting-thirdparty-makefile.md) ## 芯片移植案例 -- [轻量系统芯片移植案例](porting-minichip-cases.md) - - [带屏解决方案之恒玄芯片移植案例](porting-bes2600w-on-minisystem-display-demo.md) +- [带屏解决方案之恒玄芯片移植案例](porting-bes2600w-on-minisystem-display-demo.md) diff --git a/zh-cn/device-dev/porting/figure/HDF_WIFI.png b/zh-cn/device-dev/porting/figures/HDF_WIFI.png similarity index 100% rename from zh-cn/device-dev/porting/figure/HDF_WIFI.png rename to zh-cn/device-dev/porting/figures/HDF_WIFI.png diff --git "a/zh-cn/device-dev/porting/figure/OpenHarmony-\351\251\261\345\212\250\345\210\206\347\261\273.png" "b/zh-cn/device-dev/porting/figures/OpenHarmony-\351\251\261\345\212\250\345\210\206\347\261\273.png" similarity index 100% rename from "zh-cn/device-dev/porting/figure/OpenHarmony-\351\251\261\345\212\250\345\210\206\347\261\273.png" rename to "zh-cn/device-dev/porting/figures/OpenHarmony-\351\251\261\345\212\250\345\210\206\347\261\273.png" diff --git "a/zh-cn/device-dev/porting/figure/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" "b/zh-cn/device-dev/porting/figures/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figure/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" rename to "zh-cn/device-dev/porting/figures/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" diff --git "a/zh-cn/device-dev/porting/figure/WLAN\350\212\257\347\211\207.png" "b/zh-cn/device-dev/porting/figures/WLAN\350\212\257\347\211\207.png" similarity index 100% rename from "zh-cn/device-dev/porting/figure/WLAN\350\212\257\347\211\207.png" rename to "zh-cn/device-dev/porting/figures/WLAN\350\212\257\347\211\207.png" diff --git a/zh-cn/device-dev/porting/figure/bes2600_board_make_menuconfig.png b/zh-cn/device-dev/porting/figures/bes2600_board_make_menuconfig.png similarity index 100% rename from zh-cn/device-dev/porting/figure/bes2600_board_make_menuconfig.png rename to zh-cn/device-dev/porting/figures/bes2600_board_make_menuconfig.png diff --git a/zh-cn/device-dev/porting/figure/bes2600_hb_env.png b/zh-cn/device-dev/porting/figures/bes2600_hb_env.png similarity index 100% rename from zh-cn/device-dev/porting/figure/bes2600_hb_env.png rename to zh-cn/device-dev/porting/figures/bes2600_hb_env.png diff --git a/zh-cn/device-dev/porting/figure/bes2600_hb_set.png b/zh-cn/device-dev/porting/figures/bes2600_hb_set.png similarity index 100% rename from zh-cn/device-dev/porting/figure/bes2600_hb_set.png rename to zh-cn/device-dev/porting/figures/bes2600_hb_set.png diff --git a/zh-cn/device-dev/porting/figure/bes2600_newlib_make_menuconfig.png b/zh-cn/device-dev/porting/figures/bes2600_newlib_make_menuconfig.png similarity index 100% rename from zh-cn/device-dev/porting/figure/bes2600_newlib_make_menuconfig.png rename to zh-cn/device-dev/porting/figures/bes2600_newlib_make_menuconfig.png diff --git "a/zh-cn/device-dev/porting/figure/init\345\220\257\345\212\250\346\255\243\345\270\270\346\227\245\345\277\227.png" "b/zh-cn/device-dev/porting/figures/init\345\220\257\345\212\250\346\255\243\345\270\270\346\227\245\345\277\227.png" similarity index 100% rename from "zh-cn/device-dev/porting/figure/init\345\220\257\345\212\250\346\255\243\345\270\270\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/porting/figures/init\345\220\257\345\212\250\346\255\243\345\270\270\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/porting/figure/liteos-m\345\206\205\346\240\270\346\250\241\345\235\227\345\233\276.png" "b/zh-cn/device-dev/porting/figures/liteos-m\345\206\205\346\240\270\346\250\241\345\235\227\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figure/liteos-m\345\206\205\346\240\270\346\250\241\345\235\227\345\233\276.png" rename to "zh-cn/device-dev/porting/figures/liteos-m\345\206\205\346\240\270\346\250\241\345\235\227\345\233\276.png" diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001154212516.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001154212516.png new file mode 100644 index 0000000000000000000000000000000000000000..a1e7f8b695bebf395ea6cfa0aed55495c4896118 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001154212516.png differ diff --git "a/zh-cn/device-dev/porting/figure/\346\225\264\344\275\223\345\220\257\345\212\250\346\265\201\347\250\213.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001154212518.png similarity index 100% rename from "zh-cn/device-dev/porting/figure/\346\225\264\344\275\223\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001154212518.png diff --git "a/zh-cn/device-dev/porting/figure/\345\237\272\344\272\216linux\345\206\205\346\240\270\347\232\204OS\351\225\234\345\203\217\347\273\223\346\236\204\345\222\214\347\224\250\346\210\267\346\200\201\347\250\213\345\272\217\345\220\257\345\212\250\346\265\201\347\250\213.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001154372318.png similarity index 100% rename from "zh-cn/device-dev/porting/figure/\345\237\272\344\272\216linux\345\206\205\346\240\270\347\232\204OS\351\225\234\345\203\217\347\273\223\346\236\204\345\222\214\347\224\250\346\210\267\346\200\201\347\250\213\345\272\217\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001154372318.png diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001162805936.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001162805936.png similarity index 100% rename from zh-cn/device-dev/porting/figure/zh-cn_image_0000001162805936.png rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001162805936.png diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001167753296.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001167753296.png new file mode 100644 index 0000000000000000000000000000000000000000..0546e82fc91c605ba78f9bb56c4de88066c8c189 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001167753296.png differ diff --git "a/zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001173764984.jpg similarity index 100% rename from "zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001173764984.jpg diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001188241031.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001188241031.png new file mode 100644 index 0000000000000000000000000000000000000000..c325922a5ee67edb81aa526de1547716fae1a04b Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001188241031.png differ diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199722629.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199722629.png new file mode 100644 index 0000000000000000000000000000000000000000..2cd5f7a4c095429f8e447b17562b37051343c689 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199722629.png differ diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199805369.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199805369.png new file mode 100644 index 0000000000000000000000000000000000000000..0484bc5af11f96948ec3344deda0ba62efe11264 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199805369.png differ diff --git "a/zh-cn/device-dev/porting/figure/\345\220\257\345\212\250\346\265\201\347\250\213.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001199842521.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figure/\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001199842521.png diff --git "a/zh-cn/device-dev/porting/figure/\346\255\243\345\270\270\350\277\233\345\205\245shell\345\220\216\350\276\223\345\205\245ls\345\221\275\344\273\244\344\270\262\345\217\243\346\211\223\345\215\260.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001200171991.png similarity index 100% rename from "zh-cn/device-dev/porting/figure/\346\255\243\345\270\270\350\277\233\345\205\245shell\345\220\216\350\276\223\345\205\245ls\345\221\275\344\273\244\344\270\262\345\217\243\346\211\223\345\215\260.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001200171991.png diff --git "a/zh-cn/device-dev/porting/figure/\344\270\232\345\212\241\345\220\257\345\212\250\346\265\201\347\250\213.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001200252103.png similarity index 100% rename from "zh-cn/device-dev/porting/figure/\344\270\232\345\212\241\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001200252103.png diff --git "a/zh-cn/device-dev/porting/figure/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001200336823.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figure/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001200336823.png diff --git "a/zh-cn/device-dev/porting/figure/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001200417969.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figure/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001200417969.png diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001207599659.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001207599659.png new file mode 100644 index 0000000000000000000000000000000000000000..7edac54ec2fcd1fc93330d47acb2d44fceef2710 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001207599659.png differ diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001207756867.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001207756867.png new file mode 100644 index 0000000000000000000000000000000000000000..56e6ab3aee9a539c76afd3edac98f21bff0766d5 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001207756867.png differ diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001208365855.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001208365855.png similarity index 100% rename from zh-cn/device-dev/porting/figure/zh-cn_image_0000001208365855.png rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001208365855.png diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001208524821.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001208524821.png similarity index 100% rename from zh-cn/device-dev/porting/figure/zh-cn_image_0000001208524821.png rename to zh-cn/device-dev/porting/figures/zh-cn_image_0000001208524821.png diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001210623027.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001210623027.png new file mode 100644 index 0000000000000000000000000000000000000000..f510ddebebcfa243d67c0470a009eeb7c5e3c1aa Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001210623027.png differ diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001218806027.png b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001218806027.png new file mode 100644 index 0000000000000000000000000000000000000000..7d0b723345d413067e0142b2035205133c907ab0 Binary files /dev/null and b/zh-cn/device-dev/porting/figures/zh-cn_image_0000001218806027.png differ diff --git "a/zh-cn/device-dev/porting/figures/\344\270\232\345\212\241\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/porting/figures/\344\270\232\345\212\241\345\220\257\345\212\250\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..cbc70a899f77382e9e052c30f2a69b61764d2643 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\344\270\232\345\212\241\345\220\257\345\212\250\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" "b/zh-cn/device-dev/porting/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..dd8e1c235633c3e42fcd1360b66b3ce3452db02d Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" differ diff --git "a/zh-cn/device-dev/porting/figures/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" "b/zh-cn/device-dev/porting/figures/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..c886985b8cb0db42b71a693df78a1aac20b88ac2 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/porting/figures/\345\220\257\345\212\250\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..93f747cae385fb714334d5145103d6f7ddfacd95 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\345\220\257\345\212\250\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\345\237\272\344\272\216linux\345\206\205\346\240\270\347\232\204OS\351\225\234\345\203\217\347\273\223\346\236\204\345\222\214\347\224\250\346\210\267\346\200\201\347\250\213\345\272\217\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/porting/figures/\345\237\272\344\272\216linux\345\206\205\346\240\270\347\232\204OS\351\225\234\345\203\217\347\273\223\346\236\204\345\222\214\347\224\250\346\210\267\346\200\201\347\250\213\345\272\217\345\220\257\345\212\250\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..b241920b30fea1b2a432f6ba01045bbfbae7fb58 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\345\237\272\344\272\216linux\345\206\205\346\240\270\347\232\204OS\351\225\234\345\203\217\347\273\223\346\236\204\345\222\214\347\224\250\346\210\267\346\200\201\347\250\213\345\272\217\345\220\257\345\212\250\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\346\225\264\344\275\223\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/porting/figures/\346\225\264\344\275\223\345\220\257\345\212\250\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..39c6cb96611a7ced5e17bbeee96ac77ba5c1bf58 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\346\225\264\344\275\223\345\220\257\345\212\250\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\346\255\243\345\270\270\350\277\233\345\205\245shell\345\220\216\350\276\223\345\205\245ls\345\221\275\344\273\244\344\270\262\345\217\243\346\211\223\345\215\260.png" "b/zh-cn/device-dev/porting/figures/\346\255\243\345\270\270\350\277\233\345\205\245shell\345\220\216\350\276\223\345\205\245ls\345\221\275\344\273\244\344\270\262\345\217\243\346\211\223\345\215\260.png" new file mode 100644 index 0000000000000000000000000000000000000000..efb1e17b00d37b072a3032678144984e2e13b2d6 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\346\255\243\345\270\270\350\277\233\345\205\245shell\345\220\216\350\276\223\345\205\245ls\345\221\275\344\273\244\344\270\262\345\217\243\346\211\223\345\215\260.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" "b/zh-cn/device-dev/porting/figures/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" new file mode 100644 index 0000000000000000000000000000000000000000..3cbefc997a46c6175735c6e3b8b6e29ff03b05d4 Binary files /dev/null and "b/zh-cn/device-dev/porting/figures/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" differ diff --git a/zh-cn/device-dev/porting/oem_transplant_chip_prepare_knows.md b/zh-cn/device-dev/porting/oem_transplant_chip_prepare_knows.md deleted file mode 100644 index 188e23538673a6eb6e3888299a47874fc8d9ac1e..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/porting/oem_transplant_chip_prepare_knows.md +++ /dev/null @@ -1,84 +0,0 @@ -# 移植须知 - -- [移植目录](#section284217487490) -- [移植流程](#section639315306506) -- [移植规范](#section187870185219) - -本文为OpenHarmony平台系统开发人员和芯片(或模组)制造商提供基础的开发移植指导,典型的芯片架构例如cortex-m系列、risc-v系列等都可以按照本文进行移植,暂时不支持蓝牙服务。OpenHarmony是个持续演进的复杂项目,随着版本和API的改变,本文将会不断更新。 - -本文要求读者具有一定的嵌入式系统开发经验,因此它的重点未放在基本的OS基础介绍,而更多地描述OpenHarmony平台移植过程中主要操作和所需要关注的方面。 - -## 移植目录 - -OpenHarmony整体工程较为复杂,目录及实现为系统本身功能,如果不涉及复杂的特性增强,不需要关注每一层实现,移植过程中重点关注如下目录即可: - -**表 1** 移植过程中的重点目录 - - - - - - - - - - - - - - - - - - - -

目录名称

-

描述

-

/build/lite

-

OpenHarmony基础编译构建框架

-

/kernel/liteos_m

-

基础内核,其中芯片架构相关实现在arch目录下

-

/device

-

板级相关实现,各个三方厂商按照OpenHarmony规范适配实现,device下具体目录结构及移植过程参见板级系统移植

-

/vendor

-

产品级相关实现,主要由华为或者产品厂商贡献

-
- -device目录规则:device/\{芯片解决方案厂商\}/\{开发板\}。以hisilicon的hispark\_taurus为例: - -``` -device -└── hisilicon # 芯片解决方案厂商名 - ├── common # 芯片解决方案开发板公共部分 - └── hispark_taurus # 开发板名称 - ├── BUILD.gn # 开发板编译入口 - ├── hals # 芯片解决方案厂商OS硬件适配 - ├── linux # linux版本 - │ └── config.gni # linux版本编译工具链和编译选项配置 - └── liteos_a # liteos-a版本 - └── config.gni # liteos-a版本编译工具链和编译选项配置 -``` - -vendor目录规则:vendor/\{产品解决方案厂商\}/\{产品名称\}。以华为的wifiiot产品为例: - -``` -vendor # 产品解决方案厂商 -└── huawei # 产品解决方案厂商名称 - └── wifiiot # 产品名称 - ├── hals # 产品解决方案厂商OS适配 - ├── BUILD.gn # 产品编译脚本 - └── config.json # 产品配置文件 -``` - -## 移植流程 - -OpenHarmony的device目录是基础芯片的适配目录,如果在三方芯片应用过程中发现此目录下已经有完整的芯片适配,则不需要再额外移植,直接跳过移植过程进行系统应用开发即可,如果该目录下无对应的芯片移植实现,则根据本文完成移植过程。OpenHarmony三方芯片移植主要过程如下: - -**图 1** 芯片移植关键步骤 -![](figure/芯片移植关键步骤.png "芯片移植关键步骤") - -## 移植规范 - -- 满足OpenHarmony[开源贡献基本规范和准则](../../contribute/参与贡献.md)。 -- 三方芯片适配所需要贡献的代码主要在device、vendor和arch三个目录,参照[内核目录规范](porting-chip-kernel-overview.md)和[板级目录规范](porting-chip-board-overview.md#section6204129143013)满足基本目录命名和使用规范。 - diff --git a/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md b/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md index c804aa0e3964cf198664eaa59f9c484e94bd78d4..268ad01e67e9f992037e3e30f6bf4475c6844c2b 100644 --- a/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md +++ b/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md @@ -72,11 +72,11 @@ kernel_version = "3.0.0" --- 内核版本,跟config.json中kern 3. 验证`hb set`配置是否正确,输入`hb set`能够显示如下图片表示配置正确。 执行`hb set`输入项目根目录,并且回车,`hb`命令会遍历所有`//vendor//`目录下的`config.json`,给出可选产品编译选项,`config.json`的`product_name`用于显示产品名,`device_company`和`board`用于关联出`//device/board//`目录,并且匹配`/config.gni`文件,如果能够匹配多个文件,表示该单板适配了多个内核,那么可以根据`config.json`的`kernel_type`和`kernel_version`来唯一匹配`config.gni`的`kernel_type`和`kernel_version`,即可确定了需要编译适配了哪个内核的单板。 -![hb set](figure/bes2600_hb_set.png) +![hb set](figures/bes2600_hb_set.png) -​ 通过`hb env`可以查看选择出来的预编译环境变量。 + 通过`hb env`可以查看选择出来的预编译环境变量。 -![hb env](figure/bes2600_hb_env.png) +![hb env](figures/bes2600_hb_env.png) 在执行`hb build`之前,需要准备好`LiteOS-M`内核适配,具体适配步骤请参[内核移植](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md#%E5%86%85%E6%A0%B8%E7%A7%BB%E6%A4%8D)。 @@ -262,7 +262,7 @@ update_config menuconfig: 配置完成后,在 `kernel/liteos_m` 目录下执行 `make menuconfig`能够对`SoC Series`/`SoC`/`Board`进行选择,如下: -![board make menuconfig](figure/bes2600_board_make_menuconfig.png) +![board make menuconfig](figures/bes2600_board_make_menuconfig.png) 结果将自动保存在`$(PRODUCT_PATH)/kernel_configs/debug.config`,下次执行`make menuconfig`时会导出保存的结果。 @@ -431,7 +431,7 @@ static int32_t FsDriverInit(struct HdfDeviceObject *object) 在轻量系统中,C库适配比较复杂,设计思路请参考[LiteOS-M内核支持musl与newlib平滑切换方案](https://gitee.com/arvinzzz/ohos_kernel_design_specification/blob/master/liteos_m/%E6%94%AF%E6%8C%81newlib/%E5%86%85%E6%A0%B8%E9%80%82%E9%85%8Dnewlib%E6%96%B9%E6%A1%88%E6%80%9D%E8%B7%AF.md),由于我们的工具链采用 [gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2](https://gitee.com/link?target=https%3A%2F%2Fdeveloper.arm.com%2F-%2Fmedia%2FFiles%2Fdownloads%2Fgnu-rm%2F10.3-2021.10%2Fgcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2) 自带`newlib`的C库,那么系统移植整体采用`newlib`的C库。那么在内核的`make menuconfig`中选择`newlib`,如下图: -![image-20211212191013553](figure/bes2600_newlib_make_menuconfig.png) +![image-20211212191013553](figures/bes2600_newlib_make_menuconfig.png) #### malloc适配 @@ -1394,7 +1394,7 @@ APP_FEATURE_INIT(AppEntry); `aafwk_lite`相关的应用样例见`vendor/bestechnic/display_demo/tests/ability`目录,包含`launcher`和`js app`这两类应用,应用的函数调用流程描述如下: 1. `launcher`应用,通过`InstallLauncher`安装`BundleName`为 `"com.example.launcher"`的`native ui`应用,在`AbilityMgrSliteFeature`启动后会调用`AbilityMgrHandler::StartLauncher()`启动`launcher`应用。 - + 2. `StartJSApp`应用,通过`StartAbility`启动任意`Want`,通过将`want data`传递`JS_APP_PATH`, `SetWantData(&want, JS_APP_PATH, strlen(JS_APP_PATH) + 1)`。 @@ -1413,7 +1413,7 @@ APP_FEATURE_INIT(AppEntry); }, ``` -## 兼容性测评 +## 兼容性认证 ### 产品兼容性规范 @@ -1456,7 +1456,7 @@ APP_FEATURE_INIT(AppEntry); ### 报告提交 -将上图`XTS`用例的情况保存为测试报告,上传到`OpenHarmony`兼容性测试网站进行测评,作为`sig`仓库转正到`master`仓库的必要条件。详细步骤如下: +将上图`XTS`用例的情况保存为测试报告,上传到`OpenHarmony`兼容性测试网站进行认证,作为`sig`仓库转正到`master`仓库的必要条件。详细步骤如下: 步骤1:将`XTS`测试报告压缩成`zip`文件。 diff --git a/zh-cn/device-dev/porting/porting-chip-board-bundle.md b/zh-cn/device-dev/porting/porting-chip-board-bundle.md index d29e4480efa8927c6f4d797e3b0cbd8a2af05f9e..6c40374e471a03939674b66328c2b74c28dfa0ac 100644 --- a/zh-cn/device-dev/porting/porting-chip-board-bundle.md +++ b/zh-cn/device-dev/porting/porting-chip-board-bundle.md @@ -1,56 +1,54 @@ -# 三方组件适配 - -如果需要使用third\_party目录下与产品相关的三方组件,可能需要对三方组件进行适配,下面以比较常用的mbedtls为例,介绍下适配步骤,注意本小节中仅介绍如何将适配的代码与OpenHarmony的编译框架融合,不会详细介绍mbedtls本身的原理和适配代码的具体逻辑,这些内容请参考mbedtls官方网站上的适配指南。 - -1. 编写适配层代码 - - 根据mbedtls官网的适配指南,编写需要的适配层代码,以适配硬件随机数举例,下面的路径都是相对third\_party/mbedtls的路径: - - 1. 拷贝include/mbedtls/config.h到ports目录下,并修改打开MBEDTLS\_ENTROPY\_HARDWARE\_ALT开关。 - 2. 在ports目录下创建entropy\_poll\_alt.c文件include并实现entropy\_poll.h中的硬件随机数接口 - 3. 在BUILD.gn中的mbedtls\_sources中增加刚才适配的entropy\_poll\_alt.c的路径 - 4. 在BIULD.gn中的lite\_library\("mbedtls\_static"\)中增加一行MBEDTLS\_CONFIG\_FILE指定新配置文件的位置 - - ``` - lite_library("mbedtks_static") { - ... - defines += ["MBEDTLS_CONFIG_FILE=<../port/config.h>"] - ... - } - ``` - - 注意,上面的修改最好都新建一个config或者新建一个xxx\_alt.c文件来修改,不要直接在原先的代码中修改,侵入式的修改会导致后续版本升级出现大量零散冲突,增加升级维护成本。 - -2. 制作patch - - 由于上面的适配是硬件相关的,上库代码时,不能直接放到通用的third\_party/mbedtls目录中,因此需要将上面的修改制作成patch,在编译之前通过打patch的方式注入到代码中。 - - 1. 首先增加设备的patch配置文件device///patch.yml - 2. 编辑device///patch.yml,增加要打的patch的信息: - - ``` - # 需要打patch的路径,路径均为相对代码根目录的路径 - third_party/mbedtls: - # 该路径下需要打的patch存放路径 - - device///third_party/mbedtls/adapter.patch - third_party/wpa_supplicant: - # 当一个路径下有多个patch的时候会依次执行patch - - device///third_party/wpa_supplicant/xxxxx.patch - - device///third_party/wpa_supplicant/yyyyy.patch - ... - ``` - - 3. 制作上述**步骤1**修改的patch并放到对应的目录即可 - -3. 使用带patch的编译 - - 想要在编译的时候带上patch,其他步骤不变,仅需要在触发编译的时候加上 --patch,例如全编译的命令编程 - - ``` - hb build -f --patch - ``` - - >![](../public_sys-resources/icon-caution.gif) **注意:** - >最后一次打patch的产品信息会被记录,在进行下一次编译操作时,会对上一次的patch进行回退(即执行\`patch -p1 -R < xxx\`),回退patch失败或新增patch失败均会终止编译过程,请解决patch冲突后再次尝试编译。 - +# 三方组件适配 + + +如果需要使用third_party目录下与产品相关的三方组件,可能需要对三方组件进行适配,下面以比较常用的mbedtls为例,介绍下适配步骤,注意本小节中仅介绍如何将适配的代码与OpenHarmony的编译框架融合,不会详细介绍mbedtls本身的原理和适配代码的具体逻辑,这些内容请参考mbedtls官方网站上的适配指南。 + + +1. 编写适配层代码 + 根据mbedtls官网的适配指南,编写需要的适配层代码,以适配硬件随机数举例,下面的路径都是相对third_party/mbedtls的路径: + + 1. 拷贝include/mbedtls/config.h到ports目录下,并修改打开MBEDTLS_ENTROPY_HARDWARE_ALT开关。 + 2. 在ports目录下创建entropy_poll_alt.c文件include并实现entropy_poll.h中的硬件随机数接口 + 3. 在BUILD.gn中的mbedtls_sources中增加刚才适配的entropy_poll_alt.c的路径 + 4. 在BIULD.gn中的lite_library("mbedtls_static")中增加一行MBEDTLS_CONFIG_FILE指定新配置文件的位置 + + ``` + lite_library("mbedtks_static") { + ... + defines += ["MBEDTLS_CONFIG_FILE=<../port/config.h>"] + ... + } + ``` + + 注意,上面的修改最好都新建一个config或者新建一个xxx_alt.c文件来修改,不要直接在原先的代码中修改,侵入式的修改会导致后续版本升级出现大量零散冲突,增加升级维护成本。 + +2. 制作patch + 由于上面的适配是硬件相关的,上库代码时,不能直接放到通用的third_party/mbedtls目录中,因此需要将上面的修改制作成patch,在编译之前通过打patch的方式注入到代码中。 + + 1. 首先增加设备的patch配置文件device/<company>/<board>/patch.yml + 2. 编辑device/<company>/<board>/patch.yml,增加要打的patch的信息: + + ``` + # 需要打patch的路径,路径均为相对代码根目录的路径 + third_party/mbedtls: + # 该路径下需要打的patch存放路径 + - device///third_party/mbedtls/adapter.patch + third_party/wpa_supplicant: + # 当一个路径下有多个patch的时候会依次执行patch + - device///third_party/wpa_supplicant/xxxxx.patch + - device///third_party/wpa_supplicant/yyyyy.patch + ... + ``` + 3. 制作上述**步骤1**修改的patch并放到对应的目录即可 + +3. 使用带patch的编译 + 想要在编译的时候带上patch,其他步骤不变,仅需要在触发编译的时候加上 --patch,例如全编译的命令编程 + + + ``` + hb build -f --patch + ``` + + > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** + > 最后一次打patch的产品信息会被记录,在进行下一次编译操作时,会对上一次的patch进行回退(即执行`patch -p1 -R < xxx`),回退patch失败或新增patch失败均会终止编译过程,请解决patch冲突后再次尝试编译。 diff --git a/zh-cn/device-dev/porting/porting-chip-board-component.md b/zh-cn/device-dev/porting/porting-chip-board-component.md index 618fc8acfa8f796b8582551e5756c9b40d1eb934..555559cd0a9942496560fb9e811e236af7c82efb 100644 --- a/zh-cn/device-dev/porting/porting-chip-board-component.md +++ b/zh-cn/device-dev/porting/porting-chip-board-component.md @@ -1,26 +1,28 @@ -# 系统组件调用 +# 系统组件调用 -- [SAMGR](#section105874301910) -- [DFX](#section20064420420) 系统组件为上层应用提供基础能力,包括SAMGR(系统服务框架子系统)、DFX子系统等。在板级系统移植过程中,只需要选择使用即可,不用对其进行适配。 -## SAMGR + +## SAMGR **基本介绍** + 系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。 ->![](../public_sys-resources/icon-notice.gif) **须知:** ->本组件在板级系统移植中必须要使用,否则其他服务组件无法运行。 + +> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** +> 本组件在板级系统移植中必须要使用,否则其他服务组件无法运行。 + **SAMGR使用说明,请参考:[SAMGR 使用指导](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)** -## DFX + +## DFX **基本介绍** DFX子系统主要包含DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性,为开发者提供代码维测信息。 -**DFX子系统使用说明,请参考:[DFX子系统使用指导](../subsystems/subsys-dfx-overview.md)** - +**DFX子系统使用说明,请参考:[DFX子系统使用指导 ](../subsystems/subsys-dfx-overview.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-chip-board-driver.md b/zh-cn/device-dev/porting/porting-chip-board-driver.md index a4f06f80eca4958837f1c74fa52f399b4f983f71..17005fa27f55ec4a9fe179440c44d556925e1e1e 100755 --- a/zh-cn/device-dev/porting/porting-chip-board-driver.md +++ b/zh-cn/device-dev/porting/porting-chip-board-driver.md @@ -1,46 +1,48 @@ -# 板级驱动适配 +# 板级驱动适配 -板级驱动适配的主要步骤如下: - -1. SDK基于OpenHarmony提供的CMSIS/POSIX适配依赖OS的接口。 - 板级SDK适配OS接口存在两种选择:CMSIS、POSIX,当前liteos\_m已经适配CMSIS大部分接口(覆盖:基础内核管理、线程管理、定时器、事件、互斥锁、信号量、队列等),基本可以满足直接移植,POSIX接口当前具备初步的移植能力,接口正在补全中;如果SDK原本基于CMSIS或者POSIX接口实现,理论上可以直接适配到liteos\_m中; +板级驱动适配的主要步骤如下: - 如果SDK原本基于freeRTOS等其他嵌入式OS或者本身有一层OS interface的抽象层,建议将依赖OS接口直接适配到CMSIS接口; - 例如,某产品定义的OS interface接口,创建queue的接口原型: +1. SDK基于OpenHarmony提供的CMSIS/POSIX适配依赖OS的接口。 + 板级SDK适配OS接口存在两种选择:CMSIS、POSIX,当前liteos_m已经适配CMSIS大部分接口(覆盖:基础内核管理、线程管理、定时器、事件、互斥锁、信号量、队列等),基本可以满足直接移植,POSIX接口当前具备初步的移植能力,接口正在补全中;如果SDK原本基于CMSIS或者POSIX接口实现,理论上可以直接适配到liteos_m中; - ``` - bool osif_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) - ``` + 如果SDK原本基于freeRTOS等其他嵌入式OS或者本身有一层OS interface的抽象层,建议将依赖OS接口直接适配到CMSIS接口; - 而CMSIS提供的接口原型如下: + 例如,某产品定义的OS interface接口,创建queue的接口原型: - ``` - osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); - ``` + + ``` + bool osif_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) + ``` - 对应的OS interface接口的原型可以按照如下适配: + 而CMSIS提供的接口原型如下: - ``` - #include "CMSIS_os2.h" - osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); - bool osif_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) - { - (*pp_handle) = osMessageQueueNew (msg_num, msg_size, NULL); - if((*pp_handle) == NULL){ - return FALSE; - } - return TRUE; - } - ``` + + ``` + osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); + ``` -2. 接口SDK编译问题或者基于OpenHarmony编译框架改造SDK,将SDK按照目录结构要求合入OpenHarmony的device目录中。 + 对应的OS interface接口的原型可以按照如下适配: - OS接口适配后,板级驱动集成到OpenHarmony也存在2种选择: + + ``` + #include "CMSIS_os2.h" + osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); + bool osif_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) + { + (*pp_handle) = osMessageQueueNew (msg_num, msg_size, NULL); + if((*pp_handle) == NULL){ + return FALSE; + } + return TRUE; + } + ``` - - SDK独立编译,通过二进制形式直接链入OpenHarmony; - - SDK基于OpenHarmony改造编译框架,从长期演进及后期联调便利性角度角度考虑,建议基于GN编译框架直接改造SDK编译框架,通过源码形式链入OpenHarmony工程。 +2. 接口SDK编译问题或者基于OpenHarmony编译框架改造SDK,将SDK按照目录结构要求合入OpenHarmony的device目录中。 + OS接口适配后,板级驱动集成到OpenHarmony也存在2种选择: -3. 验证SDK基本功能。 + - SDK独立编译,通过二进制形式直接链入OpenHarmony; + - SDK基于OpenHarmony改造编译框架,从长期演进及后期联调便利性角度角度考虑,建议基于GN编译框架直接改造SDK编译框架,通过源码形式链入OpenHarmony工程。 +3. 验证SDK基本功能。 diff --git a/zh-cn/device-dev/porting/porting-chip-board-hal.md b/zh-cn/device-dev/porting/porting-chip-board-hal.md index 9f97773be5bcb87c266b0a3ddeb473f74e72edd0..64cba25738125914d680563c9be14b6b00be4e1b 100755 --- a/zh-cn/device-dev/porting/porting-chip-board-hal.md +++ b/zh-cn/device-dev/porting/porting-chip-board-hal.md @@ -1,12 +1,10 @@ -# HAL层实现 +# HAL层实现 -- [UTILS](#section1394788286) -- [IOT外设子系统](#section958113200811) -- [WLAN服务](#section1331917210911) HAL层主要功能是实现轻OpenHarmony与芯片的解耦,以下模块描述的是轻OpenHarmony系统对芯片接口的依赖情况。 -## UTILS + +## UTILS **基本介绍:** @@ -16,7 +14,8 @@ HAL层主要功能是实现轻OpenHarmony与芯片的解耦,以下模块描述 需要芯片适配相关接口的实现,对芯片文件系统接口依赖请参考[utils的HAL头文件](https://gitee.com/openharmony/utils_native_lite/tree/master/hals/file)。 -## IOT外设子系统 + +## IOT外设子系统 **基本介绍** @@ -26,16 +25,16 @@ HAL层主要功能是实现轻OpenHarmony与芯片的解耦,以下模块描述 需要芯片适配相关接口的实现,对芯片设备外设接口依赖请参考[IOT外设子系统的HAL头文件](https://gitee.com/openharmony/iothardware_peripheral/tree/master/interfaces/kits)。 -## WLAN服务 + +## WLAN服务 **基本介绍:** WLAN服务适用于设备接入WLAN无线局域网场景,包括: -- 使用STA模式,作为接入方接入其他设备、路由器开启的WLAN无线局域网接入点; - -- 使用AP模式,开启无线局域网接入点,允许其他设备连接。 +- 使用STA模式,作为接入方接入其他设备、路由器开启的WLAN无线局域网接入点; +- 使用AP模式,开启无线局域网接入点,允许其他设备连接。 借助WLAN服务,开发者可以实现对系统中WLAN的控制,包括开启关闭、扫描发现、连接断开等功能。 @@ -45,6 +44,7 @@ WLAN服务适用于设备接入WLAN无线局域网场景,包括: 代码路径及接口定义如下: + ``` foundation/communication/interfaces/kits/wifi_lite/wifiservice/ ├── station_info.h @@ -58,8 +58,9 @@ foundation/communication/interfaces/kits/wifi_lite/wifiservice/ └── wifi_scan_info.h ``` -具体的实现需要各厂家按照定义的接口在vendor/\*\*\*/\*\*\*/\*\*\*\_adapter中实现,例如hi3861中具体实现在 +具体的实现需要各厂家按照定义的接口在vendor/\*\*\*/\*\*\*/\*\*\*_adapter中实现,例如hi3861中具体实现在 + ``` vendor/hisi/hi3861/hi3861_adapter/hals/communication/wifi_lite/wifiservice/ ├── BUILD.gn @@ -71,4 +72,3 @@ vendor/hisi/hi3861/hi3861_adapter/hals/communication/wifi_lite/wifiservice/ ``` 需要芯片适配相关接口的实现,对芯片设备外设接口依赖请参考[WLAN服务的头文件](https://gitee.com/openharmony/communication_wifi_lite/tree/master/interfaces/wifiservice)。 - diff --git a/zh-cn/device-dev/porting/porting-chip-board-lwip.md b/zh-cn/device-dev/porting/porting-chip-board-lwip.md index 5fc2525d714bf76fb6ca9ce1c877d6e7f4449840..ba5fbcae83c0a33e2a41bfce16144e0be5fd3c5c 100644 --- a/zh-cn/device-dev/porting/porting-chip-board-lwip.md +++ b/zh-cn/device-dev/porting/porting-chip-board-lwip.md @@ -1,64 +1,64 @@ -# lwIP组件适配 +# lwIP组件适配 + lwIP是一个小型开源的TCP/IP协议栈,LiteOS-M已对开源lwIP做了适配和功能增强,lwIP代码分为两部分: + - third_party/lwip目录下是lwIP开源代码,里面只做了少量的侵入式修改,为了适配增强功能。 - kernel/liteos_m/components/net/lwip-2.1目录下是lwIP适配和功能增强代码,里面提供了lwIP的默认配置文件。 + 如果需要使用lwIP组件,请按如下步骤适配: + 1. 在产品目录下新建一个目录用来存放产品的适配文件,如lwip_adapter。 2. 在lwip_adapter目录下新建一个目录include,用来存放适配的头文件。 3. 在include目录下新建目录lwip,并在lwip目录下新建头文件lwipopts.h,代码如下所示,如果默认配置不能满足产品使用,可自行根据产品使用情况修改配置,如关闭DHCP功能。 - - ``` - #ifndef _LWIP_ADAPTER_LWIPOPTS_H_ - #define _LWIP_ADAPTER_LWIPOPTS_H_ - - #include_next "lwip/lwipopts.h" - - #undef LWIP_DHCP - #define LWIP_DHCP 0 // 关闭DHCP功能 - - #endif /* _LWIP_ADAPTER_LWIPOPTS_H_ */ - ``` - -4. 将kernel/liteos_m/components/net/lwip-2.1/porting目录下的BUILD.gn复制到lwip_adapter目录下,并按如下修改。 - - ``` - import("//kernel/liteos_m/liteos.gni") - import("$LITEOSTHIRDPARTY/lwip/lwip.gni") - import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni") - - module_switch = defined(LOSCFG_NET_LWIP_SACK) - module_name = "lwip" - kernel_module(module_name) { - sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES - [ "$LWIPDIR/api/sockets.c" ] - include_dirs = [ "//utils/native/lite/include" ] - } - - #添加新增加的适配头文件路径include - config("public") { - include_dirs = [ "include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS - } - ``` + + ``` + #ifndef _LWIP_ADAPTER_LWIPOPTS_H_ + #define _LWIP_ADAPTER_LWIPOPTS_H_ + + #include_next "lwip/lwipopts.h" + + #undef LWIP_DHCP#define LWIP_DHCP 0 // 关闭DHCP功能 + + #endif /* _LWIP_ADAPTER_LWIPOPTS_H_ */ + ``` + +4. 将kernel/liteos_m/components/net/lwip-2.1目录下的BUILD.gn复制到lwip_adapter目录下,并按如下修改。 + + ``` + import("//kernel/liteos_m/liteos.gni") + import("$LITEOSTHIRDPARTY/lwip/lwip.gni") + import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni") + module_switch = defined(LOSCFG_NET_LWIP_SACK) + module_name = "lwip"kernel_module(module_name) { + sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES - [ "$LWIPDIR/api/sockets.c" ] + include_dirs = [ "//utils/native/lite/include" ] + } + #添加新增加的适配头文件路径include + config("public") { + include_dirs = [ "include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS + } + ``` 5. 在产品的配置文件(如config.json)中设置lwIP的编译路径,即步骤4中BUILD.gn的路径。 - - ``` - { - "subsystem": "kernel", - "components": [ - { "component": "liteos_m", "features":["ohos_kernel_liteos_m_lwip_path = \"//xxx/lwip_adapter\"" ] } - ] - }, - ``` + + ``` + { + "subsystem": "kernel", + "components": [ + { "component": "liteos_m", "features":["ohos_kernel_liteos_m_lwip_path = \"//xxx/lwip_adapter\"" ] } + ] + }, + ``` 6. 在产品的内核编译配置文件中,如kernel_config/debug.config,打开编译lwIP的开关。 - - ``` - LOSCFG_NET_LWIP=y - ``` + + ``` + LOSCFG_NET_LWIP=y + ``` diff --git a/zh-cn/device-dev/porting/porting-chip-board-overview.md b/zh-cn/device-dev/porting/porting-chip-board-overview.md index eada2b43da18f4f8371ab449a0b3570d27ce30c1..f658a4511cb85a71895dce05d7c94d9471b289f6 100644 --- a/zh-cn/device-dev/porting/porting-chip-board-overview.md +++ b/zh-cn/device-dev/porting/porting-chip-board-overview.md @@ -1,24 +1,31 @@ -# 移植概述 +# 移植概述 -- [板级移植流程](#section1283115812294) -- [板级目录规范](#section6204129143013) -## 板级移植流程 +## 板级移植流程 最小系统移植完成后,下一步进行板级系统移植,板级系统移植包含以下几步操作: -1. 板级驱动适配。 -2. HAL层实现。 -3. XTS测试套。 -4. 业务功能验证。 +1. 板级驱动适配。 -**图 1** 单板驱动适配流程 -![](figure/单板驱动适配流程.png "单板驱动适配流程") +2. HAL层实现。 -## 板级目录规范 +3. XTS测试套。 -板级系统编译适配参考[编译系统介绍](porting-chip-prepare-process.md),板级相关的驱动、SDK、目录、HAL实现存放在device目录,目录结构和具体描述如下: +4. 业务功能验证。 + + **图1** 单板驱动适配流程 + + ![zh-cn_image_0000001200417969](figures/zh-cn_image_0000001200417969.png) + + +## 板级目录规范 + + +板级系统编译适配参考[编译系统介绍](../porting/porting-chip-prepare-process.md),板级相关的驱动、SDK、目录、HAL实现存放在device目录,目录结构和具体描述如下: + + + ``` . ├── device --- 单板样例 @@ -54,4 +61,3 @@ └── out --- 编译过程中的输出目录 ├── ... --- 单板/产品编译产生的bin等 ``` - diff --git a/zh-cn/device-dev/porting/porting-chip-board-xts.md b/zh-cn/device-dev/porting/porting-chip-board-xts.md index 00253685f7583381c9a5d89bd24a57bf2a7d3dcc..f430a04b403e8324f2609b356200d46180bfa57b 100644 --- a/zh-cn/device-dev/porting/porting-chip-board-xts.md +++ b/zh-cn/device-dev/porting/porting-chip-board-xts.md @@ -1,65 +1,66 @@ -# XTS认证 +# XTS认证 -- [XTS简介](#section6725155811454) - - [将XTS认证子系统加入编译组件中](#section46981118105417) - - [执行联接类模组acts测试用例](#section9489122319819) - -## XTS简介 +## XTS简介 XTS是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套。test/xts仓当前包括acts与tools软件包: -- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -- tools,存放acts相关测试用例开发框架。 +- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 + +- tools,存放acts相关测试用例开发框架。 + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> XTS的启动依赖SAMGR系统服务。 ->![](../public_sys-resources/icon-note.gif) **说明:** ->XTS的启动依赖SAMGR系统服务。 适配分为两步,包括: -1. 将XTS认证子系统加入编译组件中。 -2. 执行联接类模组acts测试用例。 -### 将XTS认证子系统加入编译组件中 +1. 将XTS认证子系统加入编译组件中。 + +2. 执行联接类模组acts测试用例。 + -举例:将XTS认证子系统加入hispark\_aries产品编译组件中为例。 +### 将XTS认证子系统加入编译组件中 -1. 在vendor/hisilicon/hispark\_aries/config.json中加入XTS认证子系统定义: +举例:将XTS认证子系统加入hispark_aries产品编译组件中为例。 - ``` - { - "subsystem": "test", - "components": [ - { "component": "xts_acts", "features":[] }, - { "component": "xts_tools", "features":[] } - ] - }, - ``` +1. 在vendor/hisilicon/hispark_aries/config.json中加入XTS认证子系统定义: + + ``` + { + "subsystem": "test", + "components": [ + { "component": "xts_acts", "features":[] }, + { "component": "xts_tools", "features":[] } + ] + }, + ``` -2. Debug版本才会触发XTS认证子系统编译; +2. Debug版本才会触发XTS认证子系统编译; -### 执行联接类模组acts测试用例 -举例:以hispark\_aries产品执行联接类模组acts测试用例为例。 +### 执行联接类模组acts测试用例 -1. 获取编译镜像。 +举例:以hispark_aries产品执行联接类模组acts测试用例为例。 - 请在如下目录获取版本镜像:out/hispark\_pegasus/wifiiot\_hispark\_pegasus/。 - >![](../public_sys-resources/icon-note.gif) **说明:** - >判断当前版本镜像是否集成acts测试套件方法:在map文件中查看对应.a是否被编译即可。 +1. 获取编译镜像。 + 请在如下目录获取版本镜像:out/hispark_pegasus/wifiiot_hispark_pegasus/。 -2. 版本镜像烧录进开发板。 -3. 测试步骤。 + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 判断当前版本镜像是否集成acts测试套件方法:在map文件中查看对应.a是否被编译即可。 - (1)使用串口工具登录开发板,并保存串口打印信息。 +2. 版本镜像烧录进开发板。 - (2)重启设备,查看串口日志。 +3. 测试步骤。 -4. 测试结果分析指导。 + (1)使用串口工具登录开发板,并保存串口打印信息。 - (1)基于串口打印日志进行分析; + (2)重启设备,查看串口日志。 - (2)每个测试套件执行以“Start to run test suite”开始,以“xx Tests xx Failures xx Ignored”结束。 +4. 测试结果分析指导。 + (1)基于串口打印日志进行分析; + (2)每个测试套件执行以“Start to run test suite”开始,以“xx Tests xx Failures xx Ignored”结束。 diff --git a/zh-cn/device-dev/porting/porting-chip-board.md b/zh-cn/device-dev/porting/porting-chip-board.md index 6033d18fea5897b3557dcec6e3818c286a63cf7f..0cdc6cba9d15a59fb6eaca12e3c2c39477f8c1ff 100644 --- a/zh-cn/device-dev/porting/porting-chip-board.md +++ b/zh-cn/device-dev/porting/porting-chip-board.md @@ -1,17 +1,17 @@ -# 板级系统移植 +# 板级系统移植 -- **[移植概述](porting-chip-board-overview.md)** -- **[板级驱动适配](porting-chip-board-driver.md)** -- **[HAL层实现](porting-chip-board-hal.md)** +- **[移植概述](porting-chip-board-overview.md)** -- **[系统组件调用](porting-chip-board-component.md)** +- **[板级驱动适配](porting-chip-board-driver.md)** -- **[lwip组件适配](porting-chip-board-lwip.md)** +- **[HAL层实现](porting-chip-board-hal.md)** -- **[三方组件适配](porting-chip-board-bundle.md)** +- **[系统组件调用](porting-chip-board-component.md)** -- **[XTS认证](porting-chip-board-xts.md)** +- **[lwIP组件适配](porting-chip-board-lwip.md)** +- **[三方组件适配](porting-chip-board-bundle.md)** +- **[XTS认证](porting-chip-board-xts.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-chip-faqs.md b/zh-cn/device-dev/porting/porting-chip-faqs.md index d0ebf9553d4b322c931a703d9ff0bf61d87e434b..0c2125da9effc34afb714d0efbf564c79c1ae24d 100755 --- a/zh-cn/device-dev/porting/porting-chip-faqs.md +++ b/zh-cn/device-dev/porting/porting-chip-faqs.md @@ -1,39 +1,19 @@ -# 常见问题 - -- [如何将用户的堆内存挂载进内核](#section965418378552) - -## 如何将用户的堆内存挂载进内核 - -- 内核堆内存配置的相关宏如下,用户可根据实际情况,在target\_config.h中配置: - -**表 1** 内核堆内存配置相关宏 - - - - - - - - - - - - - - - - -

宏名称

-

描述

-

LOSCFG_SYS_EXTERNAL_HEAP

-

这个宏决定系统是使用内核的内部堆内存还是用户的堆内存,默认为0(即使用内部的堆内存),大小为0x10000;如果用户需要基于外部的堆内存,那么可以将该宏设置为1。

-

LOSCFG_SYS_HEAP_ADDR

-

内核堆内存的起始地址。

-

LOSCFG_SYS_HEAP_SIZE

-

内核堆内存的大小,即LOSCFG_SYS_HEAP_ADDR指定的内存块大小。

-
- -- 注意事项: +# 常见问题 + + +## 如何将用户的堆内存挂载进内核 + +- 内核堆内存配置的相关宏如下,用户可根据实际情况,在target_config.h中配置: + + **表1** 内核堆内存配置相关宏 + +| 宏名称 | 描述 | +| -------- | -------- | +| LOSCFG_SYS_EXTERNAL_HEAP | 这个宏决定系统是使用内核的内部堆内存还是用户的堆内存,默认为0(即使用内部的堆内存),大小为0x10000;如果用户需要基于外部的堆内存,那么可以将该宏设置为1。 | +| LOSCFG_SYS_HEAP_ADDR | 内核堆内存的起始地址。 | +| LOSCFG_SYS_HEAP_SIZE | 内核堆内存的大小,即LOSCFG_SYS_HEAP_ADDR指定的内存块大小。 | + +- 注意事项: 指定的堆内存范围务必保证没有其他模块使用,避免踩内存,破坏堆内存功能。 diff --git a/zh-cn/device-dev/porting/porting-chip-kernel-adjustment.md b/zh-cn/device-dev/porting/porting-chip-kernel-adjustment.md index 31261e8790201b6eb59db288b4645bcc27d1bd96..49027fec727c239ea2125e5bcc2ba4ec2d622089 100644 --- a/zh-cn/device-dev/porting/porting-chip-kernel-adjustment.md +++ b/zh-cn/device-dev/porting/porting-chip-kernel-adjustment.md @@ -1,86 +1,49 @@ -# 内核基础适配 +# 内核基础适配 -- [基础适配](#section14523241594) -- [特性配置项](#section112994366592) 芯片架构适配完成后,liteos-m提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数;了解内核配置选项,才能裁剪出适合单板的最小内核。 -## 基础适配 + +## 基础适配 如下图所示,基础适配主要分为以下两步: -1. 启动文件startup.S和相应链接配置文件。 -2. main. c中的串口初始化和tick中断注册。 +1. 启动文件startup.S和相应链接配置文件。 + +2. main. c中的串口初始化和tick中断注册。 + + **图1** 启动流程 -**图 1** 启动流程 -![](figure/启动流程.png "启动流程") + ![zh-cn_image_0000001199842521](figures/zh-cn_image_0000001199842521.png) -启动文件startup.S需要确保中断向量表的入口函数(例如reset\_vector)放在RAM的首地址,它由链接配置文件来指定。其中iar、keil和gcc工程的链接配置文件分别为xxx.icf、xxx.sct和xxx.ld,如果startup.S已经完成系统时钟初始化,并且能够引导到main函数,则启动文件不需要进行修改,采用厂商自带的startup.S即可,否则需要实现以上功能。 +启动文件startup.S需要确保中断向量表的入口函数(例如reset_vector)放在RAM的首地址,它由链接配置文件来指定。其中iar、keil和gcc工程的链接配置文件分别为xxx.icf、xxx.sct和xxx.ld,如果startup.S已经完成系统时钟初始化,并且能够引导到main函数,则启动文件不需要进行修改,采用厂商自带的startup.S即可,否则需要实现以上功能。 在main.c文件中,需要关注串口初始化UartInit和系统Tick的handler函数注册。 -- UartInit函数表示单板串口的初始化,具体的函数名根据单板自行定义。这个函数是可选的,用户可以根据硬件单板是否支持串口来自行选择调用该函数。如果硬件单板支持串口,则该函数需要完成使能串口TX和RX通道,设置波特率。 -- HalTickStart设置tick中断的handler函数OsTickHandler。 +- UartInit函数表示单板串口的初始化,具体的函数名根据单板自行定义。这个函数是可选的,用户可以根据硬件单板是否支持串口来自行选择调用该函数。如果硬件单板支持串口,则该函数需要完成使能串口TX和RX通道,设置波特率。 -对于中断向量表不可重定向的芯片,需要关闭LOSCFG\_PLATFORM\_HWI宏,并且在startup.S中新增tick中断的handler函数。 +- HalTickStart设置tick中断的handler函数OsTickHandler。 -## 特性配置项 +对于中断向量表不可重定向的芯片,需要关闭LOSCFG_PLATFORM_HWI宏,并且在startup.S中新增tick中断的handler函数。 -liteos\_m的完整配置能力及默认配置在los\_config.h定义,该头文件中的配置项可以根据不同的单板进行裁剪配置。 -如果针对这些配置项需要进行不同的板级配置,则可将对应的配置项直接定义到对应单板的device/xxxx/target\_config.h文件中,其他未定义的配置项,采用los\_config.h中的默认值。 +## 特性配置项 -一份典型的配置参数如下: +liteos_m的完整配置能力及默认配置在los_config.h定义,该头文件中的配置项可以根据不同的单板进行裁剪配置。 + +如果针对这些配置项需要进行不同的板级配置,则可将对应的配置项直接定义到对应单板的device/xxxx/target_config.h文件中,其他未定义的配置项,采用los_config.h中的默认值。 -**表 1** 内核典型配置项说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

配置项

-

说明

-

LOSCFG_BASE_CORE_SWTMR

-

软件定时器特性开关,1表示打开,0表示关闭

-

LOSCFG_BASE_CORE_SWTMR_ALIGN

-

对齐软件定时器特性开,1表示打开,依赖软件定时器特性打开,0表示关闭

-

LOSCFG_BASE_IPC_MUX

-

mux功能开关,1表示打开,0表示关闭

-

LOSCFG_BASE_IPC_QUEUE

-

队列功能开关,1表示打开,0表示关闭

-

LOSCFG_BASE_CORE_TSK_LIMIT

-

除idle task之外,总的可用task个数限制,可以根据业务使用的task个数来配置,也可以设置一个较大的值,待业务稳定了,查看运行task的个数来进行配置

-

LOSCFG_BASE_IPC_SEM

-

信号量功能开关,1表示打开,0表示关闭

-

LOSCFG_PLATFORM_EXC

-

异常特性开关,1表示打开,0表示关闭

-

LOSCFG_KERNEL_PRINTF

-

打印特性开关,1表示打开,0表示关闭

-
+一份典型的配置参数如下: + **表1** 内核典型配置项说明 + +| 配置项 | 说明 | +| -------- | -------- | +| LOSCFG_BASE_CORE_SWTMR | 软件定时器特性开关,1表示打开,0表示关闭 | +| LOSCFG_BASE_CORE_SWTMR_ALIGN | 对齐软件定时器特性开,1表示打开,依赖软件定时器特性打开,0表示关闭 | +| LOSCFG_BASE_IPC_MUX | mux功能开关,1表示打开,0表示关闭 | +| LOSCFG_BASE_IPC_QUEUE | 队列功能开关,1表示打开,0表示关闭 | +| LOSCFG_BASE_CORE_TSK_LIMIT | 除idle task之外,总的可用task个数限制,可以根据业务使用的task个数来配置,也可以设置一个较大的值,待业务稳定了,查看运行task的个数来进行配置 | +| LOSCFG_BASE_IPC_SEM | 信号量功能开关,1表示打开,0表示关闭 | +| LOSCFG_PLATFORM_EXC | 异常特性开关,1表示打开,0表示关闭 | +| LOSCFG_KERNEL_PRINTF | 打印特性开关,1表示打开,0表示关闭 | diff --git a/zh-cn/device-dev/porting/porting-chip-kernel-overview.md b/zh-cn/device-dev/porting/porting-chip-kernel-overview.md index e2bc9d055847389c77cce1aa9410e33351e0b1da..e2fd8ea12b978e4d87d80901d207f6bd05097dc6 100644 --- a/zh-cn/device-dev/porting/porting-chip-kernel-overview.md +++ b/zh-cn/device-dev/porting/porting-chip-kernel-overview.md @@ -1,57 +1,61 @@ -# 移植概述 +# 移植概述 -- [移植场景](#section93781277367) -- [目录规范](#section18127744153119) -- [芯片架构适配点](#section137431650339) -## 移植场景 +## 移植场景 -芯片架构适配是可选过程,如果在liteos\_m/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 +芯片架构适配是可选过程,如果在liteos_m/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 -## 目录规范 + +## 目录规范 模组芯片使用的内核为liteos-m,liteos-m中主要分为KAL、Components、Kernel和Utils四个模块。 -- KAL模块作为内核对外的接口依赖Components模块和Kernel模块。 -- Components模块可插拔,它依赖Kernel模块。 +- KAL模块作为内核对外的接口依赖Components模块和Kernel模块。 + +- Components模块可插拔,它依赖Kernel模块。 + +- 在Kernel模块中,其中硬件相关的代码放在kernel的arch目录中,其余为硬件无关的代码。内核功能集(task、sem等)的实现依赖硬件相关的arch代码,例如任务上下文切换、原子操作等。 -- 在Kernel模块中,其中硬件相关的代码放在kernel的arch目录中,其余为硬件无关的代码。内核功能集(task、sem等)的实现依赖硬件相关的arch代码,例如任务上下文切换、原子操作等。 -- Utils模块作为基础代码块,被其他模块依赖。 +- Utils模块作为基础代码块,被其他模块依赖。 -**图 1** liteos-m内核模块图 -![](figure/liteos-m内核模块图.png "liteos-m内核模块图") + **图1** liteos-m内核模块图 + + ![zh-cn_image_0000001199722629](figures/zh-cn_image_0000001199722629.png) 内核的目录结构和说明如下: + ``` . -├── arch --- 内核指令架构层代码 -│ ├── arm --- arm32架构的代码 -│ │ ├── cortex-m3 --- cortex-m3架构的代码 -│ │ │ ├── iar --- iar编译工具链实现 -│ │ │ ├── keil --- keil编译工具链实现 -│ │ │ └── xxx --- xxx编译工具链实现 -│ │ └── cortex-m4 --- cortex-m4架构的代码 -│ │ ├── iar --- iar编译工具链实现 -│ │ ├── keil --- keil编译工具链实现 -│ │ └── xxx --- xxx编译工具链实现 -│ ├── include --- 所有的arch需要实现的函数定义,内核依赖 -│ └── risc-v --- risk-v架构 -│ └── gcc --- gcc编译工具链实现 ├── components --- 移植可选组件,依赖内核,单独对外提供头文件 ├── kal --- 内核抽象层,提供内核对外接口,当前支持cmsis接口和部分posix接口 ├── kernel --- 内核最小功能集代码 +│ ├── arch --- 内核指令架构层代码 +│ │ ├── arm --- arm32架构的代码 +│ │ │ ├── cortex-m3 --- cortex-m3架构的代码 +│ │ │ │ ├── iar --- iar编译工具链实现 +│ │ │ │ ├── keil --- keil编译工具链实现 +│ │ │ │ └── xxx --- xxx编译工具链实现 +│ │ │ └── cortex-m4 --- cortex-m4架构的代码 +│ │ │ ├── iar --- iar编译工具链实现 +│ │ │ ├── keil --- keil编译工具链实现 +│ │ │ └── xxx --- xxx编译工具链实现 +│ │ ├── include --- 所有的arch需要实现的函数定义,内核依赖 +│ │ └── risc-v --- risk-v架构 +│ │ └── gcc --- gcc编译工具链实现 │ ├── include --- 内核最小功能集代码 │ └── src --- 内核最小功能集代码 └──utils --- 基础代码,作为依赖的最底层,被系统依赖 ``` -## 芯片架构适配点 -如内核的[目录结构](#section18127744153119)所示,arch/include定义通用的芯片架构所需要实现的函数,另外芯片架构相关的代码会有部分的汇编代码,而汇编代码会因编译工具链的不同而不同,因此在具体的芯片架构下,还包含不同工具链(iar、keil、gcc等)的实现。 +## 芯片架构适配点 + +如内核的[目录结构](#目录规范)所示,arch/include定义通用的芯片架构所需要实现的函数,另外芯片架构相关的代码会有部分的汇编代码,而汇编代码会因编译工具链的不同而不同,因此在具体的芯片架构下,还包含不同工具链(iar、keil、gcc等)的实现。 arch/include 目录定义通用的文件以及函数列表,该目录下的所有函数在新增arch组件时都需要适配,详见每一个头文件: + ``` los_arch.h --- 定义芯片架构初始化所需要的函数 los_atomic.h --- 定义芯片架构所需要实现的原子操作函数 @@ -59,4 +63,3 @@ los_context.h --- 定义芯片架构所需要实现的任务 los_interrupt.h --- 定义芯片架构所需要实现的中断和异常相关的函数 los_timer.h --- 定义芯片架构所需要实现的系统时钟相关的函数 ``` - diff --git a/zh-cn/device-dev/porting/porting-chip-kernel-verify.md b/zh-cn/device-dev/porting/porting-chip-kernel-verify.md index 1df4bdd6f7b3edf8737962336b39e9bf78c4d22b..f510776b22daf9ed2e35d589ae7b9a840e1ed71e 100644 --- a/zh-cn/device-dev/porting/porting-chip-kernel-verify.md +++ b/zh-cn/device-dev/porting/porting-chip-kernel-verify.md @@ -1,6 +1,7 @@ -# 内核移植验证 +# 内核移植验证 -在工程device目录下添加编译main.c示例程序文件,此示例程序的主要目的是:LOS\_KernelInit完成之后,创建两个任务,循环调度延时并打印日志信息,通过此方法可以验证系统是否可正常调度以及时钟是否正常。 + +在工程device目录下添加编译main.c示例程序文件,此示例程序的主要目的是:LOS_KernelInit完成之后,创建两个任务,循环调度延时并打印日志信息,通过此方法可以验证系统是否可正常调度以及时钟是否正常。 ``` VOID TaskSampleEntry2(VOID) // 任务2的入口函数 @@ -55,5 +56,5 @@ LITE_OS_SEC_TEXT_INIT int main(void) } ``` -第一个任务运行正常后,说明最小系统的核心流程基本OK;由于xts用例框架对外依赖较多,主要是utils、bootstrap的链接脚本和编译框架,暂时无法支撑内核单独跑xts;此处略过内核测试套的测试,可以通过[XTS测试套](porting-chip-board-xts.md)来覆盖最小系统是否完整移植成功。 +第一个任务运行正常后,说明最小系统的核心流程基本OK;由于xts用例框架对外依赖较多,主要是utils、bootstrap的链接脚本和编译框架,暂时无法支撑内核单独跑xts;此处略过内核测试套的测试,可以通过[XTS测试套](../porting/porting-chip-board-xts.md)来覆盖最小系统是否完整移植成功。 diff --git a/zh-cn/device-dev/porting/porting-chip-kernel.md b/zh-cn/device-dev/porting/porting-chip-kernel.md index b488ca9132ba1421d84a15ee0a28182b3e431052..643622fcddc6d1a66f35e9433788555624c08d99 100644 --- a/zh-cn/device-dev/porting/porting-chip-kernel.md +++ b/zh-cn/device-dev/porting/porting-chip-kernel.md @@ -1,9 +1,9 @@ -# 内核移植 +# 内核移植 -- **[移植概述](porting-chip-kernel-overview.md)** -- **[内核基础适配](porting-chip-kernel-adjustment.md)** -- **[内核移植验证](porting-chip-kernel-verify.md)** +- **[移植概述](porting-chip-kernel-overview.md)** +- **[内核基础适配](porting-chip-kernel-adjustment.md)** +- **[内核移植验证](porting-chip-kernel-verify.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-chip-prepare-knows.md b/zh-cn/device-dev/porting/porting-chip-prepare-knows.md new file mode 100644 index 0000000000000000000000000000000000000000..1791018a6fc4b643576bcc5a299aa7709ffd08d9 --- /dev/null +++ b/zh-cn/device-dev/porting/porting-chip-prepare-knows.md @@ -0,0 +1,67 @@ +# 移植须知 + + +本文为OpenHarmony平台系统开发人员和芯片(或模组)制造商提供基础的开发移植指导,典型的芯片架构例如cortex-m系列、risc-v系列等都可以按照本文进行移植,暂时不支持蓝牙服务。OpenHarmony是个持续演进的复杂项目,随着版本和API的改变,本文将会不断更新。 + + +本文要求读者具有一定的嵌入式系统开发经验,因此它的重点未放在基本的OS基础介绍,而更多地描述OpenHarmony平台移植过程中主要操作和所需要关注的方面。 + + +## 移植目录 + +OpenHarmony整体工程较为复杂,目录及实现为系统本身功能,如果不涉及复杂的特性增强,不需要关注每一层实现,移植过程中重点关注如下目录即可: + + **表1** 移植过程中的重点目录 + +| 目录名称 | 描述 | +| -------- | -------- | +| /build/lite | OpenHarmony基础编译构建框架 | +| /kernel/liteos_m | 基础内核,其中芯片架构相关实现在arch目录下 | +| /device | 板级相关实现,各个三方厂商按照OpenHarmony规范适配实现,device下具体目录结构及移植过程参见[板级系统移植](../porting/porting-chip-board-overview.md) | +| /vendor | 产品级相关实现,主要由华为或者产品厂商贡献 | + +device目录规则:device/{芯片解决方案厂商}/{开发板}。以hisilicon的hispark_taurus为例: + + +``` +device +└── hisilicon # 芯片解决方案厂商名 + ├── common # 芯片解决方案开发板公共部分 + └── hispark_taurus # 开发板名称 + ├── BUILD.gn # 开发板编译入口 + ├── hals # 芯片解决方案厂商OS硬件适配 + ├── linux # linux版本 + │ └── config.gni # linux版本编译工具链和编译选项配置 + └── liteos_a # liteos-a版本 + └── config.gni # liteos-a版本编译工具链和编译选项配置 +``` + + +vendor目录规则:vendor/{产品解决方案厂商}/{产品名称}。以华为的wifiiot产品为例: + + + +``` +vendor # 产品解决方案厂商 +└── example # 产品解决方案厂商名称 + └── wifiiot # 产品名称 + ├── hals # 产品解决方案厂商OS适配 + ├── BUILD.gn # 产品编译脚本 + └── config.json # 产品配置文件 +``` + + +## 移植流程 + +OpenHarmony的device目录是基础芯片的适配目录,如果在三方芯片应用过程中发现此目录下已经有完整的芯片适配,则不需要再额外移植,直接跳过移植过程进行系统应用开发即可,如果该目录下无对应的芯片移植实现,则根据本文完成移植过程。OpenHarmony三方芯片移植主要过程如下: + + **图1** 芯片移植关键步骤 + + ![zh-cn_image_0000001200336823](figures/zh-cn_image_0000001200336823.png) + + +## 移植规范 + +- 满足OpenHarmony[开源贡献基本规范和准则](../../contribute/参与贡献.md)。 + +- 三方芯片适配所需要贡献的代码主要在device、vendor和arch三个目录,参照[内核目录规范](../porting/porting-chip-kernel-overview.md)和[板级目录规范](../porting/porting-chip-board-overview.md#板级目录规范)满足基本目录命名和使用规范。 diff --git a/zh-cn/device-dev/porting/porting-chip-prepare-process.md b/zh-cn/device-dev/porting/porting-chip-prepare-process.md index c9fe780d754e5142e3259f245f8f7d4bf14c18d6..503972d4e72da5945b93d678c71140707d70f6be 100644 --- a/zh-cn/device-dev/porting/porting-chip-prepare-process.md +++ b/zh-cn/device-dev/porting/porting-chip-prepare-process.md @@ -1,120 +1,116 @@ -# 编译构建适配流程 +# 编译构建适配流程 -- [编译构建适配流程](#section2159183845319) 编译构建的详细介绍请见[编译构建子系统介绍](../subsystems/subsys-build-mini-lite.md)。新增三方芯片时,编译相关的适配流程如下: -## 编译构建适配流程 - -首先,创建开发板目录,以芯片解决方案厂商realtek的“rtl8720“开发板为例,需创建device/realtek/rtl8720目录。编译相关的适配步骤如下: - -1. 编译工具链和编译选项配置。 - - 构建系统默认使用ohos-clang编译工具链,也支持芯片解决方案厂商按开发板自定义配置。开发板编译配置文件编译相关的变量如下: - - - kernel\_type: 开发板使用的内核类型,例如:"liteos\_a", "liteos\_m", "linux"。 - - kernel\_version: 开发使用的内核版本,例如:"4.19"。 - - board\_cpu: 开发板CPU类型,例如:"cortex-a7", "riscv32"。 - - board\_arch: 开发芯片arch, 例如: "armv7-a", "rv32imac"。 - - board\_toolchain: 开发板自定义的编译工具链名称,例如:"gcc-arm-none-eabi"。若为空,则使用默认为ohos-clang。 - - board\_toolchain\_prefix:编译工具链前缀,例如:"gcc-arm-none-eabi"。 - - board\_toolchain\_type:编译工具链类型,目前支持gcc和clang。例如:"gcc" ,"clang"。 - - board\_cflags:开发板配置的c文件编译选项。 - - board\_cxx\_flags:开发板配置的cpp文件编译选项。 - - board\_ld\_flags:开发板配置的链接选项。 - - 编译构建会按产品的选择的开发板,加载对应的config.gni,该文件中变量对系统组件全局可见。 - - 以芯片解决方案厂商realtek的“rtl8720“开发板为例,device/realtek/rtl8720/liteos\_m/config.gni的内容如下: - - ``` - # Kernel type, e.g. "linux", "liteos_a", "liteos_m". - kernel_type = "liteos_m" - - # Kernel version. - kernel_version = "3.0.0" - - # Board CPU type, e.g. "cortex-a7", "riscv32". - board_cpu = "real-m300" - - # Board arch, e.g. "armv7-a", "rv32imac". - board_arch = "" - - # Toolchain name used for system compiling. - # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. - # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. - board_toolchain = "gcc-arm-none-eabi" - - # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. - board_toolchain_path = - rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", - root_build_dir) - - # Compiler prefix. - board_toolchain_prefix = "gcc-arm-none-eabi-" - - # Compiler type, "gcc" or "clang". - board_toolchain_type = "gcc" - - # Board related common compile flags. - board_cflags = [] - board_cxx_flags = [] - board_ld_flags = [] - ``` - -2. 开发板编译脚本。 - - 新增的开发板,对应目录下需要新增BUILD.gn文件作为开发板编译的总入口。以芯片解决方案厂商realtek的rtl8720开发板为例,对应的device/realtek/rtl8720/BUILD.gn为: - - ``` - group("rtl8720") { - ... - } - ``` - -3. 编译调试开发板。 - - 1. 任意目录执行hb set按提示设置源码路径和要编译的产品。 - - 2. 在开发板目录下执行hb build, 即可启动开发板的编译。 - -4. 编译调试产品 - - 将开发板和组件信息写入产品配置文件,该配置文件字段说明如下: - - - product\_name:产品名称,支持自定义,建议与vendor下的三级目录名称一致。 - - ohos\_version:OpenHarmony版本号,应与实际下载的版本一致。 - - device\_company:芯片解决方案厂商名称,建议与device的二级目录名称一致。 - - board:开发板名称,建议与device的三级级目录名称一致。 - - kernel\_type:内核类型,应与开发板支持的内核类型匹配。 - - kernel\_version:内核版本号,应与开发板支持的内核版本匹配。 - - subsystem:产品选择的子系统,应为OS支持的子系统,OS支持的子系统请见build/lite/components目录下的各子系统描述文件。 - - components:产品选择的某个子系统下的组件,应为某个子系统支持的组件,子系统支持的组件请见build/lite/components/子系统.json文件。 - - features:产品配置的某个组件的特性,组件支持的特性请见build/lite/components/子系统.json中对应组件的features字段。 - - 以基于“rtl8720“开发板的wifiiot模组为例,vendor/my\_company/wifiiot/config.json如下: - - ``` - { - "product_name": "wifiiot", # 产品名称 - "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 - "device_company": "realtek", # 芯片解决方案厂商名称 - "board": "rtl8720", # 开发板名称 - "kernel_type": "liteos_m", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "kernel", # 选择的子系统 - "components": [ - { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 - ] - }, - ... - { - 更多子系统和组件 - } - ] - } - ``` - +## 编译构建适配流程 + +首先,创建开发板目录,以芯片解决方案厂商realtek的rtl8720开发板为例,需创建device/realtek/rtl8720目录。编译相关的适配步骤如下: + +1. 编译工具链和编译选项配置。 + 构建系统默认使用ohos-clang编译工具链,也支持芯片解决方案厂商按开发板自定义配置。开发板编译配置文件编译相关的变量如下: + + - kernel_type: 开发板使用的内核类型,例如:"liteos_a", "liteos_m", "linux"。 + - kernel_version: 开发使用的内核版本,例如:"4.19"。 + - board_cpu: 开发板CPU类型,例如:"cortex-a7", "riscv32"。 + - board_arch: 开发芯片arch, 例如: "armv7-a", "rv32imac"。 + - board_toolchain: 开发板自定义的编译工具链名称,例如:"gcc-arm-none-eabi"。若为空,则使用默认为ohos-clang。 + - board_toolchain_prefix:编译工具链前缀,例如:"gcc-arm-none-eabi"。 + - board_toolchain_type:编译工具链类型,目前支持gcc和clang。例如:"gcc" ,"clang"。 + - board_cflags:开发板配置的c文件编译选项。 + - board_cxx_flags:开发板配置的cpp文件编译选项。 + - board_ld_flags:开发板配置的链接选项。 + 编译构建会按产品的选择的开发板,加载对应的config.gni,该文件中变量对系统组件全局可见。 + + 以芯片解决方案厂商realtek的rtl8720开发板为例,device/realtek/rtl8720/liteos_m/config.gni的内容如下: + + + ``` + # Kernel type, e.g. "linux", "liteos_a", "liteos_m". + kernel_type = "liteos_m" + + # Kernel version. + kernel_version = "3.0.0" + + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "real-m300" + + # Board arch, e.g. "armv7-a", "rv32imac". + board_arch = "" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "gcc-arm-none-eabi" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "gcc-arm-none-eabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [] + board_cxx_flags = [] + board_ld_flags = [] + ``` + +2. 开发板编译脚本。 + 新增的开发板,对应目录下需要新增BUILD.gn文件作为开发板编译的总入口。以芯片解决方案厂商realtek的rtl8720开发板为例,对应的device/realtek/rtl8720/BUILD.gn为: + + + ``` + group("rtl8720") { + ... + } + ``` + +3. 编译调试开发板。 + 1. 任意目录执行hb set按提示设置源码路径和要编译的产品。 + + 2. 在开发板目录下执行hb build, 即可启动开发板的编译。 + +4. 编译调试产品 + 将开发板和组件信息写入产品配置文件,该配置文件字段说明如下: + + - product_name:产品名称,支持自定义,建议与vendor下的三级目录名称一致。 + - ohos_version:OpenHarmony版本号,应与实际下载的版本一致。 + - device_company:芯片解决方案厂商名称,建议与device的二级目录名称一致。 + - board:开发板名称,建议与device的三级级目录名称一致。 + - kernel_type:内核类型,应与开发板支持的内核类型匹配。 + - kernel_version:内核版本号,应与开发板支持的内核版本匹配。 + - subsystem:产品选择的子系统,应为OS支持的子系统,OS支持的子系统请见build/lite/components目录下的各子系统描述文件。 + - components:产品选择的某个子系统下的组件,应为某个子系统支持的组件,子系统支持的组件请见build/lite/components/子系统.json文件。 + - features:产品配置的某个组件的特性,组件支持的特性请见build/lite/components/子系统.json中对应组件的features字段。 + + 以基于rtl8720开发板的wifiiot模组为例,vendor/my_company/wifiiot/config.json如下: + + + ``` + { + "product_name": "wifiiot", # 产品名称 + "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 + "device_company": "realtek", # 芯片解决方案厂商名称 + "board": "rtl8720", # 开发板名称 + "kernel_type": "liteos_m", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "kernel", # 选择的子系统 + "components": [ + { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 + ] + }, + ... + { + 更多子系统和组件 + } + ] + } + ``` diff --git a/zh-cn/device-dev/porting/porting-chip-prepare.md b/zh-cn/device-dev/porting/porting-chip-prepare.md index 64ee48b8940843e378cc2fd767f0206ae6a5d444..c42d1cc7b365edd9a4d75dbfcacef768d682bb4e 100644 --- a/zh-cn/device-dev/porting/porting-chip-prepare.md +++ b/zh-cn/device-dev/porting/porting-chip-prepare.md @@ -1,7 +1,7 @@ -# 移植准备 +# 移植准备 -- **[移植须知](oem_transplant_chip_prepare_knows.md)** -- **[编译构建适配流程](porting-chip-prepare-process.md)** +- **[移植须知](porting-chip-prepare-knows.md)** +- **[编译构建适配流程](porting-chip-prepare-process.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-linux-kernel.md b/zh-cn/device-dev/porting/porting-linux-kernel.md index f54b3a7b8d3ebb42b858459d7783f44e0423f85b..4d46702e6c156f6f7954c3c46125736de6802885 100644 --- a/zh-cn/device-dev/porting/porting-linux-kernel.md +++ b/zh-cn/device-dev/porting/porting-linux-kernel.md @@ -18,9 +18,9 @@ OpenHarmony = OpenHarmony内核态层 + OpenHarmony用户态层 -![zh-cn_image_0000001162805936](figure/zh-cn_image_0000001162805936.png) +![zh-cn_image_0000001167753296](figures/zh-cn_image_0000001167753296.png) -其中OpenHarmony内核态层就是上图的紫色部分,可以看到,它主要由内核本身(如Linux Kernel,LiteOS),和一些运行在内核态的一些特性组成,比如HDF等。 +其中OpenHarmony内核层就是上图的紫色部分,可以看到,它主要由内核本身(如Linux Kernel,LiteOS),和一些运行在内核态的一些特性组成,比如HDF等。 而OpenHarmony用户态层,在上图,就是紫色之外的部分。可以看到,由下往上看,它主要由系统服务层,框架层,应用层组成。在这儿我们将这三层整体称为“OpenHarmony用户态层”。 @@ -35,36 +35,38 @@ OpenHarmony = OpenHarmony内核态层 + OpenHarmony用户态层 OH内核态层 = OH Linux内核 + OH内核态特性(可选特性或者必选特性,如必选特性HDF,今后的可选特性HMDFS等) -而OH Linux内核 = 标准LTS Linux内核 + 三方SoC芯片平台代码 + OH内核态基础代码(支撑OH用户态层运行的最基础代码) +而OH Linux内核 = 标准LTS Linux 内核 + 三方SoC芯片平台代码 + OH内核态基础代码(支撑OH用户态层运行的最基础代码) -因此OH内核态层 = 标准LTS Linux内核 + 三方SoC芯片平台代码 + OH内核态基础代码 + OH内核态特性(如HDF,今后的HMDFS等) +因此OH内核态层 = 标准LTS Linux 内核 + 三方SoC芯片平台代码 + OH内核态基础代码 + OH内核态特性(如HDF) -![zh-cn_image_0000001208365855](figure/zh-cn_image_0000001208365855.png) +![zh-cn_image_0000001210623027](figures/zh-cn_image_0000001210623027.png) -而将前两项组合,标准LTS Linux 内核 + 三方SoC芯片平台代码,其实就是一个三方Linux内核的基础组成。从上面的推导可以看出,OpenHarmony内核态层其实能够由两种方法得到: +而将前两项组合,标准LTS Linux 内核 + 三方SoC芯片平台代码,其实就是一个三方Linux内核的基础组成。从上面的推导可以看出,OpenHarmony 内核态层其实能够由两种方法得到: -方法一:OH内核态层 = 三方Linux内核 + OH内核态基础代码 + OH内核态特性(如HDF,今后的HMDFS等) +方法一:OH 内核态层 = 三方Linux内核 + OH内核态基础代码 + OH内核态特性(如HDF,今后的HMDFS等) 也就是直接借助三方Linux内核,再加上基础OH内核态基础代码、以及HDF等OH内核态特性。 -方法二:OH内核态层 = OH Linux内核 + OH内核态特性(如HDF,今后的HMDFS等) +方法二:OH 内核态层 = OH Linux内核 + OH内核态特性(如HDF,今后的HMDFS等) -也就是直接采用OH Linux内核,然后再加入OH的其他内核态特性。 +也就是直接采用OHLinux内核,然后再加入OH的其他内核态特性。 -当前方法二中OH Linux内核支持的三方芯片平台还不够丰富。为了能够响应三方开发者快速移植OpenHarmony的要求,下文会着重介绍方法一,即借助三方已有的Linux内核,来快速移植OpenHarmony。 +当前方法二中OHLinux内核支持的三方芯片平台还不够丰富。为了能够响应三方开发者快速移植OpenHarmony的要求,下文会着重介绍方法一,即借助三方已有的Linux内核,来快速移植OpenHarmony。 -### 借助已有Linux内核来移植OpenHarmony的流程 +### **借助已有Linux内核来移植OpenHarmony的流程** 整个移植流程可以分为三步: + 1. 准备整体构建环境,包括将三方芯片平台的现有内核代码拷贝到OpenHarmony的整体编译环境下。 2. OpenHarmony内核态基础代码的移植。 3. OpenHarmony内核态必选特性(如HDF等)的移植。 + 详细步骤在接下来的章节中介绍。 @@ -73,12 +75,12 @@ OH内核态层 = OH Linux内核 + OH内核态特性(可选特性或者必选 下面以树莓派3b (BCM2837) 为例,演示将OpenHarmony移植到树莓派的过程。 -### 整体构建环境的准备 +### 准备整体构建环境 1. 将三方内核纳入OpenHarmony编译环境。 + 完整编译过一遍标准Hi3516DV300的内核之后,clone树莓派内核源码并复制到manifest输出目录下: - 完整编译过一遍标准Hi3516DV300内核之后,clone树莓派内核源码并复制到manifest输出目录下: - + ``` export PROJ_ROOT=[OpenHarmony manifest] git clone https://gitee.com/xfan1024/oh-rpi3b-kernel.git @@ -86,7 +88,8 @@ OH内核态层 = OH Linux内核 + OH内核态特性(可选特性或者必选 ``` 2. 配置树莓派内核编译环境。 - ```shell + + ``` # 进入树莓派kernel目录 cd out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b @@ -97,31 +100,32 @@ OH内核态层 = OH Linux内核 + OH内核态特性(可选特性或者必选 ``` 3. 注释掉clang不识别的flag。 - PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b/arch/arm/Makefile注释掉以下这一行: - ```makefile + + ``` KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog ``` -### 内核态基础代码的移植 +### 移植内核态基础代码 目前OpenHarmony内核态的基础代码,主要是日志服务相关。轻量化内核日志服务代码包含: + ``` drivers/staging/hilog drivers/staging/hievent ``` -将以上代码,从OpenHarmony内核代码目录kernel/linux/linux-4.19/drivers/staging中,拷贝到out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b/drivers/staging 下。 +将以上代码,从OpenHarmony内核代码目录kernel/linux/linux-4.19/drivers/staging中,拷贝到out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b/drivers/staging下。 在三方内核的drivers/staging/Kconfig文件内增加如下代码: + + ``` source "drivers/staging/hilog/Kconfig" - source "drivers/staging/hievent/Kconfig" - ``` 在内核config项中打开对应的CONFIG控制宏:CONFIG_HILOG和CONFIG_HIEVENT。 @@ -129,10 +133,9 @@ source "drivers/staging/hievent/Kconfig" 具体日志使用说明请参见:[Hilog_lite组件介绍](https://gitee.com/openharmony/hiviewdfx_hilog_lite/blob/master/README_zh.md)。 -### 内核态必选特性HDF的移植 +### 移植内核态必选特性HDF 1. 打HDF补丁。 - 在Linux内核打HDF补丁时,执行补丁shell脚本合入HDF补丁。 1. 配置HDF补丁脚本的三个变量参数。 @@ -141,26 +144,28 @@ source "drivers/staging/hievent/Kconfig" patch_hdf.sh脚本三个参数含义为:第一个入参为工程根目录路径,第二入参为内核目录路径,第三个入参为hdf补丁文件。 + ``` ./patch_hdf.sh [工程根目录路径] [内核目录路径] [hdf补丁文件] ``` 以树莓派3b为示例介绍: + ``` # 进入树莓派kernel目录 - $PROJ_ROOT/drivers/adapter/khdf/linux/patch_hdf.sh \ - $PROJ_ROOT # 指定工程根目录路径 \ - $PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b # 打补丁的内核目录路径 \ - $PROJ_ROOT/kernel/linux/patches/linux-4.19/hi3516dv300_patch/hdf.patch # HDF补丁文件 + PROJ_ROOT/drivers/adapter/khdf/linux/patch_hdf.sh \ + PROJ_ROOT # 指定工程根目录路径 \ + PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b # 打补丁的内核目录路径 \ + PROJ_ROOT/kernel/linux/patches/linux-4.19/hi3516dv300_patch/hdf.patch # HDF补丁文件 ``` 2. 配置config。 - 提供HDF基本配置,如果需要其他功能,通过menuconfig打开对应驱动开关即可。 HDF补丁执行成功后,默认HDF开关是关闭的,打开HDF基本配置选项如下: + ``` CONFIG_DRIVERS_HDF=y CONFIG_HDF_SUPPORT_LEVEL=2 @@ -174,8 +179,9 @@ source "drivers/staging/hievent/Kconfig" 或者通过menuconfig界面打开HDF相关配置,命令如下: + ``` - # 生成.config配置文件 + # 生成 .config 配置文件 make ${MAKE_OPTIONS} rpi3b_oh_defconfig # 更改HDF内核配置 @@ -184,13 +190,14 @@ source "drivers/staging/hievent/Kconfig" # [*] HDF driver framework support ---> ``` - 配置如下(在Device Drivers -> HDF driver framework support目录下): + 配置如下(在Device Drivers -> HDF driver framework support 目录下): - ![zh-cn_image_0000001208524821](figure/zh-cn_image_0000001208524821.png) + ![zh-cn_image_0000001208524821](figures/zh-cn_image_0000001208524821.png) ### 编译Image + ``` # 执行编译命令 make ${MAKE_OPTIONS} -j33 zImage @@ -209,7 +216,7 @@ HDF(Hardware Driver Foundation)自测试用例,用于测试HDF框架和外 **用例编译和测试方法** -通过[hdc_std工具](http://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md)把用例执行文件推送到设备中,然后执行用例即可,操作步骤如下: + 通过[hdc_std工具](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md)把用例执行文件推送到设备中,然后执行用例即可,操作步骤如下: 1. 编译hdf测试用例。 2. 用hdc_std工具推送测试文件到设备中。 @@ -219,36 +226,39 @@ HDF(Hardware Driver Foundation)自测试用例,用于测试HDF框架和外 用例编译和测试详细步骤如下: 1. 编译hdf测试用例。 - 编译hdf测试用例命令和文件路径如下: + ``` ./build.sh --product-name Hi3516DV300 --build-target hdf_test ``` 等待编译完成。 -2. 将测试文件移动到目标移植设备上(以树莓派为例) - - 方法一:使用[hdc_std工具](http://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md)。 +2. 将测试文件移动到目标移植设备上(以树莓派为例)。 + 方法一:使用[hdc_std工具](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md)。 1. 先在树莓派里新建data/test目录。 + ``` mkdir -p data/test ``` 2. 推送依赖库和测试用例到树莓派。 + ``` - hdc_std file send XXX\out\{device_name}\hdf\hdf\libhdf_test_common.z.so /system/lib - hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test - hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\devmgr\DevMgrTest /data/test - hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\osal\OsalTest /data/test - hdc_std file send XXX\out\{device_name}\tests\unittest\hdf\sbuf\SbufTest /data/test + hdc file send XXX\out\{device_name}\hdf\hdf\libhdf_test_common.z.so /system/lib + hdc file send XXX\out\{device_name}\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test + hdc file send XXX\out\{device_name}\tests\unittest\hdf\devmgr\DevMgrTest /data/test + hdc file send XXX\out\{device_name}\tests\unittest\hdf\osal\OsalTest /data/test + hdc file send XXX\out\{device_name}\tests\unittest\hdf\sbuf\SbufTest /data/test ``` + 方法二:移动到储存卡内,启动树莓派之后装载。 1. 拔掉树莓派连接电脑的串口、USB线,然后拔下数据卡。 2. 将数据卡插入到电脑的读取口,将编译好的zImage和测试文件夹test/下载到电脑,然后移动到数据卡的根目录下。zImage文件会被替换,请提前做好备份。 3. 最后将数据卡插回树莓派。 + ``` # 让树莓派文件系统读取储存卡根目录 mount -t vfat /dev/block/mmcblk0p1 /boot @@ -263,23 +273,26 @@ HDF(Hardware Driver Foundation)自测试用例,用于测试HDF框架和外 3. 执行测试 1. 进入目录执行测试文件目录data/test。 + ``` cd /data/test ``` 2. 修改文件执行权限。 + ``` chmod 777 hdf_adapter_uhdf_test_config DevMgrTest OsalTest SbufTest ``` 3. 开始测试。 + ``` ./hdf_adapter_uhdf_test_config ./DevMgrTest ./OsalTest ./SbufTest ``` - 4. 如果所有测试文件输出均显示PASSED,那么HDF功能即安装成功。 - - 示例:DevMgrTest用例成功结果显示: + 4. 如果所有测试文件输出均显示 PASSED,那么HDF功能即安装成功。 + 示例:DevMgrTest用例成功结果显示: + ``` ./DevMgrTest Running main() from gmock_main.cc diff --git a/zh-cn/device-dev/porting/porting-minichip.md b/zh-cn/device-dev/porting/porting-minichip.md index cbd7bbcbda08bc96e2a9b18a8d628426544e38d9..dffdc34ed908cec087f8be7e8785a25defd0a500 100644 --- a/zh-cn/device-dev/porting/porting-minichip.md +++ b/zh-cn/device-dev/porting/porting-minichip.md @@ -1,11 +1,11 @@ -# 轻量系统芯片移植指导 +# 轻量系统芯片移植指导 -- **[移植准备](porting-chip-prepare.md)** -- **[内核移植](porting-chip-kernel.md)** -- **[板级系统移植](porting-chip-board.md)** +- **[移植准备](porting-chip-prepare.md)** -- **[常见问题](porting-chip-faqs.md)** +- **[内核移植](porting-chip-kernel.md)** +- **[板级系统移植](porting-chip-board.md)** +- **[常见问题](porting-chip-faqs.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-smallchip-driver-oom.md b/zh-cn/device-dev/porting/porting-smallchip-driver-oom.md index 1f8e6c641f0bb24bfcd7f4a3ab854d4f491b788b..87e13beb2a901e1d771a592163b6d245dc400d67 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-driver-oom.md +++ b/zh-cn/device-dev/porting/porting-smallchip-driver-oom.md @@ -1,390 +1,265 @@ -# 器件驱动移植 +# 器件驱动移植 -- [LCD驱动移植](#section1574513454119) -- [TP驱动移植](#section20284142116422) -- [WLAN驱动移植](#section0969448164217) 本章节讲解如何移植各类器件驱动。 -## LCD驱动移植 + +## LCD驱动移植 移植LCD驱动的主要工作是编写一个驱动,在驱动中生成模型的实例,并完成注册。 这些LCD的驱动被放置在源码目录//drivers/framework/model/display/driver/panel中。 -1. 创建Panel驱动 - - 创建HDF驱动,在驱动初始化中调用RegisterPanel接口注册模型实例。如: - - ``` - int32_t LCDxxEntryInit(struct HdfDeviceObject *object) - { - struct PanelData *panel = CreateYourPanel(); - // 注册模型实例 - if (RegisterPanel(panel) != HDF_SUCCESS) { - HDF_LOGE("%s: RegisterPanel failed", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - - struct HdfDriverEntry g_xxxxDevEntry = { - .moduleVersion = 1, - .moduleName = "LCD_XXXX", - .Init = LCDxxEntryInit, - }; - - HDF_INIT(g_xxxxDevEntry); - ``` - -2. 配置加载panel驱动 - - 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在display的host中,名为device\_lcd的device中增加配置。 - - >![](../public_sys-resources/icon-caution.gif) **注意:** - >moduleName 要与panel驱动中的moduleName相同。 - - ``` - root { - ... - display :: host { - device_lcd :: device { - deviceN :: deviceNode { - policy = 0; - priority = 100; - preload = 2; - moduleName = "LCD_XXXX"; - } - } - } - } - ``` - - -## TP驱动移植 +1. 创建Panel驱动 + 创建HDF驱动,在驱动初始化中调用RegisterPanel接口注册模型实例。如: + + + ``` + int32_t LCDxxEntryInit(struct HdfDeviceObject *object) + { + struct PanelData *panel = CreateYourPanel(); + // 注册模型实例 + if (RegisterPanel(panel) != HDF_SUCCESS) { + HDF_LOGE("%s: RegisterPanel failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_xxxxDevEntry = { + .moduleVersion = 1, + .moduleName = "LCD_XXXX", + .Init = LCDxxEntryInit, + }; + + HDF_INIT(g_xxxxDevEntry); + ``` + +2. 配置加载panel驱动 + 产品的所有设备信息被定义在源码文件//vendor/vendor_name/product_name/config/device_info/device_info.hcs中。修改该文件,在display的host中,名为device_lcd的device中增加配置。 + + > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** + > moduleName 要与panel驱动中的moduleName相同。 + + + ``` + root { + ... + display :: host { + device_lcd :: device { + deviceN :: deviceNode { + policy = 0; + priority = 100; + preload = 2; + moduleName = "LCD_XXXX"; + } + } + } + } + ``` + + +## TP驱动移植 本节描述如何移植触摸屏驱动。触摸屏的器件驱动被放置在源码目录//drivers/framework/model/input/driver/touchscreen中。 移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。 -详细的驱动开发指导,请参考 [TOUCHSCREEN开发指导](../driver/driver-peripherals-touch-des.md)。 - -1. 创建触摸屏器件驱动 - - 在上述touchscreen目录中创建名为touch\_ic\_name.c的文件。编写如下内容 - - ``` - #include "hdf_touch.h" - - static int32_t HdfXXXXChipInit(struct HdfDeviceObject *device) - { - ChipDevice *tpImpl = CreateXXXXTpImpl(); - if(RegisterChipDevice(tpImpl) != HDF_SUCCESS) { // 注册ChipDevice模型 - ReleaseXXXXTpImpl(tpImpl); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - - struct HdfDriverEntry g_touchXXXXChipEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH_XXXX", // 注意这里的moduleName要与后续的配置完全一致 - .Init = HdfXXXXChipInit, - }; - - HDF_INIT(g_touchXXXXChipEntry); - ``` - - 其中ChipDevice中要实现如下方法: - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

实现说明

-

int32_t (*Init)(ChipDevice *device)

-

实现器件初始化

-

int32_t (*Detect)(ChipDevice *device)

-

实现器件探测

-

int32_t (*Suspend)(ChipDevice *device)

-

实现器件休眠

-

int32_t (*Resume)(ChipDevice *device)

-

实现器件唤醒

-

int32_t (*DataHandle)(ChipDevice *device)

-

需要实现从器件读取数据,将触摸点数据填写入device->driver->frameData中

-

int32_t (*UpdateFirmware)(ChipDevice *device)

-

实现固件升级

-
- -2. 配置产品,加载器件驱动 - - 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在名为input的host中,名为device\_touch\_chip的device中增加配置。 - - >![](../public_sys-resources/icon-note.gif) **说明:** - >moduleName 要与触摸屏驱动中的moduleName相同。 - - ``` - deviceN :: deviceNode { - policy = 0; - priority = 130; - preload = 0; - permission = 0660; - moduleName = "HDF_TOUCH_XXXX"; - deviceMatchAttr = "touch_XXXX_configs"; - } - ``` - - -## WLAN驱动移植 +详细的驱动开发指导,请参考 [TOUCHSCREEN开发指导](../driver/driver-peripherals-touch-des.md)。 + +1. 创建触摸屏器件驱动 + 在上述touchscreen目录中创建名为touch_ic_name.c的文件。编写如下内容 + + + ``` + #include "hdf_touch.h" + + static int32_t HdfXXXXChipInit(struct HdfDeviceObject *device) + { + ChipDevice *tpImpl = CreateXXXXTpImpl(); + if(RegisterChipDevice(tpImpl) != HDF_SUCCESS) { // 注册ChipDevice模型 + ReleaseXXXXTpImpl(tpImpl); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_touchXXXXChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_XXXX", // 注意这里的moduleName要与后续的配置完全一致 + .Init = HdfXXXXChipInit, + }; + + HDF_INIT(g_touchXXXXChipEntry); + ``` + + 其中ChipDevice中要实现如下方法: + + | 方法 | 实现说明 | + | -------- | -------- | + | int32_t (\*Init)(ChipDevice \*device) | 实现器件初始化 | + | int32_t (\*Detect)(ChipDevice \*device) | 实现器件探测 | + | int32_t (\*Suspend)(ChipDevice \*device) | 实现器件休眠 | + | int32_t (\*Resume)(ChipDevice \*device) | 实现器件唤醒 | + | int32_t (\*DataHandle)(ChipDevice \*device) | 需要实现从器件读取数据,将触摸点数据填写入device->driver->frameData中 | + | int32_t (\*UpdateFirmware)(ChipDevice \*device) | 实现固件升级 | + +2. 配置产品,加载器件驱动 + 产品的所有设备信息被定义在源码文件//vendor/vendor_name/product_name/config/device_info/device_info.hcs中。修改该文件,在名为input的host中,名为device_touch_chip的device中增加配置。 + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > moduleName 要与触摸屏驱动中的moduleName相同。 + + + ``` + deviceN :: deviceNode { + policy = 0; + priority = 130; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH_XXXX"; + deviceMatchAttr = "touch_XXXX_configs"; + } + ``` + + +## WLAN驱动移植 WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负责处理WLAN流量。 -**图 1** OpenHarmony WLAN结构示意图 - - -![](figure/HDF_WIFI.png) + **图1** OpenHarmony WLAN结构示意图 + ![zh-cn_image_0000001207756867](figures/zh-cn_image_0000001207756867.png) 如图1,左半部分负责管理WLAN设备,右半部分负责WLAN流量。HDF WLAN分别为这两部分做了抽象,驱动的移植过程可以看做分别实现这两部分所需接口。这些接口有: - - - - - - - - - - - - - - - - - - - -

接口

-

定义头文件

-

接口说明

-

HdfChipDriverFactory

-

drivers\framework\include\wifi\hdf_wlan_chipdriver_manager.h

-

ChipDriver的Factory,用于支持一个芯片多个WLAN端口

-

HdfChipDriver

-

drivers\framework\include\wifi\wifi_module.h

-

每个WLAN端口对应一个HdfChipDriver,用来管理一个特定端口

-

NetDeviceInterFace

-

drivers\framework\include\wifi\net_device.h

-

与协议栈之间的接口,如发送数据、设置网络接口状态等

-
- ->![](../public_sys-resources/icon-note.gif) **说明:** ->详细的接口开发指导,请参考[WLAN开发](../driver/driver-peripherals-external-des.md)。 + | 接口 | 定义头文件 | 接口说明 | +| -------- | -------- | -------- | +| HdfChipDriverFactory | drivers\framework\include\wifi\hdf_wlan_chipdriver_manager.h | ChipDriver的Factory,用于支持一个芯片多个WLAN端口 | +| HdfChipDriver | drivers\framework\include\wifi\wifi_module.h | 每个WLAN端口对应一个HdfChipDriver,用来管理一个特定端口 | +| NetDeviceInterFace | drivers\framework\include\wifi\net_device.h | 与协议栈之间的接口,如发送数据、设置网络接口状态等 | -具体的移植步骤如下: - -1. 创建HDF WLAN 芯片驱动 - - 在目录/device/vendor\_name/peripheral/wifi/chip\_name/ 创建文件 hdf\_wlan\_chip\_name.c。内容模板如下: - - ``` - static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) { - static struct HdfChipDriverFactory factory = CreateChipDriverFactory(); // 需要移植者实现的方法 - struct HdfChipDriverManager *driverMgr = HdfWlanGetChipDriverMgr(); - if (driverMgr->RegChipDriver(&factory) != HDF_SUCCESS) { // 注册驱动工厂 - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - - struct HdfDriverEntry g_hdfXXXChipEntry = { - .moduleVersion = 1, - .Init = HdfWlanXXXChipDriverInit, - .Release = HdfWlanXXXChipRelease, - .moduleName = "HDF_WIFI_CHIP_XXX" // 注意:这个名字要与配置一致 - }; - - HDF_INIT(g_hdfXXXChipEntry); - ``` - - 在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口

-

说明

-

const char *driverName

-

当前driverName

-

int32_t (*InitChip)(struct HdfWlanDevice *device)

-

初始化芯片

-

int32_t (*DeinitChip)(struct HdfWlanDevice *device)

-

去初始化芯片

-

void (*ReleaseFactory)(struct HdfChipDriverFactory *factory)

-

释放HdfChipDriverFactory对象

-

struct HdfChipDriver *(*Build)(struct HdfWlanDevice *device, uint8_t ifIndex)

-

创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号

-

void (*Release)(struct HdfChipDriver *chipDriver)

-

释放chipDriver

-

uint8_t (*GetMaxIFCount)(struct HdfChipDriverFactory *factory)

-

获取当前芯片支持的最大接口数

-
- - 其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver 。该对象需要提供方法: - - - - - - - - - - - - - - - - - - - - - - -

接口

-

说明

-

int32_t (*init)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

-

初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace

-

int32_t (*deinit)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

-

去初始化当前网络接口

-

struct HdfMac80211BaseOps *ops

-

WLAN基础能力接口集

-

struct HdfMac80211STAOps *staOps

-

支持STA模式所需的接口集

-

struct HdfMac80211APOps *apOps

-

支持AP模式所需要的接口集

-
- -2. 编写配置文件描述驱动支持的芯片 - - 在产品配置目录下创建芯片的配置文件,保存至源码路径//vendor/vendor\_name/product\_name/config/wifi/wlan\_chip\_chip\_name.hcs - - 该文件模板如下: - - ``` - root { - wlan_config { - chip_name :& chipList { - chip_name :: chipInst { - match_attr = "hdf_wlan_chips_chip_name"; /* 这是配置匹配属性,用于提供驱动的配置根 */ - driverName = "driverName"; /* 需要与HdfChipDriverFactory中的driverName相同*/ - sdio { - vendorId = 0xXXXX; /* your vendor id */ - deviceId = [0xXXXX]; /*your supported devices */ - } - } - } - } - } - ``` - - >![](../public_sys-resources/icon-note.gif) **说明:** - >路径和文件中的vendor\_name、product\_name、chip\_name请替换成实际名称 - >vendorId 和 deviceId需要根据实际芯片的识别码进行填写。 - -3. 编写配置文件,加载驱动 - - 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在名为network的host中,名为device\_wlan\_chips的device中增加配置。模板如下: - - ``` - deviceN :: deviceNode { - policy = 0; - preload = 2; - moduleName = "HDF_WLAN_CHIPS"; - deviceMatchAttr = "hdf_wlan_chips_chip_name"; - serviceName = "driverName"; - } - ``` - - >![](../public_sys-resources/icon-note.gif) **说明:** - >moduleName 要与HDF WLAN 芯片驱动中的moduleName相同。 - -4. 修改Kconfig文件,让移植的WLAN模组出现再内核配置中 - - 在device/vendor\_name/drivers/Kconfig中增加配置菜单,模板如下 - - ``` - config DRIVERS_HDF_WIFI_chip_name - bool "Enable chip_name Host driver" - default n - depends on DRIVERS_HDF_WLAN help - Answer Y to enable chip_name Host driver. - ``` - - >![](../public_sys-resources/icon-note.gif) **说明:** - >请替换模板中的chip\_name为实际的芯片名称 - -5. 修改构建脚本,让驱动参与内核构建 - - 在源码文件//device/vendor\_name/drivers/lite.mk末尾追加如下内容 - - ``` - ifeq ($(LOSCFG_DRIVERS_HDF_WIFI_chip_name), y) - # 构建完成要链接一个叫hdf_wlan_chipdriver_chip_name的对象,建议按这个命名,防止冲突 - LITEOS_BASELIB += -lhdf_wlan_chipdriver_chip_name - # 增加构建目录gpio - LIB_SUBDIRS += ../peripheral/wifi/chip_name - endif - ``` - - >![](../public_sys-resources/icon-note.gif) **说明:** - >请替换模板中的chip\_name为实际的芯片名称 +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 详细的接口开发指导,请参考[WLAN开发](../driver/driver-peripherals-external-des.md)。 +具体的移植步骤如下: +1. 创建HDF WLAN 芯片驱动 + 在目录/device/vendor_name/peripheral/wifi/chip_name/ 创建文件 hdf_wlan_chip_name.c。内容模板如下: + + + ``` + static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) { + static struct HdfChipDriverFactory factory = CreateChipDriverFactory(); // 需要移植者实现的方法 + struct HdfChipDriverManager *driverMgr = HdfWlanGetChipDriverMgr(); + if (driverMgr->RegChipDriver(&factory) != HDF_SUCCESS) { // 注册驱动工厂 + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_hdfXXXChipEntry = { + .moduleVersion = 1, + .Init = HdfWlanXXXChipDriverInit, + .Release = HdfWlanXXXChipRelease, + .moduleName = "HDF_WIFI_CHIP_XXX" // 注意:这个名字要与配置一致 + }; + + HDF_INIT(g_hdfXXXChipEntry); + ``` + + 在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法 + + | 接口 | 说明 | + | -------- | -------- | + | const char \*driverName | 当前driverName | + | int32_t (\*InitChip)(struct HdfWlanDevice \*device) | 初始化芯片 | + | int32_t (\*DeinitChip)(struct HdfWlanDevice \*device) | 去初始化芯片 | + | void (\*ReleaseFactory)(struct HdfChipDriverFactory \*factory) | 释放HdfChipDriverFactory对象 | + | struct HdfChipDriver \*(\*Build)(struct HdfWlanDevice \*device, uint8_t ifIndex) | 创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号 | + | void (\*Release)(struct HdfChipDriver \*chipDriver) | 释放chipDriver | + | uint8_t (\*GetMaxIFCount)(struct HdfChipDriverFactory \*factory) | 获取当前芯片支持的最大接口数 | + + 其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver 。该对象需要提供方法: + + | 接口 | 说明 | + | -------- | -------- | + | int32_t (\*init)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | 初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace | + | int32_t (\*deinit)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | 去初始化当前网络接口 | + | struct HdfMac80211BaseOps \*ops | WLAN基础能力接口集 | + | struct HdfMac80211STAOps \*staOps | 支持STA模式所需的接口集 | + | struct HdfMac80211APOps \*apOps | 支持AP模式所需要的接口集 | + +2. 编写配置文件描述驱动支持的芯片 + 在产品配置目录下创建芯片的配置文件,保存至源码路径//vendor/vendor_name/product_name/config/wifi/wlan_chip_chip_name.hcs + + 该文件模板如下: + + + ``` + root { + wlan_config { + chip_name :& chipList { + chip_name :: chipInst { + match_attr = "hdf_wlan_chips_chip_name"; /* 这是配置匹配属性,用于提供驱动的配置根 */ + driverName = "driverName"; /* 需要与HdfChipDriverFactory中的driverName相同*/ + sdio { + vendorId = 0xXXXX; /* your vendor id */ + deviceId = [0xXXXX]; /*your supported devices */ + } + } + } + } + } + ``` + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 路径和文件中的vendor_name、product_name、chip_name请替换成实际名称 + > + > vendorId 和 deviceId需要根据实际芯片的识别码进行填写。 + +3. 编写配置文件,加载驱动 + 产品的所有设备信息被定义在源码文件//vendor/vendor_name/product_name/config/device_info/device_info.hcs中。修改该文件,在名为network的host中,名为device_wlan_chips的device中增加配置。模板如下: + + + ``` + deviceN :: deviceNode { + policy = 0; + preload = 2; + moduleName = "HDF_WLAN_CHIPS"; + deviceMatchAttr = "hdf_wlan_chips_chip_name"; + serviceName = "driverName"; + } + ``` + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > moduleName 要与HDF WLAN 芯片驱动中的moduleName相同。 + +4. 修改Kconfig文件,让移植的WLAN模组出现再内核配置中 + 在device/vendor_name/drivers/Kconfig中增加配置菜单,模板如下 + + + ``` + config DRIVERS_HDF_WIFI_chip_name + bool "Enable chip_name Host driver" + default n + depends on DRIVERS_HDF_WLAN help + Answer Y to enable chip_name Host driver. + ``` + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 请替换模板中的chip_name为实际的芯片名称 + +5. 修改构建脚本,让驱动参与内核构建 + 在源码文件//device/vendor_name/drivers/lite.mk末尾追加如下内容 + + + ``` + ifeq ($(LOSCFG_DRIVERS_HDF_WIFI_chip_name), y) + # 构建完成要链接一个叫hdf_wlan_chipdriver_chip_name的对象,建议按这个命名,防止冲突 + LITEOS_BASELIB += -lhdf_wlan_chipdriver_chip_name + # 增加构建目录gpio + LIB_SUBDIRS += ../peripheral/wifi/chip_name + endif + ``` + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 请替换模板中的chip_name为实际的芯片名称 diff --git a/zh-cn/device-dev/porting/porting-smallchip-driver-overview.md b/zh-cn/device-dev/porting/porting-smallchip-driver-overview.md index bd131e478628429fa97a91a2b855ba48dc7c03f9..17a39ef50a78d17a917fab86b643f968516224e9 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-driver-overview.md +++ b/zh-cn/device-dev/porting/porting-smallchip-driver-overview.md @@ -1,9 +1,12 @@ -# 移植概述 +# 移植概述 + 驱动主要包含两部分,平台驱动和器件驱动。平台驱动主要包括通常在SOC内的GPIO、I2C、SPI等;器件驱动则主要包含通常在SOC外的器件,如 LCD、TP、WLAN等 -**图 1** OpenHarmony 驱动分类 -![](figure/OpenHarmony-驱动分类.png "OpenHarmony-驱动分类") -HDF驱动被设计为可以跨OS使用的驱动程序,HDF驱动框架会为驱动达成这个目标提供有力的支撑。开发HDF驱动中,请尽可能只使用HDF驱动框架提供的接口,否则会导致驱动丧失跨OS使用的特性。在开始驱动开发前,建议先了解[HDF驱动框架](../driver/driver-hdf-overview.md)。 + **图1** OpenHarmony 驱动分类 + + ![zh-cn_image_0000001207599659](figures/zh-cn_image_0000001207599659.png) + +HDF驱动被设计为可以跨OS使用的驱动程序,HDF驱动框架会为驱动达成这个目标提供有力的支撑。开发HDF驱动中,请尽可能只使用HDF驱动框架提供的接口,否则会导致驱动丧失跨OS使用的特性。在开始驱动开发前,建议先了解[HDF驱动框架](../driver/driver-hdf-overview.md)。 diff --git a/zh-cn/device-dev/porting/porting-smallchip-driver-plat.md b/zh-cn/device-dev/porting/porting-smallchip-driver-plat.md index a28bc2faf3fae4cb54a85094e10a185d20b34041..d30d6c469b472703847e4bda2a8e0bd7f10f9795 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-driver-plat.md +++ b/zh-cn/device-dev/porting/porting-smallchip-driver-plat.md @@ -1,9 +1,13 @@ -# 平台驱动移植 +# 平台驱动移植 + + +在这一步,我们会在源码目录//device/vendor_name/soc_name/drivers 目录下创建平台驱动,如果你要移植的SOC的厂商还没有创建仓库的话,请联系[sig-devboard](https://gitee.com/openharmony/community/blob/master/sig/sig-devboard/sig_devboard_cn.md)创建。 -在这一步,我们会在源码目录//device/vendor\_name/soc\_name/drivers 目录下创建平台驱动,如果你要移植的SOC的厂商还没有创建仓库的话,请联系[sig-devboard](https://gitee.com/openharmony/community/blob/master/sig/sig-devboard/sig_devboard_cn.md)创建。 建议的目录结构: + + ``` device ├── vendor_name @@ -29,137 +33,141 @@ device │ ├── board_name ``` + + HDF为所有的平台驱动都创建了驱动模型,移植平台驱动的主要工作是向模型注入实例。 这些模型你可以在源码目录//drivers/framework/support/platform/include中找到定义。 + 本节我们会以GPIO为例,讲解如何移植平台驱动,移植过程包含以下步骤: -1. 创建GPIO驱动 - - 在源码目录//device/vendor\_name/soc\_name/drivers/gpio中创建文件soc\_name\_gpio.c 内容模板如下: - - ``` - #include "gpio_core.h" - - // 定义GPIO结构体,如果需要的话 - struct SocNameGpioCntlr { - struct GpioCntlr cntlr; // 这是HDF GPIO驱动框架需要的结构体 - int myData; // 以下是当前驱动自身需要的 - }; - - // Bind 方法在HDF驱动中主要用户对外发布服务,这里我们不需要,直接返回成功即可 - static int32_t GpioBind(struct HdfDeviceObject *device) - { - (void)device; - return HDF_SUCCESS; - } - - // Init方法时驱动初始化的入口,我们需要在Init方法中完成模型实例的注册 - static int32_t GpioInit(struct HdfDeviceObject *device) - { - SocNameGpioCntlr *impl = CreateGpio(); // 你的创建代码 - ret = GpioCntlrAdd(&impl->cntlr); // 注册GPIO模型实例 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: err add controller:%d", __func__, ret); - return ret; - } - return HDF_SUCCESS; - } - - // Release方法会在驱动卸载时被调用,这里主要完成资源回收 - static void GpioRelease(struct HdfDeviceObject *device) - { - // GpioCntlrFromDevice 方法能从抽象的设备对象中获得init方法注册进去的模型实例。 - struct GpioCntlr *cntlr = GpioCntlrFromDevice(device); - //资源释放... - } - - struct HdfDriverEntry g_gpioDriverEntry = { - .moduleVersion = 1, - .Bind = GpioBind, - .Init = GpioInit, - .Release = GpioRelease, - .moduleName = "SOC_NAME_gpio_driver", // 这个名字我们稍后会在配置文件中用到,用来加载驱动。 - }; - HDF_INIT(g_gpioDriverEntry); // 注册一个GPIO的驱动入口 - ``` - -2. 创建厂商驱动构建入口 - - 如前所述device/vendor\_name/drivers/lite.mk是厂商驱动的构建的入口。我们需要从这个入口开始,进行构建 - - ``` - #文件device/vendor_name/drivers/lite.mk - - SOC_VENDOR_NAME := $(subst $/",,$(LOSCFG_DEVICE_COMPANY)) - SOC_NAME := $(subst $/",,$(LOSCFG_PLATFORM)) - BOARD_NAME := $(subst $/",,$(LOSCFG_PRODUCT_NAME)) - - # 指定SOC进行构建 - LIB_SUBDIRS += $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ - ``` - -3. 创建SOC驱动构建入口 - - ``` - #文件device/vendor_name/soc_name/drivers/lite.mk - - SOC_DRIVER_ROOT := $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ - - # 判断如果打开了GPIO的内核编译开关 - ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO), y) - # 构建完成要链接一个叫hdf_gpio的对象 - LITEOS_BASELIB += -lhdf_gpio - # 增加构建目录gpio - LIB_SUBDIRS += $(SOC_DRIVER_ROOT)/gpio - endif - - # 后续其他驱动在此基础上追加 - ``` - -4. 创建GPIO构建入口 - - ``` - include $(LITEOSTOPDIR)/config.mk - include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk - - # 指定输出对象的名称,注意要与SOC驱动构建入口里的LITEOS_BASELIB 保持一致 - MODULE_NAME := hdf_gpio - - # 增加HDF框架的INCLUDE - LOCAL_CFLAGS += $(HDF_INCLUDE) - - # 要编译的文件 - LOCAL_SRCS += soc_name_gpio.c - - # 编译参数 - LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char -fno-strict-aliasing -fno-common - - include $(HDF_DRIVER) - ``` - -5. 配置产品加载驱动 - - 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。 - - 平台驱动请添加到platform的host中。 - - >![](../public_sys-resources/icon-note.gif) **说明:** - >moduleName要与驱动定义中的相同。 - - ``` - root { - ... - platform :: host { - device_gpio :: device { - device0 :: deviceNode { - policy = 0; - priority = 10; - permission = 0644; - moduleName = "SOC_NAME_gpio_driver"; - } - } - } - } - ``` +1. 创建GPIO驱动 + 在源码目录//device/vendor_name/soc_name/drivers/gpio中创建文件soc_name_gpio.c 内容模板如下: + + + ``` + #include "gpio_core.h" + + // 定义GPIO结构体,如果需要的话 + struct SocNameGpioCntlr { + struct GpioCntlr cntlr; // 这是HDF GPIO驱动框架需要的结构体 + int myData; // 以下是当前驱动自身需要的 + }; + + // Bind 方法在HDF驱动中主要用户对外发布服务,这里我们不需要,直接返回成功即可 + static int32_t GpioBind(struct HdfDeviceObject *device) + { + (void)device; + return HDF_SUCCESS; + } + + // Init方法时驱动初始化的入口,我们需要在Init方法中完成模型实例的注册 + static int32_t GpioInit(struct HdfDeviceObject *device) + { + SocNameGpioCntlr *impl = CreateGpio(); // 你的创建代码 + ret = GpioCntlrAdd(&impl->cntlr); // 注册GPIO模型实例 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: err add controller:%d", __func__, ret); + return ret; + } + return HDF_SUCCESS; + } + + // Release方法会在驱动卸载时被调用,这里主要完成资源回收 + static void GpioRelease(struct HdfDeviceObject *device) + { + // GpioCntlrFromDevice 方法能从抽象的设备对象中获得init方法注册进去的模型实例。 + struct GpioCntlr *cntlr = GpioCntlrFromDevice(device); + //资源释放... + } + + struct HdfDriverEntry g_gpioDriverEntry = { + .moduleVersion = 1, + .Bind = GpioBind, + .Init = GpioInit, + .Release = GpioRelease, + .moduleName = "SOC_NAME_gpio_driver", // 这个名字我们稍后会在配置文件中用到,用来加载驱动。 + }; + HDF_INIT(g_gpioDriverEntry); // 注册一个GPIO的驱动入口 + ``` + +2. 创建厂商驱动构建入口 + 如前所述device/vendor_name/drivers/lite.mk是厂商驱动的构建的入口。我们需要从这个入口开始,进行构建 + + + ``` + #文件device/vendor_name/drivers/lite.mk + + SOC_VENDOR_NAME := $(subst $/",,$(LOSCFG_DEVICE_COMPANY)) + SOC_NAME := $(subst $/",,$(LOSCFG_PLATFORM)) + BOARD_NAME := $(subst $/",,$(LOSCFG_PRODUCT_NAME)) + + # 指定SOC进行构建 + LIB_SUBDIRS += $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ + ``` + +3. 创建SOC驱动构建入口 + + ``` + #文件device/vendor_name/soc_name/drivers/lite.mk + + SOC_DRIVER_ROOT := $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ + + # 判断如果打开了GPIO的内核编译开关 + ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO), y) + # 构建完成要链接一个叫hdf_gpio的对象 + LITEOS_BASELIB += -lhdf_gpio + # 增加构建目录gpio + LIB_SUBDIRS += $(SOC_DRIVER_ROOT)/gpio + endif + + # 后续其他驱动在此基础上追加 + ``` + +4. 创建GPIO构建入口 + + + ``` + include $(LITEOSTOPDIR)/config.mk + include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk + + # 指定输出对象的名称,注意要与SOC驱动构建入口里的LITEOS_BASELIB 保持一致 + MODULE_NAME := hdf_gpio + + # 增加HDF框架的INCLUDE + LOCAL_CFLAGS += $(HDF_INCLUDE) + + # 要编译的文件 + LOCAL_SRCS += soc_name_gpio.c + + # 编译参数 + LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char -fno-strict-aliasing -fno-common + + include $(HDF_DRIVER) + ``` + +5. 配置产品加载驱动 + 产品的所有设备信息被定义在源码文件//vendor/vendor_name/product_name/config/device_info/device_info.hcs中。 + + 平台驱动请添加到platform的host中。 + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > moduleName要与驱动定义中的相同。 + + + ``` + root { + ... + platform :: host { + device_gpio :: device { + device0 :: deviceNode { + policy = 0; + priority = 10; + permission = 0644; + moduleName = "SOC_NAME_gpio_driver"; + } + } + } + } + ``` diff --git a/zh-cn/device-dev/porting/porting-smallchip-driver.md b/zh-cn/device-dev/porting/porting-smallchip-driver.md index 5b2a0921c904135c90d0decda6f55b96a8737b81..92e81567ebe4bcf261b66e5f86866a0013deacad 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-driver.md +++ b/zh-cn/device-dev/porting/porting-smallchip-driver.md @@ -1,9 +1,9 @@ -# 驱动移植 +# 驱动移植 -- **[移植概述](porting-smallchip-driver-overview.md)** -- **[平台驱动移植](porting-smallchip-driver-plat.md)** -- **[器件驱动移植](porting-smallchip-driver-oom.md)** +- **[移植概述](porting-smallchip-driver-overview.md)** +- **[平台驱动移植](porting-smallchip-driver-plat.md)** +- **[器件驱动移植](porting-smallchip-driver-oom.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-smallchip-kernel-a.md b/zh-cn/device-dev/porting/porting-smallchip-kernel-a.md index 80e20305dc85fee55e5a9c9661688bb89b42b89b..b0097516f6ff76c0c302e262cf52d8fae5e42bfa 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-kernel-a.md +++ b/zh-cn/device-dev/porting/porting-smallchip-kernel-a.md @@ -1,222 +1,112 @@ -# LiteOS-A内核 +# LiteOS-A内核 -- [移植概述](#section14876256185510) - - [移植场景](#section1986014410569) - - [目录规范](#section10916181716564) -- [基础适配](#section814974018565) - - [编程样例](#section10854481825) +## 移植概述 -- [验证](#section646410453212) -## 移植概述 - -### 移植场景 +### 移植场景 LiteOS-A当前支持ARMv7-a指令集架构,如果三方芯片为ARMv7-a架构,可以进行内核基础适配;否则还需要先根据芯片的架构来新增内核对该芯片架构的支持,这个工作较为复杂,不在这篇文章范围内。 -### 目录规范 + +### 目录规范 LiteOS-A目录规范参考[LiteOS-A 简介](https://gitee.com/openharmony/kernel_liteos_a)。 -## 基础适配 + +## 基础适配 LiteOS-A提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数。 + 如下图所示,LiteOS-A的初始化流程主要包含以下七步: -1. 新增target\_config.h文件,并且编写单板内存相关的配置宏DDR\_MEM\_ADDR和DDR\_MEM\_SIZE,分别表示内存起始地址和内存的长度,预链接脚本board.ld.S会根据这两个宏进行展开生成链接脚本board.ld。 -2. 新增定义MMU映射全局数组\(g\_archMmuInitMapping\),指定各个内存段属性及虚实映射关系,内核启动阶段根据该表建立内存映射关系。 -3. 如果是多核,需要新增定义从核操作函数句柄\(struct SmpOps\),其中SmpOps-\>SmpCpuOn函数需要实现唤醒从核的功能;接着定义SmpRegFunc函数,调用LOS\_SmpOpsSet接口进行句柄注册;最后通过启动框架完成注册过程,即LOS\_MODULE\_INIT\(SmpRegFunc, LOS\_INIT\_LEVEL\_EARLIEST\)。 -4. 链接阶段根据链接脚本board.ld生成内核镜像。 -5. 单核CPU镜像运行入口为汇编文件reset\_vector\_up.S,多核CPU的入口为reset\_vector\_mp.S,在汇编文件中进行中断向量表初始化、MMU页表初始化等操作。 -6. reset\_vector.S汇编代码最终会跳转到C语言的main函数,进行硬件时钟、软件定时器、内存和任务等初始化,这个过程会依赖target\_config.h的特性宏配置,最后会创建SystemInit任务,并且开启任务调度OsSchedStart\(\)。 -7. SystemInit任务在单板代码中实现,其中调用DeviceManagerStart函数进行HDF驱动初始化,这个过程会调用单板代码中的驱动配置文件hdf.hcs以及drivers源码实现 -整体启动流程如下图所示: +1. 新增target_config.h文件,并且编写单板内存相关的配置宏DDR_MEM_ADDR和DDR_MEM_SIZE,分别表示内存起始地址和内存的长度,预链接脚本board.ld.S会根据这两个宏进行展开生成链接脚本board.ld。 + +2. 新增定义MMU映射全局数组(g_archMmuInitMapping),指定各个内存段属性及虚实映射关系,内核启动阶段根据该表建立内存映射关系。 + +3. 如果是多核,需要新增定义从核操作函数句柄(struct SmpOps),其中SmpOps->SmpCpuOn函数需要实现唤醒从核的功能;接着定义SmpRegFunc函数,调用LOS_SmpOpsSet接口进行句柄注册;最后通过启动框架完成注册过程,即LOS_MODULE_INIT(SmpRegFunc, LOS_INIT_LEVEL_EARLIEST)。 + +4. 链接阶段根据链接脚本board.ld生成内核镜像。 + +5. 单核CPU镜像运行入口为汇编文件reset_vector_up.S,多核CPU的入口为reset_vector_mp.S,在汇编文件中进行中断向量表初始化、MMU页表初始化等操作。 + +6. reset_vector.S汇编代码最终会跳转到C语言的main函数,进行硬件时钟、软件定时器、内存和任务等初始化,这个过程会依赖target_config.h的特性宏配置,最后会创建SystemInit任务,并且开启任务调度OsSchedStart()。 + +7. SystemInit任务在单板代码中实现,其中调用DeviceManagerStart函数进行HDF驱动初始化,这个过程会调用单板代码中的驱动配置文件hdf.hcs以及drivers源码实现 + + + 整体启动流程如下图所示: + + **图1** 整体启动流程 + + ![zh-cn_image_0000001154212518](figures/zh-cn_image_0000001154212518.png) -**图 1** 整体启动流程 -![](figure/整体启动流程.png "整体启动流程") 从图1中可以看到,内核基础适配需要单板进行适配的代码包含三部分: -- 新增target\_config.h文件,其中新增单板硬件配置参数和特性开关的配置参数,具体说明如下: - - **表 1** target\_config.h配置项说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

配置项

-

说明

-

OS_SYS_CLOCK

-

系统cycle的频率

-

DDR_MEM_ADDR

-

系统内存的起始地址

-

DDR_MEM_SIZE

-

系统内存的大小

-

PERIPH_PMM_BASE

-

外设寄存器的起始地址

-

PERIPH_PMM_SIZE

-

外设寄存器的长度大小

-

OS_HWI_MIN

-

系统中断最小值

-

OS_HWI_MAX

-

系统中断最大值

-

NUM_HAL_INTERRUPT_UART0

-

UART0中断号

-

UART0_REG_BASE

-

UART0寄存器基址

-

GIC_BASE_ADDR

-

GIC中断寄存器基址

-

GICD_OFFSET

-

GICD相对GIC基址的偏移地址

-

GICC_OFFSET

-

GICC相对GIC基址的偏移地址

-
- -- SystemInit函数用于单板用户态业务初始化,典型的初始化场景如图2所示: - - **图 2** 业务启动流程 - ![](figure/业务启动流程.png "业务启动流程") - -- main函数用于内核基础初始化和单板内核态业务初始化,流程如下图3所示,整体由内核启动框架主导初始化流程,图中浅蓝色部分为启动框架中可接受外部模块注册启动的阶段。 - - >![](../public_sys-resources/icon-caution.gif) **注意:** - >同一层级内的模块不能有依赖关系。 - - **图 3** 内核启动框架 - ![](figure/内核启动框架.jpg "内核启动框架") - - **表 2** 启动框架层级 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

层级

-

说明

-

LOS_INIT_LEVEL_EARLIEST

-

最早期初始化

-

说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化

-

例如:Trace模块

-

LOS_INIT_LEVEL_ARCH_EARLY

-

架构早期初始化

-

说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层

-

LOS_INIT_LEVEL_PLATFORM_EARLY

-

平台早期初始化

-

说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层

-

例如:uart模块

-

LOS_INIT_LEVEL_KMOD_PREVM

-

内存初始化前的内核模块初始化

-

说明:在内存初始化之前需要使能的模块初始化

-

LOS_INIT_LEVEL_VM_COMPLETE

-

基础内存就绪后的初始化

-

说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化

-

例如:共享内存功能

-

LOS_INIT_LEVEL_ARCH

-

架构后期初始化

-

说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化

-

LOS_INIT_LEVEL_PLATFORM

-

平台后期初始化

-

说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化

-

例如:驱动内核抽象层初始化(mmc、mtd)

-

LOS_INIT_LEVEL_KMOD_BASIC

-

内核基础模块初始化

-

说明:内核可拆卸的基础模块初始化

-

例如:VFS初始化

-

LOS_INIT_LEVEL_KMOD_EXTENDED

-

内核扩展模块初始化

-

说明:内核可拆卸的扩展模块初始化

-

例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化

-

LOS_INIT_LEVEL_KMOD_TASK

-

内核任务创建

-

说明:进行内核任务的创建(内核线程,软件定时器任务)

-

例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建

-
- - 进行单板移植适配,推荐关注LOS\_INIT\_LEVEL\_ARCH至LOS\_INIT\_LEVEL\_KMOD\_TASK之间的层级,且尽可能拆分初始化行为进行细化阶段注册。 - - >![](../public_sys-resources/icon-note.gif) **说明:** - >启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。 - >可通过查看系统编译生成文件OHOS\_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。 - - -### 编程样例 - -在单板SDK文件中 +- 新增target_config.h文件,其中新增单板硬件配置参数和特性开关的配置参数,具体说明如下: + + **表1** target_config.h配置项说明 + + | 配置项 | 说明 | + | -------- | -------- | + | OS_SYS_CLOCK | 系统cycle的频率 | + | DDR_MEM_ADDR | 系统内存的起始地址 | + | DDR_MEM_SIZE | 系统内存的大小 | + | PERIPH_PMM_BASE | 外设寄存器的起始地址 | + | PERIPH_PMM_SIZE | 外设寄存器的长度大小 | + | OS_HWI_MIN | 系统中断最小值 | + | OS_HWI_MAX | 系统中断最大值 | + | NUM_HAL_INTERRUPT_UART0 | UART0中断号 | + | UART0_REG_BASE | UART0寄存器基址 | + | GIC_BASE_ADDR | GIC中断寄存器基址 | + | GICD_OFFSET | GICD相对GIC基址的偏移地址 | + | GICC_OFFSET | GICC相对GIC基址的偏移地址 | + +- SystemInit函数用于单板用户态业务初始化,典型的初始化场景如图2所示: + + **图2** 业务启动流程 + + ![zh-cn_image_0000001200252103](figures/zh-cn_image_0000001200252103.png) + +- main函数用于内核基础初始化和单板内核态业务初始化,流程如下图3所示,整体由内核启动框架主导初始化流程,图中浅蓝色部分为启动框架中可接受外部模块注册启动的阶段。 + > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** + > 同一层级内的模块不能有依赖关系。 + + **图3** 内核启动框架 + + ![zh-cn_image_0000001173764984](figures/zh-cn_image_0000001173764984.jpg) + + **表2** 启动框架层级 + + | 层级 | 说明 | + | -------- | -------- | + | LOS_INIT_LEVEL_EARLIEST | 最早期初始化
说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化
例如:Trace模块 | + | LOS_INIT_LEVEL_ARCH_EARLY | 架构早期初始化
说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层 | + | LOS_INIT_LEVEL_PLATFORM_EARLY | 平台早期初始化
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层
例如:uart模块 | + | LOS_INIT_LEVEL_KMOD_PREVM | 内存初始化前的内核模块初始化
说明:在内存初始化之前需要使能的模块初始化 | + | LOS_INIT_LEVEL_VM_COMPLETE | 基础内存就绪后的初始化
说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化
例如:共享内存功能 | + | LOS_INIT_LEVEL_ARCH | 架构后期初始化
说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化 | + | LOS_INIT_LEVEL_PLATFORM | 平台后期初始化
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化
例如:驱动内核抽象层初始化(mmc、mtd) | + | LOS_INIT_LEVEL_KMOD_BASIC | 内核基础模块初始化
说明:内核可拆卸的基础模块初始化
例如:VFS初始化 | + | LOS_INIT_LEVEL_KMOD_EXTENDED | 内核扩展模块初始化
说明:内核可拆卸的扩展模块初始化
例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化 | + | LOS_INIT_LEVEL_KMOD_TASK | 内核任务创建
说明:进行内核任务的创建(内核线程,软件定时器任务)
例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建 | + + 进行单板移植适配,推荐关注LOS_INIT_LEVEL_ARCH至LOS_INIT_LEVEL_KMOD_TASK之间的层级,且尽可能拆分初始化行为进行细化阶段注册。 + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。 + > + > 可通过查看系统编译生成文件OHOS_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。 + + +### 编程样例 + + 在单板SDK文件中 + ``` /* 内核启动框架头文件 */ #include "los_init.h" @@ -233,8 +123,10 @@ unsigned int OsSampleModInit(void) LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED); ``` -## 验证 +## 验证 + + ``` main core booting up... OsSampleModInit SUCCESS! @@ -247,9 +139,10 @@ cpu 0 entering scheduler 系统启动完毕后进入内核态shell,能够运行task命令能够正常显示即可。 + ``` OHOS # help -*******************shell commands:************************* +***shell commands:* arp cat cd chgrp chmod chown cp cpup date dhclient dmesg dns format free help hwi @@ -260,4 +153,3 @@ su swtmr sync systeminfo task telnet uname v2p virstatfs vmm watch writeproc ``` - diff --git a/zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md b/zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md index f4d1407168d076a462d30aa14c42529f944458da..87af95951ca85767253b2e7be0000cd010cb77e1 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md +++ b/zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md @@ -1,118 +1,101 @@ -# Linux内核 +# Linux内核 -- [移植概述](#section6282121355111) - - [基本信息](#section19589322515) - - [Bootloader](#section19062510518) -- [适配编译和烧录启动](#section11112101695215) -- [验证](#section17318153325311) - -## 移植概述 +## 移植概述 Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后,进行基础的内核编译构建及验证。 -### 基本信息 - -当前Linux内核基线是基于Linux社区 4.19 LTS版本演进,合入CVE及bugfix补丁。具体信息参考[代码库](https://gitee.com/openharmony/kernel_linux),对应repo工程代码路径为kernel/linux-4.19。 -### Bootloader +### 基本信息 -可以使用芯片厂商自带的Bootloader,或者是开源Uboot等加载内核镜像。比如为支持Hi3516DV300开发板,OpenHarmony引入的开源[Uboot](https://gitee.com/openharmony/device_hisilicon_third_party_uboot)。 +当前Linux内核基线是基于Linux社区 4.19 LTS版本演进,合入CVE及bugfix补丁。具体信息参考[代码库](https://gitee.com/openharmony/kernel_linux),对应repo工程代码路径为kernel/linux-4.19。 -## 适配编译和烧录启动 -1. 准备内核config(特别是芯片相关的config)。 +### Bootloader - config文件所在源码目录:kernel/linux/config/ +可以使用芯片厂商自带的Bootloader,或者是开源Uboot等加载内核镜像。比如为支持Hi3516DV300开发板,OpenHarmony引入的开源[Uboot](https://gitee.com/openharmony/device_hisilicon_third_party_uboot)。 - 以hi3516dv300芯片为例,可在对应的linux-4.19/arch/arm/configs/目录下新建\_small\_defconfig,如hi3516dv300\_small\_defconfig表示针对hi3516dv300小型系统的defconfig。该config文件可以由基础defconfig文件small\_common\_defconfig与该芯片相关的config组合生成。 -2. 准备芯片补丁。 +## 适配编译和烧录启动 - 补丁文件所在源码目录:kernel/linux/patches/linux-4.19 +1. 准备内核config(特别是芯片相关的config)。 + config文件所在源码目录:kernel/linux/config/ - 以hi3516dv300芯片为例,参考已有的patch目录hi3516dv300\_small\_patch目录,新建\_patch目录,放置相关芯片补丁,注意hdf.patch等驱动补丁。 + 以hi3516dv300芯片为例,可在对应的linux-4.19/arch/arm/configs/目录下新建<YOUR_CHIP>_small_defconfig,如hi3516dv300_small_defconfig表示针对hi3516dv300小型系统的defconfig。该config文件可以由基础defconfig文件small_common_defconfig与该芯片相关的config组合生成。 -3. 编译。 +2. 准备芯片补丁。 + 补丁文件所在源码目录:kernel/linux/patches/linux-4.19 - 具体内核编译入口脚本位于工程目录kernel/linux/patches/下面,版本级整编命令会通过BUILD.gn进入kernel\_module\_build.sh和kernel.mk,需要在这2个文件中针对性进行patch及defconfig文件路径、编译器、芯片架构、内核Image格式等的适配。 + 以hi3516dv300芯片为例,参考已有的patch目录hi3516dv300_small_patch目录,新建<YOUR_CHIP>_patch目录,放置相关芯片补丁,注意hdf.patch等驱动补丁。 - 通过编译错误日志调整补丁,典型错误场景: +3. 编译。 + 具体内核编译入口脚本位于工程目录kernel/linux/patches/下面,版本级整编命令会通过BUILD.gn进入kernel_module_build.sh和kernel.mk,需要在这2个文件中针对性进行patch及defconfig文件路径、编译器、芯片架构、内核Image格式等的适配。 - (1)补丁合入失败,出现冲突,需要进行上下文适配修改。 + 通过编译错误日志调整补丁,典型错误场景: - (2)编译失败,内核版本差异(函数实现调整等)需要针对性进行内核适配。 + (1)补丁合入失败,出现冲突,需要进行上下文适配修改。 - >![](../public_sys-resources/icon-caution.gif) **注意:** - >- 参考kernel.mk,在OpenHarmony工程的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 - >- 对应拷贝后的目录位于: out/<\*\*\*\>/kernel/linux-4.19,可以在该目录下进行补丁的修改适配。 + (2)编译失败,内核版本差异(函数实现调整等)需要针对性进行内核适配。 -4. 烧录启动。 + > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** + > - 参考kernel.mk,在OpenHarmony工程的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 + > + > - 对应拷贝后的目录位于: out/<\*\*\*>/kernel/linux-4.19,可以在该目录下进行补丁的修改适配。 - 由于不同芯片的开发板的烧录方式不一样,此处不表述具体的烧录方式。需要注意烧录的各镜像的大小及启动参数的配置,参考hi3516dv300采用uboot启动参数: +4. 烧录启动。 + 由于不同芯片的开发板的烧录方式不一样,此处不表述具体的烧录方式。需要注意烧录的各镜像的大小及启动参数的配置,参考hi3516dv300采用uboot启动参数: - ``` - setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 ro rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M(boot),9M(kernel),50M(rootfs),50M(userfs)' - ``` + + ``` + setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 ro rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M(boot),9M(kernel),50M(rootfs),50M(userfs)' + ``` -## 验证 +## 验证 调试init进程、启动shell和运行简单的用户态程序,验证内核移植是否成功。OpenHarmony[小型系统](../quick-start/quickstart-lite-overview.md)的OS镜像结构以及linux用户态的启动流程如下图1所示: -**图 1** 基于linux内核的OS镜像结构和用户态程序启动流程 -![](figure/基于linux内核的OS镜像结构和用户态程序启动流程.png "基于linux内核的OS镜像结构和用户态程序启动流程") + **图1** 基于linux内核的OS镜像结构和用户态程序启动流程 + ![zh-cn_image_0000001154372318](figures/zh-cn_image_0000001154372318.png) 基于上述流程,推荐按以下步骤完成验证: -1. 制作根文件系统镜像。 - - 请参考[新建芯片解决方案和产品解决方案](../subsystems/subsys-build-mini-lite.md)生成根文件系统镜像rootfs.img。从上图可以看到启动过程与产品配置强相关,在制作rootfs.img过程中请完成如下四种配置: - - - 组件配置 - - 产品组件配置文件vendor/\{company\}/\{product\}/config.json需配置启动恢复子系统\(startup\)的init\_lite组件和内核子系统的linux\_4\_1\_9组件。 - - - 系统服务配置 - - 系统服务配置文件vendor/\{company\}/\{product\}/init\_configs/init\_xxx.cfg需要启动shell服务。 - - - 文件系统配置 - - 文件系统配置vendor/\{company\}/\{product\}/fs.yml中需要创建“/bin/sh -\> mksh“和“/lib/ld-musl-arm.so.1 -\> libc.so“软连接,这两个文件分别是shell可执行程序和可执行程序依赖的c库。 - - - 启动配置 - - 启动配置在vendor/\{company\}/\{product\}/init\_configs/etc目录下,包括fstab、rsS和Sxxx文件,请按开发板实际情况配置。 - - 编译完成后,可通过检查产品编译输出目录下的rootfs内容,确认rootfs.img文件生成是否符合预期。 - -2. 调试init进程和shell。 - - 烧录rootfs.img并调试init进程和shell,不同厂商的开发板的烧录工具和流程可能不同,请按芯片解决方案提供的流程进行烧录。烧录rootfs.img前请确认bootloader和linux内核启动正常。如果rootfs.img被内核正常挂载,接着将运行/bin/init程序,init进程为用户态的第一个应用程序,它的运行意味着用户态的开始。 - - init程序首先会调用/etc/init.d/rcS脚本,rcS脚本执行第一条命令为"/bin/mount -a”,该命令会加载fstab文件,在fstab中的命令执行完后rcS将顺序调用Sxxx脚本完成设备节点创建和扫描、文件权限配置等操作。 +1. 制作根文件系统镜像。 + 请参考[新建芯片解决方案和产品解决方案](../subsystems/subsys-build-mini-lite.md)生成根文件系统镜像rootfs.img。从上图可以看到启动过程与产品配置强相关,在制作rootfs.img过程中请完成如下四种配置: - 最后,init程序会读取init.cfg系统服务配置文件。根据步骤1中的设置,init程序将会启动shell。如果上述流程运行正常,系统则会进入shell。 + - 组件配置 + 产品组件配置文件vendor/{company}/{product}/config.json需配置启动恢复子系统(startup)的init_lite组件和内核子系统的linux_4_1_9组件。 + - 系统服务配置 + 系统服务配置文件vendor/{company}/{product}/init_configs/init_xxx.cfg需要启动shell服务。 + - 文件系统配置 + 文件系统配置vendor/{company}/{product}/fs.yml中需要创建“/bin/sh -> mksh“和“/lib/ld-musl-arm.so.1 -> libc.so“软连接,这两个文件分别是shell可执行程序和可执行程序依赖的c库。 + - 启动配置 + 启动配置在vendor/{company}/{product}/init_configs/etc目录下,包括fstab、rsS和Sxxx文件,请按开发板实际情况配置。 - 若串口有如下版本号日志打印,则表示init程序启动正常: + 编译完成后,可通过检查产品编译输出目录下的rootfs内容,确认rootfs.img文件生成是否符合预期。 - **图 2** init启动正常日志 - ![](figure/init启动正常日志.png "init启动正常日志") +2. 调试init进程和shell。 + 烧录rootfs.img并调试init进程和shell,不同厂商的开发板的烧录工具和流程可能不同,请按芯片解决方案提供的流程进行烧录。烧录rootfs.img前请确认bootloader和linux内核启动正常。如果rootfs.img被内核正常挂载,接着将运行/bin/init程序,init进程为用户态的第一个应用程序,它的运行意味着用户态的开始。 - 正常进入shell后执行ls命令,串口打印信息如下图: + init程序首先会调用/etc/init.d/rcS脚本,rcS脚本执行第一条命令为"/bin/mount -a”,该命令会加载fstab文件,在fstab中的命令执行完后rcS将顺序调用Sxxx脚本完成设备节点创建和扫描、文件权限配置等操作。 - **图 3** 正常进入shell后输入ls命令串口打印 - ![](figure/正常进入shell后输入ls命令串口打印.png "正常进入shell后输入ls命令串口打印") + 最后,init程序会读取init.cfg系统服务配置文件。根据步骤1中的设置,init程序将会启动shell。如果上述流程运行正常,系统则会进入shell。 -3. 配置NFS。 + 若串口有如下版本号日志打印,则表示init程序启动正常: - init进程和shell正常启动后,以服务端IP为192.168.1.22、客户端IP为192.168.1.4为例,可在根目录执行如下命令开启NFS: + **图2** init启动正常日志 + ![zh-cn_image_0000001154212516](figures/zh-cn_image_0000001154212516.png) - ``` - ifconfig eth0 192.168.1.4 netmask 255.255.255.0 - mkdir -p /storgage/nfs - mount -t nfs -o nolock,addr=192.168.1.22 192.168.1.22:/nfs /storage/nfs - ``` + 正常进入shell后执行ls命令,串口打印信息如下图: + **图3** 正常进入shell后输入ls命令串口打印 + ![zh-cn_image_0000001200171991](figures/zh-cn_image_0000001200171991.png) +3. 配置NFS。 + init进程和shell正常启动后,以服务端IP为192.168.1.22、客户端IP为192.168.1.4为例,可在根目录执行如下命令开启NFS: + + ``` + ifconfig eth0 192.168.1.4 netmask 255.255.255.0 + mkdir -p /storgage/nfs + mount -t nfs -o nolock,addr=192.168.1.22 192.168.1.22:/nfs /storage/nfs + ``` diff --git a/zh-cn/device-dev/porting/porting-smallchip-kernel.md b/zh-cn/device-dev/porting/porting-smallchip-kernel.md index 2d13c4839377e4a433c3efb6cd1a446e3f780074..60f2ce0f2c3a7acf68a15f33a403f4bb1a9bea5f 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-kernel.md +++ b/zh-cn/device-dev/porting/porting-smallchip-kernel.md @@ -1,7 +1,7 @@ -# 移植内核 +# 移植内核 -- **[LiteOS-A内核](porting-smallchip-kernel-a.md)** -- **[Linux内核](porting-smallchip-kernel-linux.md)** +- **[LiteOS-A内核](porting-smallchip-kernel-a.md)** +- **[Linux内核](porting-smallchip-kernel-linux.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-smallchip-prepare-building.md b/zh-cn/device-dev/porting/porting-smallchip-prepare-building.md index 15adc37f7525d8167aa00896d658a9427dca0dcd..9fe8e43aff7baef85f9054fd49f5899d17c0a351 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-prepare-building.md +++ b/zh-cn/device-dev/porting/porting-smallchip-prepare-building.md @@ -1,142 +1,140 @@ -# 编译构建 +# 编译构建 -- [编译环境搭建](#section3336103410314) -- [编译构建系统介绍](#section354343816319) -- [新建芯片解决方案](#section18612153175011) +## 编译环境搭建 -## 编译环境搭建 +首先请搭建OpenHarmony基础环境,步骤请参考轻量和小型系统入门[安装Hi3861开发板环境](../quick-start/quickstart-lite-steps-hi3861-setting.md)。用户态和LiteOS-A的内核态编译均使用llvm编译器编译,安装方法在搭建基础环境中已提供。若选择移植linux内核,请执行如下命令安装gcc-arm-linux-gnueabi交叉编译工具链,用于编译linux内核态镜像: -首先请搭建OpenHarmony基础环境,步骤请参考轻量和小型系统入门[linux环境搭建](../quick-start/quickstart-lite-package-environment.md)。用户态和LiteOS-A的内核态编译均使用llvm编译器编译,安装方法在搭建基础环境中已提供。若选择移植linux内核,请执行如下命令安装gcc-arm-linux-gnueabi交叉编译工具链,用于编译linux内核态镜像: ``` sudo apt-get install gcc-arm-linux-gnueabi ``` -## 编译构建系统介绍 -编译构建流程、编译脚本编写、目录规则、独立编译单个组件、独立编译芯片解决方案等介绍请见[编译构建子系统介绍](../subsystems/subsys-build-mini-lite.md)。 +## 编译构建系统介绍 -## 新建芯片解决方案 +编译构建流程、编译脚本编写、目录规则、独立编译单个组件、独立编译芯片解决方案等介绍请见[编译构建子系统介绍](../subsystems/subsys-build-mini-lite.md)。 -了解编译框架和搭建完编译环境后,请参考如下步骤新建芯片解决方案: -1. 新建目录 - - 芯片解决方案的目录规则为:device/\{芯片解决方案厂商\}/\{开发板\}。以海思的hispark\_taurus开发板为例,在代码根目录执行如下命令建立目录: - - ``` - mkdir -p device/hisilicon/hispark_taurus - ``` - - 芯片解决方案目录树的规则如下: - - ``` - device - └── company # 芯片解决方案厂商 - └── board # 开发板名称 - ├── BUILD.gn # 编译脚本 - ├── hals # OS南向接口适配 - ├── linux # 可选,linux内核版本 - │ └── config.gni # linux版本编译配置 - └── liteos_a # 可选,liteos内核版本 - └── config.gni # liteos_a版本编译配置 - ``` - - 以hispark\_taurus移植linux内核为例,目录树应该如下: - - ``` - device - └── hisilicon - └── hispark_tautus - ├── BUILD.gn - ├── hals - ├── ...... - └── linux - └── config.gni - ``` - - 目录树建立后开发板相关的源码放到hispark\_taurus目录下。 - -2. 配置开发板编译选项 - - [步骤1](#li20894101862)中的config.gni可配置开发板相关的编译选项,编译构建框架将会遵照该配置文件中的参数编译所有用户态OS组件。其中关键的字段说明如下: - - ``` - kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 - kernel_version: 开发板使用的内核版本,例如:“4.19”。 - board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 - board_arch: 开发板芯片arch, 例如: “armv7-a”, “rv32imac”。 - board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 - board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 - board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 - board_cflags: 开发板配置的c文件编译选项。 - board_cxx_flags: 开发板配置的cpp文件编译选项。 - board_ld_flags: 开发板配置的链接选项。 - ``` - - 还以海思的hispark\_taurus开发板为例,对应的device/hisilicon/hispark\_taurus/config.gni内容如下: - - ``` - # Board CPU type, e.g. "cortex-a7", "riscv32". - board_cpu = "cortex-a7" - - # Toolchain name used for system compiling. - # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. - # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. - board_toolchain = "mips-linux-gnu-gcc" - - # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. - board_toolchain_path = - rebase_path("//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/bin", - root_build_dir) - - # Compiler prefix. - board_toolchain_prefix = "arm-linux-ohoseabi-" - - # Compiler type, "gcc" or "clang". - board_toolchain_type = "gcc" - - # Board related common compile flags. - board_cflags = [ - ] - board_cxx_flags = [ - ] - board_ld_flags = [] - - # Board related headfiles search path. - board_include_dirs = [] - board_include_dirs += [ rebase_path( - "//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/target/usr/include", - root_build_dir) ] - - # Board adapter dir for OHOS components. - board_adapter_dir = "" - - # Sysroot path. - board_configed_sysroot = "" - - # Board storage type, it used for file system generation. - storage_type = "emmc" - ``` - -3. 编写开发板编译脚本 - - 步骤1中的BUILD.gn为新增的开发板的编译入口,主要用于编译开发板相关的代码,主要为设备侧驱动、设备侧接口适配\(媒体,图形等\)和开发板的SDK等等。 - - 海思的hispark\_taurus开发板的device/hisilicon/hispark\_taurus/BUILD.gn可写成: - - ``` - # group名称建议与开发板名称一致 - group("hispark_taurus") { - deps = [ "//kernel/linux/patches:linux_kernel" ] # 拉起内核编译 - deps += [ - ...... # 开发板其他编译单元 - ] - } - ``` - -4. 编译调试 - - 在开发板目录下执行hb set和hb build即可启动芯片解决方案的编译,编译框架会以开发板下的BUILD.gn为入口启动编译。 +## 新建芯片解决方案 +了解编译框架和搭建完编译环境后,请参考如下步骤新建芯片解决方案: +1. 新建目录 + 芯片解决方案的目录规则为:device/{芯片解决方案厂商}/{开发板}。以海思的hispark_taurus开发板为例,在代码根目录执行如下命令建立目录: + + + ``` + mkdir -p device/hisilicon/hispark_taurus + ``` + + 芯片解决方案目录树的规则如下: + + + ``` + device + └── company # 芯片解决方案厂商 + └── board # 开发板名称 + ├── BUILD.gn # 编译脚本 + ├── hals # OS南向接口适配 + ├── linux # 可选,linux内核版本 + │ └── config.gni # linux版本编译配置 + └── liteos_a # 可选,liteos内核版本 + └── config.gni # liteos_a版本编译配置 + ``` + + 以hispark_taurus移植linux内核为例,目录树应该如下: + + + ``` + device + └── hisilicon + └── hispark_taurus + ├── BUILD.gn + ├── hals + ├── ...... + └── linux + └── config.gni + ``` + + 目录树建立后开发板相关的源码放到hispark_taurus目录下。 + +2. 配置开发板编译选项 + 步骤1中的config.gni可配置开发板相关的编译选项,编译构建框架将会遵照该配置文件中的参数编译所有用户态OS组件。其中关键的字段说明如下: + + + ``` + kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 + kernel_version: 开发板使用的内核版本,例如:“4.19”。 + board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 + board_arch: 开发板芯片arch, 例如: “armv7-a”, “rv32imac”。 + board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 + board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 + board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 + board_cflags: 开发板配置的c文件编译选项。 + board_cxx_flags: 开发板配置的cpp文件编译选项。 + board_ld_flags: 开发板配置的链接选项。 + ``` + + 还以海思的hispark_taurus开发板为例,对应的device/hisilicon/hispark_taurus/config.gni内容如下: + + ``` + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "cortex-a7" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "mips-linux-gnu-gcc" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "arm-linux-ohoseabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [ + ] + board_cxx_flags = [ + ] + board_ld_flags = [] + + # Board related headfiles search path. + board_include_dirs = [] + board_include_dirs += [ rebase_path( + "//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/target/usr/include", + root_build_dir) ] + + # Board adapter dir for OHOS components. + board_adapter_dir = "" + + # Sysroot path. + board_configed_sysroot = "" + + # Board storage type, it used for file system generation. + storage_type = "emmc" + ``` + +3. 编写开发板编译脚本 + 步骤1中的BUILD.gn为新增的开发板的编译入口,主要用于编译开发板相关的代码,主要为设备侧驱动、设备侧接口适配(媒体,图形等)和开发板的SDK等等。 + + 海思的hispark_taurus开发板的device/hisilicon/hispark_taurus/BUILD.gn可写成: + + + ``` + # group名称建议与开发板名称一致 + group("hispark_taurus") { + deps = [ "//kernel/linux/patches:linux_kernel" ] # 拉起内核编译 + deps += [ + ...... # 开发板其他编译单元 + ] + } + ``` + +4. 编译调试 + 在开发板目录下执行hb set和hb build即可启动芯片解决方案的编译,编译框架会以开发板下的BUILD.gn为入口启动编译。 diff --git a/zh-cn/device-dev/porting/porting-smallchip-prepare-needs.md b/zh-cn/device-dev/porting/porting-smallchip-prepare-needs.md index 0217107b8523b98e36f72b89fe9a98f79fd528fd..b8bcb956d8ccc29e138fde8784604b89caa9159b 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-prepare-needs.md +++ b/zh-cn/device-dev/porting/porting-smallchip-prepare-needs.md @@ -1,98 +1,23 @@ -# 移植须知 +# 移植须知 + 本文详细介绍如何将OpenHarmony[小型系统](../quick-start/quickstart-lite-overview.md)的linux和LiteOS-A内核移植到新的开发板上,要求读者具有一定的嵌入式系统开发经验。建议先查看[入门指导](../../OpenHarmony-Overview_zh.md),以了解OpenHarmony软件架构、目录结构、内核子系统和驱动子系统相关知识。当前小型系统已适配的开发板如下表所示: -**表 1** OpenHarmony小型系统已适配的开发板 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

开发板

-

内核

-

arch

-

ROM

-

RAM

-

文件系统

-

Flash 类型

-

hispark_taurus

-

LiteOS-A和linux-4.19

-

ARM cortex-a7

-

8G

-

1GB

-

VFAT、EXT4

-

eMMC4.5

-

hispark_aries

-

LiteOS-A

-

ARM cortex-a7

-

16M

-

512M

-

JFFS2

-

SPI NOR

-
+ **表1** OpenHarmony小型系统已适配的开发板 + +| 开发板 | 内核 | arch | ROM | RAM | 文件系统 | Flash 类型 | +| -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| hispark_taurus | LiteOS-A和linux-4.19 | ARM cortex-a7 | 8G | 1GB | VFAT、EXT4 | eMMC4.5 | +| hispark_aries | LiteOS-A | ARM cortex-a7 | 16M | 512M | JFFS2 | SPI NOR | + 表1中的开发板可作为待移植开发板的参考,当前LiteOS-A和linux-4.19支持的arch、ROM占用、支持的文件系统和支持的Flash类型如下表所示: -**表 2** OpenHarmony小型系统内核移植信息表 - - - - - - - - - - - - - - - - - - - - - -

内核

-

支持的arch

-

ROM

-

文件系统

-

Flash类型

-

LiteOS-A

-

ARMv7

-

> 2M

-

VFAT、JFFS2、YAFFS2

-

SPI NOR、NAND、EMMC

-

linux-4.19

-

ARM, ARM64、 MIPS、 X86等

-

> 5M

-

VFAT、JFFS2、YAFFS、EXT/2/3/4、NFS等等

-

NOR、NAND、EMMC等

-
+ **表2** OpenHarmony小型系统内核移植信息表 +| 内核 | 支持的arch | ROM | 文件系统 | Flash类型 | +| -------- | -------- | -------- | -------- | -------- | +| LiteOS-A | ARMv7 | > 2M | VFAT、JFFS2、YAFFS2 | SPI NOR、NAND、EMMC | +| linux-4.19 | ARM, ARM64、 MIPS、 X86等 | > 5M | VFAT、JFFS2、YAFFS、EXT/2/3/4、NFS等等 | NOR、NAND、EMMC等 | diff --git a/zh-cn/device-dev/porting/porting-smallchip-prepare.md b/zh-cn/device-dev/porting/porting-smallchip-prepare.md index b76d5afe44d24f5c0294e9d5f0a8c5c944e0b72c..f0fd72dabfa505722910bda6559f9767a830403f 100644 --- a/zh-cn/device-dev/porting/porting-smallchip-prepare.md +++ b/zh-cn/device-dev/porting/porting-smallchip-prepare.md @@ -1,7 +1,7 @@ -# 移植准备 +# 移植准备 -- **[移植须知](porting-smallchip-prepare-needs.md)** -- **[编译构建](porting-smallchip-prepare-building.md)** +- **[移植须知](porting-smallchip-prepare-needs.md)** +- **[编译构建](porting-smallchip-prepare-building.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-smallchip.md b/zh-cn/device-dev/porting/porting-smallchip.md index df2ce355915f58107c9f9e431a25d69a86d83351..69f8d4ad5b0e2f8ccff11a878679ec673cedd036 100644 --- a/zh-cn/device-dev/porting/porting-smallchip.md +++ b/zh-cn/device-dev/porting/porting-smallchip.md @@ -1,9 +1,9 @@ -# 小型系统芯片移植指导 +# 小型系统芯片移植指导 -- **[移植准备](porting-smallchip-prepare.md)** -- **[移植内核](porting-smallchip-kernel.md)** -- **[驱动移植](porting-smallchip-driver.md)** +- **[移植准备](porting-smallchip-prepare.md)** +- **[移植内核](porting-smallchip-kernel.md)** +- **[驱动移植](porting-smallchip-driver.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-standardchip.md b/zh-cn/device-dev/porting/porting-standardchip.md new file mode 100644 index 0000000000000000000000000000000000000000..6eeb95e54983e909f2cd8bf811a5445cd738a361 --- /dev/null +++ b/zh-cn/device-dev/porting/porting-standardchip.md @@ -0,0 +1,7 @@ +# 标准系统芯片移植指导 + + + +- **[标准系统移植指南](standard-system-porting-guide.md)** + +- **[一种快速移植OpenHarmony Linux内核的方法](porting-linux-kernel.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting-thirdparty-cmake.md b/zh-cn/device-dev/porting/porting-thirdparty-cmake.md index 6800ba882e2a34476c4aeafa6e4f107af8cb0a9b..55ff536c6be07bd0903a0701ab5b046738f8939a 100644 --- a/zh-cn/device-dev/porting/porting-thirdparty-cmake.md +++ b/zh-cn/device-dev/porting/porting-thirdparty-cmake.md @@ -1,435 +1,297 @@ -# CMake方式组织编译的库移植 +# CMake方式组织编译的库移植 -- [源码获取](#section1771132116245) -- [移植思路](#section9737174410328) -- [交叉编译](#section38205577332) - - [编译参考](#section1088111263418) - - [设置执行交叉编译](#section8168182883515) -- [测试](#section6686144293611) -- [将该库编译添加到OpenHarmony工程中](#section1651053153715) +以double-conversion库为例,其移植过程如下文所示。 -以double-conversion库为例,其移植过程如下文所示 -## 源码获取 +## 源码获取 从仓库[获取double-conversion源码](https://github.com/google/double-conversion),其目录结构如下表: -**表 1** 源码目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

double-conversion/cmake/

-

CMake组织编译使用到的模板

-

double-conversion/double-conversion/

-

源文件目录

-

double-conversion/msvc/

-

-

-

double-conversion/test/

-

测试用例源文件

-

double-conversion/.gitignore

-

-

-

double-conversion/AUTHORS

-

-

-

double-conversion/BUILD

-

-

-

double-conversion/CMakeLists.txt

-

CMake方式顶层编译组织文件

-

double-conversion/COPYING

-

-

-

double-conversion/Changelog

-

-

-

double-conversion/LICENSE

-

-

-

double-conversion/Makefile

-

-

-

double-conversion/README.md

-

-

-

double-conversion/SConstruct

-

-

-

double-conversion/WORKSPACE

-

-

-
- -## 移植思路 + **表1** 源码目录结构 + +| 名称 | 描述 | +| -------- | -------- | +| double-conversion/cmake/ | CMake组织编译使用到的模板 | +| double-conversion/double-conversion/ | 源文件目录 | +| double-conversion/msvc/ | - | +| double-conversion/test/ | 测试用例源文件 | +| double-conversion/.gitignore | - | +| double-conversion/AUTHORS | - | +| double-conversion/BUILD | - | +| double-conversion/CMakeLists.txt | CMake方式顶层编译组织文件 | +| double-conversion/COPYING | - | +| double-conversion/Changelog | - | +| double-conversion/LICENSE | - | +| double-conversion/Makefile | - | +| double-conversion/README.md | - | +| double-conversion/SConstruct | - | +| double-conversion/WORKSPACE | - | + + +## 移植思路 移植思路:通过修改工具链,交叉编译该三方库,生成OpenHarmony平台的可执行文件,最后再通过GN调用CMake的方式添加到OpenHarmony工程中。 -## 交叉编译 -### 编译参考 +## 交叉编译 -代码仓库的[README.md](https://github.com/google/double-conversion/blob/master/README.md)中详细介绍了使用CMake编译double-conversion库的步骤,以及测试方法。本文参考该指导设置该库的编译配置,并完成测试。若开发人员在移植过程中对该库的编译选项配置有疑惑的地方,可参考该指导。对于其他使用CMake可独立编译的三方库,在移植时可以参考其自带的编译指导。 -### 设置执行交叉编译 +### 编译参考 -CMake方式可通过指定工具链进行交叉编译,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: +代码仓库的[README.md](https://github.com/google/double-conversion/blob/master/README.md)中详细介绍了使用CMake编译double-conversion库的步骤,以及测试方法。本文参考该指导设置该库的编译配置,并完成测试。若开发人员在移植过程中对该库的编译选项配置有疑惑的地方,可参考该指导。对于其他使用CMake可独立编译的三方库,在移植时可以参考其自带的编译指导。 -1. 设置工具链 - - 将下列clang工具链配置添加到该工程的顶层CMakeLists.txt(即[表1中的该文件](#table824211132418))中即可。 - - ``` - set(CMAKE_CROSSCOMPILING TRUE) - set(CMAKE_SYSTEM_NAME Generic) - set(CMAKE_CXX_COMPILER_ID Clang) - set(CMAKE_TOOLCHAIN_PREFIX llvm-) - #指定c编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,使用clang编译时标志中必须指定--target,否则无法交叉编译。 - set(CMAKE_C_COMPILER clang) - set(CMAKE_C_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") - #指定c++编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,必须指定--target,否则无法交叉编译。 - set(CMAKE_CXX_COMPILER clang++) - set(CMAKE_CXX_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") - #指定链接工具和链接标志,必须指定--target和--sysroot,其中OHOS_ROOT_PATH可通过cmake命令后缀参数来指定。 - set(MY_LINK_FLAGS "--target=arm-liteos --sysroot=${OHOS_SYSROOT_PATH}") - set(CMAKE_LINKER clang) - set(CMAKE_CXX_LINKER clang++) - set(CMAKE_C_LINKER clang) - set(CMAKE_C_LINK_EXECUTABLE - "${CMAKE_C_LINKER} ${MY_LINK_FLAGS} -o ") - set(CMAKE_CXX_LINK_EXECUTABLE - "${CMAKE_CXX_LINKER} ${MY_LINK_FLAGS} -o ") - #指定链接库的查找路径。 - set(CMAKE_SYSROOT ${OHOS_SYSROOT_PATH}) - ``` - -2. 执行编译 - - linux命令行中进入double-conversion的源文件目录(即[表1所示目录](#table824211132418)),执行下列命令: - - ``` - mkdir build && cd build - cmake .. -DBUILD_TESTING=ON -DOHOS_SYSROOT_PATH="..." - make -j - ``` - - 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot目录的位置,以OpenHarmony为例即目录out/hispark\_xxx/ipcamera\_hispark\_xxx/sysroot的绝对路径。上述目录会在全量编译后生成,因此移植前先完成一次全量编译。 - -3. 查看结果 - - 步骤2操作完成后,build目录下会生成静态库文件和测试用例: - - **表 2** 编译生成文件目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

double-conversion/build/libdouble-conversion.a

-

生成的静态库文件

-

double-conversion/build/test/

-

目录下存放生成的测试用例和相关CMake缓存文件

-

double-conversion/build/CMakeCache.txt

-

CMake构建过程中的缓存文件

-

double-conversion/build/CMakeFiles/

-

-

-

double-conversion/build/cmake_install.cmake

-

-

-

double-conversion/build/CTestTestfile.cmake

-

-

-

double-conversion/build/DartConfiguration.tcl

-

-

-

double-conversion/build/generated/

-

-

-

double-conversion/build/Makefile

-

-

-

double-conversion/build/Testing/

-

-

-
- - -## 测试 - -1. 搭建OpenHarmony环境 - - 以hi3518ev300为例,编译出OpenHarmony镜像,烧写到开发板,参考[开发Hi3518第一个示例程序](../quick-start/quickstart-lite-steps-hi3518-running.md)。 - - 进入系统如下所示: - - **图 1** OpenHarmony启动成功界面 - ![](figure/OpenHarmony启动成功界面.png "OpenHarmony启动成功界面") - -2. 挂载nfs目录,将[表2](#table1452412391911)中test目录下cctest可执行文件放入nfs目录 -3. 执行用例 - - 该库采用非交叉编译时用例是通过make test执行,CMake会有相关的执行结果统计;交叉编译时无法使用该方法,因此可直接执行生成的测试文件完成测试。 - - - 挂载成功后执行下列命令可列出用例所有条目: - - ``` - cd nfs - ./cctest --list - ``` - - 上述命令执行结果部分展示: - - ``` - test-bignum/Assign< - test-bignum/ShiftLeft< - test-bignum/AddUInt64< - test-bignum/AddBignum< - test-bignum/SubtractBignum< - test-bignum/MultiplyUInt32< - test-bignum/MultiplyUInt64< - test-bignum/MultiplyPowerOfTen< - test-bignum/DivideModuloIntBignum< - test-bignum/Compare< - test-bignum/PlusCompare< - test-bignum/Square< - test-bignum/AssignPowerUInt16< - test-bignum-dtoa/BignumDtoaVariousDoubles< - test-bignum-dtoa/BignumDtoaShortestVariousFloats< - test-bignum-dtoa/BignumDtoaGayShortest< - test-bignum-dtoa/BignumDtoaGayShortestSingle< - test-bignum-dtoa/BignumDtoaGayFixed< - test-bignum-dtoa/BignumDtoaGayPrecision< - test-conversions/DoubleToShortest< - test-conversions/DoubleToShortestSingle< - ... - ``` - - - 以test-bignum条目为例,执行下列命令开始测试: - - ``` - ./cctest test-bignum - ``` - - 测试结果如下则表示通过: - - ``` - Ran 13 tests. - ``` - - -## 将该库编译添加到OpenHarmony工程中 - -1. 复制库到OpenHarmony工程中 - - 拷贝已经能够成功交叉编译的库到OpenHarmony的third\_party目录,为了不修改要移植的三方库目录下的BUILD.gn文件,再添加一层目录放置新增的gn转CMake编译适配文件,新增的文件有BUILD.gn、build\_thirdparty.py、 config.gni,新增后的目录结构如下所示。 - - **表 3** 添加到工程后的目录结构 - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/double-conversion/BUILD.gn

-

将三方库加入工程的gn适配文件

-

openHarmony/third_party/double-conversion/build_thirdparty.py

-

GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转CMake

-

openHarmony/third_party/double-conversion/config.gni

-

三方库编译配置文件,可修改该文件来配置用例是否参与构建等

-

openHarmony/third_party/double-conversion/double-conversion/

-

要移植的三方库目录

-
- -2. 添加gn到CMake适配文件 - - - **新增的BUILD.gn文件实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony平台时只需修改路径即可**。 - - ``` - import("config.gni") - group("double-conversion") { - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - deps = [":make"] - } - } - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - action("make") { - script = "//third_party/double-conversion/build_thirdparty.py" - outputs = ["$root_out_dir/log_dc.txt"] - exec_path = rebase_path(rebase_path("./build", ohos_third_party_dir)) - command = "rm * .* -rf && $CMAKE_TOOLS_PATH/cmake .. $CMAKE_FLAG $CMAKE_TOOLCHAIN_FLAG && make -j" - args = [ - "--path=$exec_path", - "--command=${command}" - ] - } - } - ``` - - - **新增的config.gni用于配置该库,实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时只需修改CMAKE\_FLAG的配置即可。** - - ``` - #CMAKE_FLAG: config compile feature - CMAKE_FLAG = "-DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=11" - - #toolchain:follow up-layer,depend on $ohos_build_compiler - if (ohos_build_compiler == "clang") { - CMAKE_TOOLCHAIN_FLAG = "-DOHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" - } else { - CMAKE_TOOLCHAIN_FLAG = "" - } - - #CMake tools path,no need setting if this path already joined to $PATH. - CMAKE_TOOLS_PATH = "setting CMake tools path..." - ``` - - - **新增的build\_thirdparty.py实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时无需修改即可使用。** - - ``` - import os - import sys - from subprocess import Popen - import argparse - import shlex - - def cmd_exec(command): - cmd = shlex.split(command) - proc = Popen(cmd) - proc.wait() - ret_code = proc.returncode - if ret_code != 0: - raise Exception("{} failed, return code is {}".format(cmd, ret_code)) - - def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--path', help='Build path.') - parser.add_argument('--command', help='Build command.') - parser.add_argument('--enable', help='enable python.', nargs='*') - args = parser.parse_args() - - if args.enable: - if args.enable[0] == 'false': - return - - if args.path: - curr_dir = os.getcwd() - os.chdir(args.path) - if args.command: - if '&&' in args.command: - command = args.command.split('&&') - for data in command: - cmd_exec(data) - else: - cmd_exec(args.command) - os.chdir(curr_dir) - - if __name__ == '__main__': - sys.exit(main()) - ``` - - - 在配置文件中添加开关控制该库编译,默认设为关闭 - - 在//build/lite/ohos\_var.gni文件中添加下列配置: - - ``` - declare_args() { - ohos_build_thirdparty_migrated_from_fuchisa = true - } - ``` - -3. 编译构建 - - - 手动单独构建: - - 执行下列命令 - - ``` - hb build -T //third_party/double-conversion:double-conversion - ``` - - 编译成功则[build](#li15717101715249)目录下会生成静态库文件和测试用例 +### 设置执行交叉编译 + +CMake方式可通过指定工具链进行交叉编译,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: +1. 设置工具链 + 将下列clang工具链配置添加到该工程的顶层CMakeLists.txt(即表1中的该文件)中即可。 + + ``` + set(CMAKE_CROSSCOMPILING TRUE) + set(CMAKE_SYSTEM_NAME Generic) + set(CMAKE_CXX_COMPILER_ID Clang) + set(CMAKE_TOOLCHAIN_PREFIX llvm-) + #指定c编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,使用clang编译时标志中必须指定--target,否则无法交叉编译。 + set(CMAKE_C_COMPILER clang) + set(CMAKE_C_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4") + #指定c++编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,必须指定--target,否则无法交叉编译。 + set(CMAKE_CXX_COMPILER clang++) + set(CMAKE_CXX_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4") + #指定链接工具和链接标志,必须指定--target和--sysroot,其中OHOS_ROOT_PATH可通过cmake命令后缀参数来指定。 + set(MY_LINK_FLAGS "--target=arm-liteos --sysroot=${OHOS_SYSROOT_PATH}") + set(CMAKE_LINKER clang) + set(CMAKE_CXX_LINKER clang++) + set(CMAKE_C_LINKER clang) + set(CMAKE_C_LINK_EXECUTABLE + "${CMAKE_C_LINKER} ${MY_LINK_FLAGS} -o ") + set(CMAKE_CXX_LINK_EXECUTABLE + "${CMAKE_CXX_LINKER} ${MY_LINK_FLAGS} -o ") + #指定链接库的查找路径。 + set(CMAKE_SYSROOT ${OHOS_SYSROOT_PATH}) + ``` + +2. 执行编译 + linux命令行中进入double-conversion的源文件目录(即标1所示目录),执行下列命令: + + + ``` + mkdir build && cd build + cmake .. -DBUILD_TESTING=ON -DOHOS_SYSROOT_PATH="..." + make -j + ``` + + 其中OHOS_SYSROOT_PATH需用绝对路径指定出sysroot目录的位置,以OpenHarmony为例即目录out/hispark_xxx/ipcamera_hispark_xxx/sysroot的绝对路径。上述目录会在全量编译后生成,因此移植前先完成一次全量编译。 + +3. 查看结果 + 步骤2操作完成后,build目录下会生成静态库文件和测试用例: + + **表2** 编译生成文件目录结构 + + | 名称 | 描述 | + | -------- | -------- | + | double-conversion/build/libdouble-conversion.a | 生成的静态库文件 | + | double-conversion/build/test/ | 目录下存放生成的测试用例和相关CMake缓存文件 | + | double-conversion/build/CMakeCache.txt | CMake构建过程中的缓存文件 | + | double-conversion/build/CMakeFiles/ | - | + | double-conversion/build/cmake_install.cmake | - | + | double-conversion/build/CTestTestfile.cmake | - | + | double-conversion/build/DartConfiguration.tcl | - | + | double-conversion/build/generated/ | - | + | double-conversion/build/Makefile | - | + | double-conversion/build/Testing/ | - | + + +## 测试 + +1. 搭建OpenHarmony环境 + 以Hi3516DV300为例,编译出OpenHarmony镜像,烧写到开发板,参考[开发Hi3516第一个示例程序](../quick-start/quickstart-lite-steps-hi3516-running.md)。 + + 进入系统如下所示: + + **图1** OpenHarmony启动成功界面 + + ![zh-cn_image_0000001218806027](figures/zh-cn_image_0000001218806027.png) + +2. 挂载nfs目录,将表2中test目录下cctest可执行文件放入nfs目录 + +3. 执行用例 + 该库采用非交叉编译时用例是通过make test执行,CMake会有相关的执行结果统计;交叉编译时无法使用该方法,因此可直接执行生成的测试文件完成测试。 + + - 挂载成功后执行下列命令可列出用例所有条目: + + + ``` + cd nfs + ./cctest --list + ``` + + 上述命令执行结果部分展示: + + + ``` + test-bignum/Assign< + test-bignum/ShiftLeft< + test-bignum/AddUInt64< + test-bignum/AddBignum< + test-bignum/SubtractBignum< + test-bignum/MultiplyUInt32< + test-bignum/MultiplyUInt64< + test-bignum/MultiplyPowerOfTen< + test-bignum/DivideModuloIntBignum< + test-bignum/Compare< + test-bignum/PlusCompare< + test-bignum/Square< + test-bignum/AssignPowerUInt16< + test-bignum-dtoa/BignumDtoaVariousDoubles< + test-bignum-dtoa/BignumDtoaShortestVariousFloats< + test-bignum-dtoa/BignumDtoaGayShortest< + test-bignum-dtoa/BignumDtoaGayShortestSingle< + test-bignum-dtoa/BignumDtoaGayFixed< + test-bignum-dtoa/BignumDtoaGayPrecision< + test-conversions/DoubleToShortest< + test-conversions/DoubleToShortestSingle< + ... + ``` + + - 以test-bignum条目为例,执行下列命令开始测试: + + + ``` + ./cctest test-bignum + ``` + + 测试结果如下则表示通过: + + + ``` + Ran 13 tests. + ``` + + +## 将该库编译添加到OpenHarmony工程中 + +1. 复制库到OpenHarmony工程中 + 拷贝已经能够成功交叉编译的库到OpenHarmony的third_party目录,为了不修改要移植的三方库目录下的BUILD.gn文件,再添加一层目录放置新增的gn转CMake编译适配文件,新增的文件有BUILD.gn、build_thirdparty.py、 config.gni,新增后的目录结构如下所示。 + + **表3** 添加到工程后的目录结构 + + | 名称 | 描述 | + | -------- | -------- | + | OpenHarmony/third_party/double-conversion/BUILD.gn | 将三方库加入工程的gn适配文件 | + | OpenHarmony/third_party/double-conversion/build_thirdparty.py | GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转CMake | + | OpenHarmony/third_party/double-conversion/config.gni | 三方库编译配置文件,可修改该文件来配置用例是否参与构建等 | + | OpenHarmony/third_party/double-conversion/double-conversion/ | 要移植的三方库目录 | + +2. 添加gn到CMake适配文件 + - **新增的BUILD.gn文件实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony平台时只需修改路径即可**。 + + + ``` + import("config.gni") + group("double-conversion") { + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + deps = [":make"] + } + } + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + action("make") { + script = "//third_party/double-conversion/build_thirdparty.py" + outputs = ["$root_out_dir/log_dc.txt"] + exec_path = rebase_path(rebase_path("./build", ohos_third_party_dir)) + command = "rm * .* -rf && $CMAKE_TOOLS_PATH/cmake .. $CMAKE_FLAG $CMAKE_TOOLCHAIN_FLAG && make -j" + args = [ + "--path=$exec_path", + "--command=${command}" + ] + } + } + ``` + + - **新增的config.gni用于配置该库,实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时只需修改CMAKE_FLAG的配置即可。** + + + ``` + #CMAKE_FLAG: config compile feature + CMAKE_FLAG = "-DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=11" + + #toolchain:follow up-layer,depend on $ohos_build_compiler + if (ohos_build_compiler == "clang") { + CMAKE_TOOLCHAIN_FLAG = "-DOHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" + } else { + CMAKE_TOOLCHAIN_FLAG = "" + } + + #CMake tools path,no need setting if this path already joined to $PATH. + CMAKE_TOOLS_PATH = "setting CMake tools path..." + ``` + + - **新增的build_thirdparty.py实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时无需修改即可使用。** + + + ``` + import os + import sys + from subprocess import Popen + import argparse + import shlex + + def cmd_exec(command): + cmd = shlex.split(command) + proc = Popen(cmd) + proc.wait() + ret_code = proc.returncode + if ret_code != 0: + raise Exception("{} failed, return code is {}".format(cmd, ret_code)) + + def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--path', help='Build path.') + parser.add_argument('--command', help='Build command.') + parser.add_argument('--enable', help='enable python.', nargs='*') + args = parser.parse_args() + + if args.enable: + if args.enable[0] == 'false': + return + + if args.path: + curr_dir = os.getcwd() + os.chdir(args.path) + if args.command: + if '&&' in args.command: + command = args.command.split('&&') + for data in command: + cmd_exec(data) + else: + cmd_exec(args.command) + os.chdir(curr_dir) + + if __name__ == '__main__': + sys.exit(main()) + ``` + + - 在配置文件中添加开关控制该库编译,默认设为关闭 + + 在//build/lite/ohos_var.gni文件中添加下列配置: + + + ``` + declare_args() { + ohos_build_thirdparty_migrated_from_fuchisa = true + } + ``` + +3. 编译构建 + - 手动单独构建: + + 执行下列命令 + + + ``` + hb build -T //third_party/double-conversion:double-conversion + ``` + + 编译成功则build目录下会生成静态库文件和测试用例 diff --git a/zh-cn/device-dev/porting/porting-thirdparty-makefile.md b/zh-cn/device-dev/porting/porting-thirdparty-makefile.md index 51627f2fcbf895aa960948877f5eac60f0eec35a..dca898d1a778dbf19bfd97f1ef67af4325e6fe71 100644 --- a/zh-cn/device-dev/porting/porting-thirdparty-makefile.md +++ b/zh-cn/device-dev/porting/porting-thirdparty-makefile.md @@ -1,189 +1,94 @@ -# Makefile方式组织编译的库移植 +# Makefile方式组织编译的库移植 -- [源码获取](#section114115321416) -- [设置交叉编译](#section81263255384) -- [测试](#section1830015913391) -- [将该库编译添加到OpenHarmony工程中](#section1898016213406) -以yxml库为例,其移植过程如下文所示 +以yxml库为例,其移植过程如下文所示。 -## 源码获取 + +## 源码获取 从仓库[获取yxml源码](https://github.com/getdnsapi/yxml),其目录结构如下表: -**表 1** 源码目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

yxml/bench/

-

benchmark相关代码

-

yxml/test/

-

测试输入输出文件,及测试脚本

-

yxml/Makefile

-

编译组织文件

-

yxml/.gitattributes

-

-

-

yxml/.gitignore

-

-

-

yxml/COPYING

-

-

-

yxml/yxml.c

-

-

-

yxml/yxml.c.in

-

-

-

yxml/yxml-gen.pl

-

-

-

yxml/yxml.h

-

-

-

yxml/yxml.md

-

-

-

yxml/yxml-states

-

-

-
- -## 设置交叉编译 + **表1** 源码目录结构 + +| 名称 | 描述 | +| -------- | -------- | +| yxml/bench/ | benchmark相关代码 | +| yxml/test/ | 测试输入输出文件,及测试脚本 | +| yxml/Makefile | 编译组织文件 | +| yxml/.gitattributes | - | +| yxml/.gitignore | - | +| yxml/COPYING | - | +| yxml/yxml.c | - | +| yxml/yxml.c.in | - | +| yxml/yxml-gen.pl | - | +| yxml/yxml.h | - | +| yxml/yxml.md | - | +| yxml/yxml-states | - | + + +## 设置交叉编译 设置Makefile的交叉编译工具链,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: -1. 设置工具链 - - 将下列clang工具链配置替换掉yxml库根目录的MakeFile(即[表1中的文件](#table16520154171813))中的原有配置。 - - clang工具链配置 - - ``` - #设置交叉编译工具链,确保工具链所在路径已经添加到了PATH环境变量中 - CC:=clang - AR:=llvm-ar - #cflags中必须要添加--target及--sysroot选项 - CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g --target=arm-liteos -march=armv7-a --sysroot=$(OHOS_SYSROOT_PATH) - ``` - - 原有配置 - - ``` - CC:=gcc - AR:=ar - CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g - ``` - -2. 执行编译 - - linux命令行中进入yxml的源文件目录(即图1所示目录),执行下列命令: - - ``` - make test OHOS_SYSROOT_PATH=... - ``` - - 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot所在目录,以OpenHarmony为例即源码根目录下out/hispark\_xxx/ipcamera\_hispark\_xxx/sysroot目录的绝对路径。上述目录会在全量编译后生成,因此移植前先完成一次全量编译。 - -3. 查看结果 - - 步骤2操作完成后,yxml下会生成out目录,里面有静态库文件和测试用例: - - **表 2** yxml编译生成目录 - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/yxml/yxml/out/lib/

-

编译生成的静态库的存放目录

-

openHarmony/third_party/yxml/yxml/out/test/

-

编译生成的测试用例及其输入输出等文件的存放目录

-
- - -## 测试 - -yxml库测试步骤与double-conversion库基本一致,可参考[CMake方式组织编译的库移植](porting-thirdparty-cmake.md#section6686144293611)的测试过程,以下内容介绍yxml库测试用例的使用方法: - -**表 3** 生成的test目录结构示意 - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/yxml/yxml/out/test/test.sh

-

自动化测试脚本,由于OpenHarmony不支持脚本运行,因此无法使用,可参考其内容手动测试

-

openHarmony/third_party/yxml/yxml/out/test/test

-

用于测试的可执行文件

-

openHarmony/third_party/yxml/yxml/out/test/*.xml

-

测试输入文件

-

openHarmony/third_party/yxml/yxml/out/test/*.out

-

期望的输出文件

-
+1. 设置工具链 + 将下列clang工具链配置替换掉yxml库根目录的MakeFile(即表1中的文件)中的原有配置。 + + clang工具链配置: + + ``` + #设置交叉编译工具链,确保工具链所在路径已经添加到了PATH环境变量中 + CC:=clang + AR:=llvm-ar + #cflags中必须要添加--target及--sysroot选项 + CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g --target=arm-liteos -march=armv7-a -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 --sysroot=$(OHOS_SYSROOT_PATH) + ``` + + 原有配置: + + + ``` + CC:=gcc + AR:=ar + CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g + ``` + +2. 执行编译 + linux命令行中进入yxml的源文件目录(即图1所示目录),执行下列命令: + + + ``` + make test OHOS_SYSROOT_PATH=... + ``` + + 其中OHOS_SYSROOT_PATH需用绝对路径指定出sysroot所在目录,以OpenHarmony为例即源码根目录下out/hispark_xxx/ipcamera_hispark_xxx/sysroot目录的绝对路径。上述目录会在全量编译后生成,因此移植前先完成一次全量编译。 + +3. 查看结果 + 步骤2操作完成后,yxml下会生成out目录,里面有静态库文件和测试用例: + + **表2** yxml编译生成目录 + + | 名称 | 描述 | + | -------- | -------- | + | OpenHarmony/third_party/yxml/yxml/out/lib/ | 编译生成的静态库的存放目录 | + | OpenHarmony/third_party/yxml/yxml/out/test/ | 编译生成的测试用例及其输入输出等文件的存放目录 | + + +## 测试 + +yxml库测试步骤与double-conversion库基本一致,可参考[CMake方式组织编译的库移植](../porting/porting-thirdparty-cmake.md#测试)的测试过程,以下内容介绍yxml库测试用例的使用方法: + + **表3** 生成的test目录结构示意 + +| 名称 | 描述 | +| -------- | -------- | +| OpenHarmony/third_party/yxml/yxml/out/test/test.sh | 自动化测试脚本,由于OpenHarmony不支持脚本运行,因此无法使用,可参考其内容手动测试 | +| OpenHarmony/third_party/yxml/yxml/out/test/test | 用于测试的可执行文件 | +| OpenHarmony/third_party/yxml/yxml/out/test/\*.xml | 测试输入文件 | +| OpenHarmony/third_party/yxml/yxml/out/test/\*.out | 期望的输出文件 | test.sh内容如下所示: + ``` #!/bin/sh for i in *.xml; do @@ -200,46 +105,46 @@ done echo "All tests completed successfully." ``` -由于OpenHarmony的shell中暂不支持输入输出重定向(<和\>),所以测试时需要将输入\*.xml文件内容直接复制进shell后回车,输出内容会直接展示在shell窗口。过程如下: +由于OpenHarmony的shell中暂不支持输入输出重定向(<和>),所以测试时需要将输入\*.xml文件内容直接复制进shell后回车,输出内容会直接展示在shell窗口。过程如下: 下列操作假定已按照2.4节的步骤搭建OpenHarmony,挂载并进入nfs目录: -1. 执行下列命令 +1. 执行下列命令 + + ``` + ./test + ``` - ``` - ./test - ``` +2. 复制\*.xml内容到shell + 以表3test目录下pi01.xml为例,内容如下,输入到shell并回车: + + ``` + + ``` -2. 复制\*.xml内容到shell +3. 比较shell中输出的内容与表3test目录中对应的\*.out文件是否一致 + 输出结果如下: - 以[test目录](#table115941423164318)下pi01.xml为例,内容如下,输入到shell并回车: + + ``` + pistart SomePI + picontent abc + piend + elemstart a + elemend + ok + ``` - ``` - - ``` + 经比较与表3test目录下pi01.out内容一致,测试通过。 -3. 比较shell中输出的内容与[test目录](#table115941423164318)中对应的\*.out文件是否一致 - 输出结果如下: +## 将该库编译添加到OpenHarmony工程中 - ``` - pistart SomePI - picontent abc - piend - elemstart a - elemend - ok - ``` +yxml库添加的过程除了适配文件build.gn和config.gni有些许变化外,其他和double-conversion库完全一致,参考[CMake方式组织编译的库移植](../porting/porting-thirdparty-cmake.md#将该库编译添加到openharmony工程中)的配置过程。要修改的适配文件及添加后的目录结构如下: - 经比较与[test目录](#table115941423164318)下pi01.out内容一致,测试通过。 - - -## 将该库编译添加到OpenHarmony工程中 - -yxml库添加的过程除了适配文件build.gn和config.gni有些许变化外,其他和double-conversion库完全一致,参考[CMake方式组织编译的库移植](porting-thirdparty-cmake.md#section1651053153715)的配置过程。要修改的适配文件及添加后的目录结构如下: - -- yxml库新增的BUILD.gn实现如下: +- yxml库新增的BUILD.gn实现如下: + ``` import("config.gni") group("yxml") { @@ -261,8 +166,9 @@ if (ohos_build_thirdparty_migrated_from_fuchisa == true) { } ``` -- yxml库新增的config.gni配置如下: +- yxml库新增的config.gni配置如下: + ``` TEST_ENABLE = "YES" @@ -273,37 +179,13 @@ if (TEST_ENABLE == "YES") { } ``` -- 添加完成后目录结构示意: - -**表 4** 添加到工程后的目录结构 - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/yxml/BUILD.gn

-

将三方库加入工程的gn适配文件

-

openHarmony/third_party/yxml/build_thirdparty.py

-

GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转Makefile

-

openHarmony/third_party/yxml/config.gni

-

三方库编译配置文件,可修改该文件来配置用例是否参与构建等

-

openHarmony/third_party/yxml/yxml/

-

要移植的三方库目录

-
+- 添加完成后目录结构示意: + + **表4** 添加到工程后的目录结构 +| 名称 | 描述 | +| -------- | -------- | +| OpenHarmony/third_party/yxml/BUILD.gn | 将三方库加入工程的gn适配文件 | +| OpenHarmony/third_party/yxml/build_thirdparty.py | GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转Makefile | +| OpenHarmony/third_party/yxml/config.gni | 三方库编译配置文件,可修改该文件来配置用例是否参与构建等 | +| OpenHarmony/third_party/yxml/yxml/ | 要移植的三方库目录 | diff --git a/zh-cn/device-dev/porting/porting-thirdparty-overview.md b/zh-cn/device-dev/porting/porting-thirdparty-overview.md index 9b230dfd42f3f25faa73c09cb41993003e4618c8..a5a11e743dad81e7c39ae8e32e35defad24edae3 100755 --- a/zh-cn/device-dev/porting/porting-thirdparty-overview.md +++ b/zh-cn/device-dev/porting/porting-thirdparty-overview.md @@ -1,4 +1,4 @@ -# 概述 +# 概述 -本文为OpenHarmony开发者提供一些组织编译形式比较常见(CMakeLists、Makefile)的三方库的移植指南,该指南当前仅适用于Hi3516DV300和Hi3518EV300两个平台,文中着重介绍各编译组织方式下工具链的设置方法以及如何将该库的编译添加到OpenHarmony整个工程的构建中。 +本文为OpenHarmony开发者提供一些组织编译形式比较常见(CMakeLists、Makefile)的三方库的移植指南,该指南当前仅适用于Hi3516DV300和Hi3518EV300两个平台,文中着重介绍各编译组织方式下工具链的设置方法以及如何将该库的编译添加到OpenHarmony整个工程的构建中。 diff --git a/zh-cn/device-dev/porting/porting-thirdparty.md b/zh-cn/device-dev/porting/porting-thirdparty.md index bd86b610370fa3716c4e39ee36a72e0e7fd976b7..8ce9009780c141eaccf044b4ad0539b124c08e41 100644 --- a/zh-cn/device-dev/porting/porting-thirdparty.md +++ b/zh-cn/device-dev/porting/porting-thirdparty.md @@ -1,9 +1,9 @@ -# 轻量和小型系统三方库移植指导 +# 轻量和小型系统三方库移植指导 -- **[概述](porting-thirdparty-overview.md)** -- **[CMake方式组织编译的库移植](porting-thirdparty-cmake.md)** -- **[Makefile方式组织编译的库移植](porting-thirdparty-makefile.md)** +- **[概述](porting-thirdparty-overview.md)** +- **[CMake方式组织编译的库移植](porting-thirdparty-cmake.md)** +- **[Makefile方式组织编译的库移植](porting-thirdparty-makefile.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/porting.md b/zh-cn/device-dev/porting/porting.md index f91d8af91d792e8f0e76d5a221d6f41ed42c38e8..8e94e3841dec35cd49cba7b8f9253b40b8e940a5 100644 --- a/zh-cn/device-dev/porting/porting.md +++ b/zh-cn/device-dev/porting/porting.md @@ -1,11 +1,11 @@ -# 移植 +# 移植 -- **[三方库移植指导](porting-thirdparty.md)** -- **[轻量系统芯片移植指导](porting-minichip.md)** -- **[小型系统芯片移植指导](porting-smallchip.md)** +- **[轻量系统芯片移植指导](porting-minichip.md)** -- **[标准系统移植指导](standard-system-porting-guide.md)** +- **[小型系统芯片移植指导](porting-smallchip.md)** +- **[标准系统芯片移植指导](porting-standardchip.md)** +- **[轻量和小型系统三方库移植指导](porting-thirdparty.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda Binary files /dev/null and b/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 Binary files /dev/null and b/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..93aa72053b510e456b149f36a0972703ea9999b7 Binary files /dev/null and b/zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif differ diff --git a/zh-cn/device-dev/porting/standard-system-porting-guide.md b/zh-cn/device-dev/porting/standard-system-porting-guide.md index 9abc7dc788d738d021c67916718c411244ef3f60..5dfa7809c77437b9a6d0d0bd0d5a09d6d93c683d 100644 --- a/zh-cn/device-dev/porting/standard-system-porting-guide.md +++ b/zh-cn/device-dev/porting/standard-system-porting-guide.md @@ -1,29 +1,15 @@ -# 标准系统移植指南 - -- [定义开发板](#section132mcpsimp) - - [定义SOC](#section135mcpsimp) - - [定义产品](#section145mcpsimp) - - [移植验证](#section163mcpsimp) - -- [内核移植](#section171mcpsimp) - - [1.为SOC添加内核构建的子系统](#section174mcpsimp) - - [2. 编译内核](#section182mcpsimp) - - [3. 移植验证](#section207mcpsimp) - -- [HDF驱动移植](#section210mcpsimp) - - [1. LCD](#section212mcpsimp) - - [2. 触摸屏](#section229mcpsimp) - - [3. WLAN](#section274mcpsimp) - - [4. 开发移植示例](#section11253153018415) +# 标准系统移植指南 本文描述了移植一块开发板的通用步骤,和具体芯片相关的详细移植过程无法在此一一列举。后续社区还会陆续发布开发板移植的实例供开发者参考。 -## 定义开发板 + +## 定义开发板 本文以移植名为MyProduct的开发板为例讲解移植过程,假定MyProduct是MyProductVendor公司的开发板,使用MySoCVendor公司生产的MySOC芯片作为处理器。 -### 定义SOC + +### 定义SOC 在“//productdefine/common/device”目录下创建以SOC名字命名的json文件,并指定CPU的架构。 @@ -31,6 +17,7 @@ //productdefine/common/device/MySOC.json + ``` { "target_os": "ohos", @@ -38,14 +25,16 @@ } ``` -根据实际情况,这里的target\_cpu也可能是arm64 、riscv、 x86等。当前仅支持arm作为target\_cpu。 +根据实际情况,这里的target_cpu也可能是arm64 、riscv、 x86等。当前仅支持arm作为target_cpu。 -### 定义产品 + +### 定义产品 在“//productdefine/common/products”目录下创建以产品名命名的json文件。该文件用于描述产品所使用的SOC 以及所需的子系统。配置如下 //productdefine/common/products/MyProduct.json + ``` { "product_name": "MyProduct", @@ -65,32 +54,38 @@ 主要的配置内容包括: -1. product\_device:配置所使用的SOC -2. type:配置系统的级别, 这里直接standard即可 -3. parts:系统需要启用的子系统。子系统可以简单理解位一块独立构建的功能块。 +1. product_device:配置所使用的SOC + +2. type:配置系统的级别, 这里直接standard即可 -已定义的子系统可以在“//build/subsystem\_config.json”中找到。当然你也可以定制子系统。 +3. parts:系统需要启用的子系统。子系统可以简单理解为一块独立构建的功能块。 -这里建议先拷贝Hi3516DV300 开发板的配置文件,删除掉 hisilicon\_products 这个子系统。这个子系统为Hi3516DV300 SOC编译内核,显然不适合MySOC。 +已定义的子系统可以在“//build/subsystem_config.json”中找到。当然你也可以定制子系统。 -### 移植验证 +这里建议先拷贝Hi3516DV300 开发板的配置文件,删除掉 hisilicon_products 这个子系统。这个子系统为Hi3516DV300 SOC编译内核,显然不适合MySOC。 -至此,你可以使用如下命令,启动你产品的构建了: +### 移植验证 + + 至此,你可以使用如下命令,启动你产品的构建了: + ``` ./build.sh --product-name MyProduct ``` 构建完成后,可以在“//out/{device_name}/packages/phone/images”目录下看到构建出来的OpenHarmony镜像文件。 -## 内核移植 + +## 内核移植 这一步需要移植Linux内核,让Linux内核可以成功运行起来。 -### 1.为SOC添加内核构建的子系统 -修改文件 //build/subsystem\_config.json增加一个子系统. 配置如下: +### 1.为SOC添加内核构建的子系统 +修改文件 //build/subsystem_config.json增加一个子系统. 配置如下: + + ``` "MySOCVendor_products": { "project": "hmf/MySOCVendor_products", @@ -102,14 +97,16 @@ 接着需要修改定义产品的配置文件//productdefine/common/products/MyProduct.json,将刚刚定义的子系统加入到产品中。 -### 2. 编译内核 -OpenHarmony源码中提供了Linux 4.19的内核,归档在//kernel/linux-4.19。本节以该内核版本为例,讲解如何编译内核。 +### 2. 编译内核 + +源码中提供了Linux 4.19的内核,归档在//kernel/linux-4.19。本节以该内核版本为例,讲解如何编译内核。 -在子系统的定义中,描述了子系统构建的路径path,即\`//device/MySOCVendor/MySOC/build\`。这一节会在这个目录创建构建脚本,告诉构建系统如何构建内核。 +在子系统的定义中,描述了子系统构建的路径path,即`//device/MySOCVendor/MySOC/build`。这一节会在这个目录创建构建脚本,告诉构建系统如何构建内核。 建议的目录结构 + ``` ├── build │ ├── kernel @@ -123,41 +120,58 @@ BUILD.gn是subsystem构建的唯一入口。 期望的构建结果 - - - - - - - - - - - -

文件

-

文件说明

-

$root_build_dir/packages/phone/images/uImage

-

内核镜像

-

$root_build_dir/packages/phone/images/uboot

-

bootloader镜像

-
- -### 3. 移植验证 + | | | +| -------- | -------- | +| 文件 | 文件说明 | +| $root_build_dir/packages/phone/images/uImage | 内核镜像 | +| $root_build_dir/packages/phone/images/uboot | bootloader镜像 | + + +### 3. 移植验证 启动编译,验证预期的kernel镜像是否成功生成。 -## HDF驱动移植 +## 用户态启动引导 + +1. 用户态进程启动引导总览。 + + ![zh-cn_image_0000001199805369](figures/zh-cn_image_0000001199805369.png) + + + 系统上电加载内核后,按照以下流程完成系统各个服务和应用的启动: -### 1. LCD + 1. 内核启动init进程,一般在bootloader启动内核时通过设置内核的cmdline来指定init的位置;如上图所示的"init=/init root/dev/xxx"。 + 2. init进程启动后,会挂载tmpfs,procfs,创建基本的dev设备节点,提供最基本的根文件系统。 + 3. init继续启动ueventd监听内核热插拔事件,为这些设备创建dev设备节点;包括block设备各个分区设备都是通过此事件创建。 + 4. init进程挂载block设备各个分区(system,vendor),开始扫描各个系统服务的init启动脚本,并拉起各个SA服务。 + 5. samgr是各个SA的服务注册中心,每个SA启动时,都需要向samgr注册,每个SA会分配一个ID,应用可以通过该ID访问SA。 + 6. foundation是一个特殊的SA服务进程,提供了用户程序管理框架及基础服务;由该进程负责应用的生命周期管理。 + 7. 由于应用都需要加载JS的运行环境,涉及大量准备工作,因此appspawn作为应用的孵化器,在接收到foundation里的应用启动请求时,可以直接孵化出应用进程,减少应用启动时间。 + +2. init。 + init启动引导组件配置文件包含了所有需要由init进程启动的系统关键服务的服务名、可执行文件路径、权限和其他信息。每个系统服务各自安装其启动脚本到/system/etc/init目录下。 + + 新芯片平台移植时,平台相关的初始化配置需要增加平台相关的初始化配置文件/vendor/etc/init/init.{hardware}.cfg;该文件完成平台相关的初始化设置,如安装ko驱动,设置平台相关的/proc节点信息。 + + init相关进程代码在//base/startup/init_lite目录下,该进程是系统第一个进程,无其它依赖。 + + 初始化配置文件具体的开发指导请参考 [init启动引导组件](../subsystems/subsys-boot-init.md)。 + + +## HDF驱动移植 + + +### 1. LCD HDF为LCD设计了驱动模型。支持一块新的LCD,需要编写一个驱动,在驱动中生成模型的实例,并完成注册。 这些LCD的驱动被放置在//drivers/framework/model/display/driver/panel目录中。 -- 创建Panel驱动 +- 创建Panel驱动 在驱动的Init方法中,需要调用RegisterPanel接口注册模型实例。如: + ``` int32_t XXXInit(struct HdfDeviceObject *object) { @@ -180,8 +194,9 @@ struct HdfDriverEntry g_xxxxDevEntry = { HDF_INIT(g_xxxxDevEntry); ``` -- 配置加载panel驱动产品的所有设备信息被定义在文件//vendor/MyProductVendor/MyProduct/config/device\_info/device\_info.hcs中。修改该文件,在display的host中,名为device\_lcd的device中增加配置。注意:moduleName 要与panel驱动中的moduleName相同。 +- 配置加载panel驱动产品的所有设备信息被定义在文件//vendor/MyProductVendor/MyProduct/config/device_info/device_info.hcs中。修改该文件,在display的host中,名为device_lcd的device中增加配置。注意:moduleName 要与panel驱动中的moduleName相同。 + ``` root { ... @@ -198,16 +213,18 @@ root { } ``` -更详细的驱动开发指导,请参考 [LCD](../driver/driver-peripherals-lcd-des.md)。 +更详细的驱动开发指导,请参考 [LCD](../driver/driver-peripherals-lcd-des.md)。 + -### 2. 触摸屏 +### 2. 触摸屏 本节描述如何移植触摸屏驱动。触摸屏的驱动被放置在//drivers/framework/model/input/driver/touchscreen目录中。移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。 -- 创建触摸屏器件驱动 +- 创建触摸屏器件驱动 -在目录中创建名为touch\_ic\_name.c的文件。代码模板如下:注意:请替换ic\_name为你所适配芯片的名称。 +在目录中创建名为touch_ic_name.c的文件。代码模板如下:注意:请替换ic_name为你所适配芯片的名称。 + ``` #include "hdf_touch.h" @@ -232,50 +249,20 @@ HDF_INIT(g_touchXXXXChipEntry); 其中ChipDevice中要提供若干方法。 - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

实现说明

-

int32_t (*Init)(ChipDevice *device)

-

器件初始化

-

int32_t (*Detect)(ChipDevice *device)

-

器件探测

-

int32_t (*Suspend)(ChipDevice *device)

-

器件休眠

-

int32_t (*Resume)(ChipDevice *device)

-

器件唤醒

-

int32_t (*DataHandle)(ChipDevice *device)

-

从器件读取数据,将触摸点数据填写入device->driver->frameData中

-

int32_t (*UpdateFirmware)(ChipDevice *device)

-

固件升级

-
- -- 配置产品,加载器件驱动 - - 产品的所有设备信息被定义在文件//vendor/MyProductVendor/MyProduct/config/device\_info/device\_info.hcs中。修改该文件,在名为input的host中,名为device\_touch\_chip的device中增加配置。注意:moduleName 要与触摸屏驱动中的moduleName相同。 + | | | +| -------- | -------- | +| 方法 | 实现说明 | +| int32_t (\*Init)(ChipDevice \*device) | 器件初始化 | +| int32_t (\*Detect)(ChipDevice \*device) | 器件探测 | +| int32_t (\*Suspend)(ChipDevice \*device) | 器件休眠 | +| int32_t (\*Resume)(ChipDevice \*device) | 器件唤醒 | +| int32_t (\*DataHandle)(ChipDevice \*device) | 从器件读取数据,将触摸点数据填写入device->driver->frameData中 | +| int32_t (\*UpdateFirmware)(ChipDevice \*device) | 固件升级 | +- 配置产品,加载器件驱动 + 产品的所有设备信息被定义在文件//vendor/MyProductVendor/MyProduct/config/device_info/device_info.hcs中。修改该文件,在名为input的host中,名为device_touch_chip的device中增加配置。注意:moduleName 要与触摸屏驱动中的moduleName相同。 + ``` deviceN :: deviceNode { policy = 0; @@ -287,53 +274,31 @@ HDF_INIT(g_touchXXXXChipEntry); } ``` -更详细的驱动开发指导,请参考 [TOUCHSCREEN](../driver/driver-peripherals-touch-des.md)。 +更详细的驱动开发指导,请参考 [TOUCHSCREEN](../driver/driver-peripherals-touch-des.md)。 -### 3. WLAN + +### 3. WLAN Wi-Fi驱动分为两部分,一部分负责管理WLAN设备,另一个部分负责处理WLAN流量。HDF WLAN分别为这两部分做了抽象。目前支持SDIO接口的WLAN芯片。 -**图 1** WLAN芯片 -![](figure/WLAN芯片.png "WLAN芯片") - -支持一款芯片的主要工作是实现一个ChipDriver驱动。实现HDF\_WLAN\_CORE和NetDevice提供的接口。主要需要实现的接口有: - - - - - - - - - - - - - - - - - - - -

接口

-

定义头文件

-

说明

-

HdfChipDriverFactory

-

//drivers/framework/include/wifi/hdf_wlan_chipdriver_manager.h

-

ChipDriver的Factory,用于支持一个芯片多个Wi-Fi端口

-

HdfChipDriver

-

//drivers/framework/include/wifi/wifi_module.h

-

每个WLAN端口对应一个HdfChipDriver,用来管理一个特定的WLAN端口

-

NetDeviceInterFace

-

//drivers/framework/include/net/net_device.h

-

与协议栈之间的接口,如发送数据、设置网络接口状态等

-
+ **图1** WLAN芯片 + + ![zh-cn_image_0000001188241031](figures/zh-cn_image_0000001188241031.png) + +支持一款芯片的主要工作是实现一个ChipDriver驱动。实现HDF_WLAN_CORE和NetDevice提供的接口。主要需要实现的接口有: + + | | | | +| -------- | -------- | -------- | +| 接口 | 定义头文件 | 说明 | +| HdfChipDriverFactory | //drivers/framework/include/wifi/hdf_wlan_chipdriver_manager.h | ChipDriver的Factory,用于支持一个芯片多个Wi-Fi端口 | +| HdfChipDriver | //drivers/framework/include/wifi/wifi_module.h | 每个WLAN端口对应一个HdfChipDriver,用来管理一个特定的WLAN端口 | +| NetDeviceInterFace | //drivers/framework/include/net/net_device.h | 与协议栈之间的接口,如发送数据、设置网络接口状态等 | 建议适配按如下步骤操作: -1.创建HDF驱动建议将代码放置在//device/MySoCVendor/peripheral/wifi/chip\_name/,文件模板如下: +1.创建HDF驱动建议将代码放置在//device/MySoCVendor/peripheral/wifi/chip_name/,文件模板如下: + ``` static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) { static struct HdfChipDriverFactory factory = CreateChipDriverFactory(); @@ -357,94 +322,37 @@ HDF_INIT(g_hdfXXXChipEntry); 在CreateChipDriverFactory中,需要创建一个HdfChipDriverFactory,接口如下: - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口

-

说明

-

const char *driverName

-

当前driverName

-

int32_t (*InitChip)(struct HdfWlanDevice *device)

-

初始化芯片

-

int32_t (*DeinitChip)(struct HdfWlanDevice *device)

-

去初始化芯片

-

void (_ReleaseFactory)(struct HdfChipDriverFactory _factory)

-

释放HdfChipDriverFactory对象

-

struct HdfChipDriver _(_Build)(struct HdfWlanDevice *device, uint8_t ifIndex)

-

创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号

-

void (_Release)(struct HdfChipDriver _chipDriver)

-

释放chipDriver

-

uint8_t (*GetMaxIFCount)(struct HdfChipDriverFactory *factory)

-

获取当前芯片支持的最大接口数

-
+ | | | +| -------- | -------- | +| 接口 | 说明 | +| const char \*driverName | 当前driverName | +| int32_t (\*InitChip)(struct HdfWlanDevice \*device) | 初始化芯片 | +| int32_t (\*DeinitChip)(struct HdfWlanDevice \*device) | 去初始化芯片 | +| void (_ReleaseFactory)(struct HdfChipDriverFactory _factory) | 释放HdfChipDriverFactory对象 | +| struct HdfChipDriver _(_Build)(struct HdfWlanDevice \*device, uint8_t ifIndex) | 创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号 | +| void (_Release)(struct HdfChipDriver _chipDriver) | 释放chipDriver | +| uint8_t (\*GetMaxIFCount)(struct HdfChipDriverFactory \*factory) | 获取当前芯片支持的最大接口数 | HdfChipDriver需要实现的接口有 - - - - - - - - - - - - - - - - - - - - -

接口

-

说明

-

int32_t (*init)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

-

初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace

-

int32_t (*deinit)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

-

去初始化当前网络接口

-

struct HdfMac80211BaseOps *ops

-

WLAN基础能力接口集

-

struct HdfMac80211STAOps *staOps

-

支持STA模式所需的接口集

-

struct HdfMac80211APOps *apOps

-

支持AP模式所需要的接口集

-
+ | | | +| -------- | -------- | +| 接口 | 说明 | +| int32_t (\*init)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | 初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace | +| int32_t (\*deinit)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | 去初始化当前网络接口 | +| struct HdfMac80211BaseOps \*ops | WLAN基础能力接口集 | +| struct HdfMac80211STAOps \*staOps | 支持STA模式所需的接口集 | +| struct HdfMac80211APOps \*apOps | 支持AP模式所需要的接口集 | 2.编写配置文件,描述驱动支持的设备 -在产品配置目录下创建芯片的配置文件//vendor/MyProductVendor/MyProduct/config/wifi/wlan\_chip\_chip\_name.hcs。 +在产品配置目录下创建芯片的配置文件//vendor/MyProductVendor/MyProduct/config/wifi/wlan_chip_chip_name.hcs。 -注意: 路径中的vendor\_name、product\_name、chip\_name请替换成实际名称。 +注意: 路径中的vendor_name、product_name、chip_name请替换成实际名称。 模板如下: + ``` root { wlan_config { @@ -464,8 +372,9 @@ root { 3.编写配置文件,加载驱动 -产品的所有设备信息被定义在文件//vendor/MyProductVendor/MyProduct/config/device\_info/device\_info.hcs中。修改该文件,在名为network的host中,名为device\_wlan\_chips的device中增加配置。注意:moduleName 要与触摸屏驱动中的moduleName相同。 +产品的所有设备信息被定义在文件//vendor/MyProductVendor/MyProduct/config/device_info/device_info.hcs中。修改该文件,在名为network的host中,名为device_wlan_chips的device中增加配置。注意:moduleName 要与触摸屏驱动中的moduleName相同。 + ``` deviceN :: deviceNode { policy = 0; @@ -478,8 +387,9 @@ root { 4.构建驱动 -- 创建内核菜单在//device/MySoCVendor/peripheral目录中创建Kconfig文件,内容模板如下: +- 创建内核菜单在//device/MySoCVendor/peripheral目录中创建Kconfig文件,内容模板如下: + ``` config DRIVERS_WLAN_XXX bool "Enable XXX WLAN Host driver" @@ -491,23 +401,23 @@ config DRIVERS_WLAN_XXX 接着修改文件//drivers/adapter/khdf/linux/model/network/wifi/Kconfig,在文件末尾加入如下代码将配置菜单加入内核中,如: + ``` source "../../../../../device/MySoCVendor/peripheral/Kconfig" ``` -- 创建构建脚本 - - 在//drivers/adapter/khdf/linux/model/network/wifi/Makefile文件末尾增加配置,模板如下: - +- 创建构建脚本 + 在//drivers/adapter/khdf/linux/model/network/wifi/Makefile文件末尾增加配置,模板如下: + ``` HDF_DEVICE_ROOT := $(HDF_DIR_PREFIX)/../device obj-$(CONFIG_DRIVERS_WLAN_XXX) += $(HDF_DEVICE_ROOT)/MySoCVendor/peripheral/build/standard/ ``` -当在内核中开启DRIVERS\_WLAN\_XXX开关时,会调用//device/MySoCVendor/peripheral/build/standard/中的makefile。更多详细的开发手册,请参考[WLAN开发](../guide/device-wlan-led-control.md)。 +当在内核中开启DRIVERS_WLAN_XXX开关时,会调用//device/MySoCVendor/peripheral/build/standard/中的makefile。更多详细的开发手册,请参考[WLAN开发](../guide/device-wlan-led-control.md)。 -### 4. 开发移植示例 -开发移植示例请参考[DAYU开发板](https://gitee.com/openharmony-sig/devboard_device_hihope_build/blob/master/DAYU%20%E5%B9%B3%E5%8F%B0OpenHarmony%20%E9%80%82%E9%85%8D%E6%8C%87%E5%AF%BC%20-202108.pdf)。 +### 4. 开发移植示例 +开发移植示例请参考[DAYU开发板](https://gitee.com/openharmony-sig/devboard_device_hihope_build/blob/master/DAYU%20%E5%B9%B3%E5%8F%B0OpenHarmony%20%E9%80%82%E9%85%8D%E6%8C%87%E5%AF%BC%20-202108.pdf)。 diff --git a/zh-cn/device-dev/quick-start/Readme-CN.md b/zh-cn/device-dev/quick-start/Readme-CN.md index 623dbf6c1335167f117d457d2dedf2bbbdaeb728..0724994b52963832580b500b5121d979d6d5d19e 100644 --- a/zh-cn/device-dev/quick-start/Readme-CN.md +++ b/zh-cn/device-dev/quick-start/Readme-CN.md @@ -43,3 +43,6 @@ - 开发板介绍 - [Hi3516开发板介绍](quickstart-ide-standard-board-introduction-hi3516.md) - [RK3568开发板介绍](quickstart-ide-standard-board-introduction-rk3568.md) + - 快速入门(安装包方式) + - [轻量和小型系统快速入门](quickstart-lite-package-directory.md) + - [标准系统快速入门](quickstart-standard-package-directory.md) diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442129.png b/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442129.png deleted file mode 100644 index fbd3cb48f2cb35c02595be0293733644e16020bd..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442129.png and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442261.png b/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442261.png index fbd3cb48f2cb35c02595be0293733644e16020bd..c728580c57510fa2fe67a7e337492adae328d7ea 100644 Binary files a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442261.png and b/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001271442261.png differ diff --git a/zh-cn/device-dev/quick-start/quickstart-docker-lite.md b/zh-cn/device-dev/quick-start/quickstart-docker-lite.md index 6e091cdbb85386c862f3e2e10bd0226be71b3dc1..aafc6e81655de9c5e21aebfd2d9a73aa6b788f25 100644 --- a/zh-cn/device-dev/quick-start/quickstart-docker-lite.md +++ b/zh-cn/device-dev/quick-start/quickstart-docker-lite.md @@ -1,4 +1,4 @@ -# 轻量和小型系统快速入门-安装包 +# 轻量和小型系统快速入门(安装包方式) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-create-project.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-create-project.md index 9820c21f04f5ce23ed36a30f3dc7d80b299d01e6..6133d1ae6cd5de59b24126c076166cd618531c7b 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-create-project.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-create-project.md @@ -21,9 +21,9 @@ 5. 在Import Project界面,选择**Product**后,会自动填充对应的MCU、Board、company和kernel信息,然后**ohosVersion**选择对应的OpenHarmony源码版本。下图以导入wifiiot_hispark_pegasus为例进行说明。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > Hi3861开发板Product选择“wifiiot_hispark_pegasus”。 + > - Hi3861开发板Product选择“wifiiot_hispark_pegasus”。 > - > Hi3516DV300开发板Product选择“ipcamera_hispark_taurus”。 + > - Hi3516DV300开发板Product选择“ipcamera_hispark_taurus”。 ![zh-cn_image_0000001271237241](figures/zh-cn_image_0000001271237241.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-env-setup-win-ubuntu.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-env-setup-win-ubuntu.md index 2bf28b4adb6e0e984586b6056f95cf1a28b6fbc1..d08f1aa776dee42211a1ef886d24511355426e36 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-env-setup-win-ubuntu.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-env-setup-win-ubuntu.md @@ -58,7 +58,7 @@ ``` - sudo ./devicetool-linux-tool-3.0.0.300.sh + sudo ./devicetool-linux-tool-3.0.0.400.sh ``` 安装完成后,当界面输出“Deveco Device Tool successfully installed.”时,表示DevEco Device Tool安装成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-overview.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-overview.md index aeeed1e4c43745f82601582268643ff7fc193aa9..3f1b6b56cb815e006e5f4ce5ccf7b9f3a108ebc4 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-overview.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-overview.md @@ -12,7 +12,7 @@ OpenHarmony轻量和小型系统适用于内存较小的IOT设备(参考内存 - 安装包方式:通过命令行进行编译依赖工具的下载安装,编译操作也通过命令实现。烧录、运行等操作使用IDE。 OpenHarmony还为开发者提供了[Docker环境](../get-code/gettools-acquire.md),在很大程度上简化了编译前的环境配置,习惯使用安装包方式的开发者也可以选择Docker环境进行编译 。 -本文采用Deveco Device Tool进行一站式开发介绍,习惯使用命令行的开发者可参考[轻量和小型系统快速入门(安装包方式)](../quick-start/quickstart-docker-lite.md)。 +本文采用Deveco Device Tool进行一站式开发介绍,习惯使用命令行的开发者可参考[轻量和小型系统快速入门(安装包方式)](../quick-start/quickstart-lite-package-directory.md)。 ## 开发环境 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-sourcecode-acquire.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-sourcecode-acquire.md index 992c99c9d3729cfdf248b204a8a1234f34cedaf0..4558077deaccbf400db66d5d8c3a3da352df9b2c 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-sourcecode-acquire.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-sourcecode-acquire.md @@ -10,7 +10,7 @@ 2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装git客户端和git-lfs。(上述工具已在搭建环境章节安装。如已安装,请忽略) +3. 安装git客户端和git-lfs。 更新软件源: @@ -47,6 +47,7 @@ > Master主干为开发分支,开发者可通过Master主干获取最新特性。发布分支代码相对比较稳定,开发者可基于发布分支代码进行商用功能开发。 - **OpenHarmony主干代码获取** + 方式一(推荐):通过repo + ssh下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 ``` @@ -65,10 +66,11 @@ ``` - **OpenHarmony发布分支代码获取** + OpenHarmony各个版本发布分支的源码获取方式请参考[Release-Notes](../../release-notes/Readme.md)。 -### 执行prebuilts +## 执行prebuilts 在源码根目录下执行prebuilts脚本,安装编译器及二进制工具。 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-application-framework.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-application-framework.md index ef824fc8fb8e6f7c8d7bf8cd619d1a7a34d107da..928049b41efe3db8ca86b6b36dd276421ec285d6 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-application-framework.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-application-framework.md @@ -23,6 +23,7 @@ applications/sample/hello 请在源码目录中通过以下步骤创建“Hello World”应用程序: 1. 新建目录及源码。 + 新建**applications/sample/hello/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 @@ -40,6 +41,7 @@ applications/sample/hello ``` 2. 新建编译组织文件。 + 新建**applications/sample/hello/BUILD.gn**文件,内容如下所示: @@ -55,6 +57,7 @@ applications/sample/hello ``` 3. 添加新组件。 + 修改文件**build/lite/components/applications.json**,添加组件hello_world_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): @@ -117,6 +120,7 @@ applications/sample/hello ``` 4. 修改单板配置文件。 + 修改文件**vendor/hisilicon/hispark_taurus/config.json**,新增hello_world_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-running.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-running.md index 353bf9f1581f24175927eeca7947b3ad44296396..75a7b6809c19bbaf3ca27251b38985911cd7de91 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-running.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3516-running.md @@ -12,12 +12,15 @@ ![zh-cn_image_0000001226794644](figures/zh-cn_image_0000001226794644.png) 2. 提示如下图中的重启开发板的提示信息时,重启开发板,然后在控制台输出“SUCCESS”表示设置成功。 + ![zh-cn_image_0000001227114584](figures/zh-cn_image_0000001227114584.png) 3. 在任务栏点击**Monitor**按钮,启动串口工具。 + ![zh-cn_image_0000001271234705](figures/zh-cn_image_0000001271234705.png) 4. 当界面打印回显信息,点击Enter按钮,直到界面显示OHOS \#信息,表示系统启动成功。 + ![zh-cn_image_0000001271594709](figures/zh-cn_image_0000001271594709.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-application-framework.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-application-framework.md index 023fca41a0925099ea0a94f119e45545f17cfd27..f9adf40d8b20a2fd6ff4610a3b1416805bf7e581 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-application-framework.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-application-framework.md @@ -5,6 +5,7 @@ 1. 确定目录结构。 + 开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 例如:在app下新增业务my_first_app,其中hello_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下: @@ -22,6 +23,7 @@ ``` 2. 编写业务代码。 + 新建./applications/sample/wifi-iot/app/my_first_app下的hello_world.c文件,在hello_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动恢复模块接口SYS_RUN()启动业务。(SYS_RUN定义在ohos_init.h文件中) ``` @@ -37,6 +39,7 @@ ``` 3. 编写用于将业务构建成静态库的BUILD.gn文件。 + 新建./applications/sample/wifi-iot/app/my_first_app下的BUILD.gn文件,并完成如下配置。 如步骤1所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 @@ -58,6 +61,7 @@ - include_dirs中指定source所需要依赖的.h文件路径。 4. 添加新组件。 + 修改文件**build/lite/components/applications.json**,添加组件hello_world_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): @@ -120,6 +124,7 @@ ``` 5. 修改单板配置文件。 + 修改文件**vendor/hisilicon/hispark_pegasus/config.json**,新增hello_world_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-netconfig.md b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-netconfig.md index b9262ff4b85b92f07cb1137c8c95e3fe2db10baf..24949702fdf8e661836459439037f2ee07520829 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-netconfig.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-lite-steps-hi3861-netconfig.md @@ -5,11 +5,15 @@ 1. 保持Windows工作台和Hi3861 WLAN模组的连接状态,在DevEco工具最下方,点击“DevEco:Serial Monitor”按钮。 + **图1** 打开DevEco串口终端示意图 + ![zh-cn_image_0000001226634700](figures/zh-cn_image_0000001226634700.png) 2. 复位Hi3861 WLAN模组,终端界面显示“ready to OS start”,则启动成功。 + **图2** Hi3861 WLAN模组复位成功示意图 + ![zh-cn_image_0000001271594733](figures/zh-cn_image_0000001271594733.png) 3. 在DevEco的串口终端中,依次执行如下AT命令,启动STA模式,连接指定AP热点,并开启DHCP功能。 @@ -31,4 +35,5 @@ ``` **图3** Hi3861 WLAN模组联网成功示意图 + ![zh-cn_image_0000001227114612](figures/zh-cn_image_0000001227114612.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-hi3516.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-hi3516.md index 697ac159e15e3d19107ca8cb5677916e5c9d0100..fe7e28246dea89f0f07384d7ce5d1401a1229972 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-hi3516.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-hi3516.md @@ -6,6 +6,7 @@ Hi3516DV300是新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP(Image Signal Processor)、H.265视频压缩编码器、高性能NNIE引擎,在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 **图1** Hi3516单板正面外观图 + ![zh-cn_image_0000001227082182](figures/zh-cn_image_0000001227082182.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-rk3568.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-rk3568.md index f67dd25dd4cb79fcecfccfb21ba2bc26c1f76c8f..538e87de8e98b52b799cdfd6f7671220ccf8d7f2 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-rk3568.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-board-introduction-rk3568.md @@ -6,7 +6,7 @@ RK3568开发板基于Rockchip RK3568芯片,集成双核心架构GPU以及高效能NPU;搭载四核64位Cortex-A55处理器,采用22nm先进工艺,主频高达2.0GHz;支持蓝牙、Wi-Fi、音频、视频和摄像头等功能,拥有丰富的扩展接口,支持多种视频输入输出接口;配置双千兆自适应RJ45以太网口,可满足NVR、工业网关等多网口产品需求。 **图1** RK3568开发板正面 - ![zh-cn_image_0000001271442129](figures/zh-cn_image_0000001271442129.png) + ![zh-cn_image_0000001271442129](figures/zh-cn_image_0000001271442261.png) **图2** RK3568开发板背面 ![zh-cn_image_0000001271322293](figures/zh-cn_image_0000001271322293.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-create-project.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-create-project.md index 684c3c56dd23050d74fcf90d1e6be6e41eebb6e3..a2a960e99b95916a2293c63c47372cc8c992e596 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-create-project.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-create-project.md @@ -21,9 +21,9 @@ 5. 在Import Project界面,选择**Product**后,会自动填充对应的MCU、Board、company和kernel信息,然后**ohosVersion**选择对应的OpenHarmony源码版本。下图以导入Hi3516DV300为例进行展示 。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > Hi3516DV300开发板Product选择“Hi3516DV300”。 + > - Hi3516DV300开发板Product选择“Hi3516DV300”。 > - > RK3568开发板Product选择“rk3568”。 + > - RK3568开发板Product选择“rk3568”。 ![zh-cn_image_0000001271448821](figures/zh-cn_image_0000001271448821.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-env-setup-win-ubuntu.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-env-setup-win-ubuntu.md index 116c938b327cc6c762d1e882c875b276601a6642..ea31b2dfe324de6b5ab3ebdff6bc8afbab034d31 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-env-setup-win-ubuntu.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-env-setup-win-ubuntu.md @@ -58,7 +58,7 @@ ``` - sudo ./devicetool-linux-tool-3.0.0.300.sh + sudo ./devicetool-linux-tool-3.0.0.400.sh ``` 安装完成后,当界面输出“Deveco Device Tool successfully installed.”时,表示DevEco Device Tool安装成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-overview.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-overview.md index 2f3537d4a3081a50af2b789937c33ebaa478a036..a63a062889da8bdf6e09308e52abb0a511060977 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-overview.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-overview.md @@ -12,7 +12,7 @@ OpenHarmony标准系统适用于参考内存≥128MiB的设备。通过本文, - 安装包方式:通过命令行进行编译依赖工具的下载安装,编译操作也通过命令实现。烧录、运行等操作使用IDE。 OpenHarmony还为开发者提供了[Docker环境](../get-code/gettools-acquire.md),在很大程度上简化了编译前的环境配置,习惯使用安装包方式的开发者也可以选择Docker环境进行编译 。 -本文采用Deveco Device Tool进行一站式开发介绍,习惯使用命令行的开发者可参考[标准系统快速入门(安装包方式)](../quick-start/quickstart-standard-docker.md)。 +本文采用Deveco Device Tool进行一站式开发介绍,习惯使用命令行的开发者可参考[标准系统快速入门(安装包方式)](../quick-start/quickstart-standard-package-directory.md)。 ## 开发环境 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-hi3516-create.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-hi3516-create.md index 2a72e8ff9a9fd2f5166214021270237f53fa32bc..c7048712ad9dab9171b7069981843f62d564f21f 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-hi3516-create.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-hi3516-create.md @@ -31,6 +31,7 @@ productdefine/common 1. 创建目录,编写业务代码。 + 新建applications/sample/hello/src/helloworld.c目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改World为OHOS)。其中helloworld.h包含字符串打印函数HelloPrint的声明。当前应用程序可支持标准C及C++的代码开发。 @@ -75,6 +76,7 @@ productdefine/common ``` 2. 新建编译组织文件。 + 1. 新建applications/sample/hello/BUILD.gn文件,内容如下所示: ``` @@ -136,6 +138,7 @@ productdefine/common bundle.json文件包含两个部分,第一部分描述该部件所属子系统的信息,第二部分component则定义该部件构建相关配置。添加的时候需要指明该部件包含的模块sub_component,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test中说明,inner_kits与test没有也可以不添加。 3. 修改子系统配置文件。 + 在build/subsystem_config.json中添加新建的子系统的配置。 @@ -147,6 +150,7 @@ productdefine/common ``` 4. 修改产品配置文件。 + 在productdefine\common\products\Hi3516DV300.json中添加对应的hello部件,直接添加到原有部件后即可。 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-build.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-build.md index a12939ff92479c07d507a55b1d400d59211b5766..321f4955fe0fd376c13b9484e7b2808c109d9c99 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-build.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-build.md @@ -2,6 +2,7 @@ 1. 在Projects中,点击**Settings**按钮,进入HH-SCDY200配置界面。 + ![zh-cn_image_0000001221036768](figures/zh-cn_image_0000001221036768.png) 2. 在toolchain页签中,DevEco Device Tool会自动检测依赖的编译工具链是否完备,如果提示部分工具缺失,可点击**SetUp**按钮,自动安装所需工具链。 @@ -15,12 +16,15 @@ ![zh-cn_image_0000001265676877](figures/zh-cn_image_0000001265676877.png) 3. 在“hh_scdy200”配置页签中,设置源码的编译类型**build_type**,默认为"debug类型,请根据需要进行修改。然后点击**Save**按钮进行保存。 + ![zh-cn_image_0000001265956897](figures/zh-cn_image_0000001265956897.png) 4. 在DevEco Device Tool界面的“PROJECT TASKS”中,点击对应开发板下的**Build**按钮,执行编译。 + ![zh-cn_image_0000001265516901](figures/zh-cn_image_0000001265516901.png) 5. 等待编译完成,在**TERMINAL**窗口输出“SUCCESS”,编译完成。 + ![zh-cn_image_0000001222361042](figures/zh-cn_image_0000001222361042.png) 编译完成后,可以在工程的**out**目录下,查看编译生成的文件,用于后续的[RK3568开发板烧录](https://device.harmonyos.com/cn/docs/documentation/guide/ide-rk3568-upload-0000001239220669)。 diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-burning.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-burning.md index c7a8a120ec1311e509e5d42b9c2c01c8d7b1305a..7ba3557cb8ee93b639efda18dd18e7f7180e5fbc 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-burning.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-burning.md @@ -17,6 +17,7 @@ > 该操作仅在远程模式(Windows+Ubuntu混合开发环境)中需要设置,如果采用本地模式(Windows开发环境或Ubuntu开发环境),则请跳过该步骤。 4. 打开DevEco Device Tool,在QUICK ACCESS > DevEco Home > Projects中,点击**Settings**打开工程配置界面。 + ![zh-cn_image_0000001239661509](figures/zh-cn_image_0000001239661509.png) 5. 在“hh_scdy200”页签,设置烧录选项,包括upload_partitions和upload_protocol。 @@ -27,6 +28,7 @@ 6. 分别检查待烧录文件的烧录信息,DevEco Device Tool已预置默认的烧录文件信息,可根据实际情况进行调整。待烧录文件包括:loader、parameter、uboot、boot_linux、system、vendor和userdata。 1. 在“hh_scdy200_loader”页签,在New Option选项中选择需要修改的项,例如partition_bin(烧录文件路径)、partition_addr(烧录文件起始地址)、partition_length(烧录文件分区长度)等。 + ![zh-cn_image_0000001224173270](figures/zh-cn_image_0000001224173270.png) 2. 然后在Partition Options中,分别修改上述步骤中选择的修改项。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** @@ -38,7 +40,9 @@ 7. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 8. 点击工程的Open按钮,打开工程文件,点击![zh-cn_image_0000001239221905](figures/zh-cn_image_0000001239221905.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hh_scdy200下的**Upload**按钮,启动烧录。 + ![zh-cn_image_0000001194821710](figures/zh-cn_image_0000001194821710.png) 9. 等待开发板烧录完成,当屏幕提示如下信息时,表示烧录成功。 + ![zh-cn_image_0000001194984912](figures/zh-cn_image_0000001194984912.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-create.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-create.md index 24504ab8403272d1bf5ac9c695e98579240df8f8..40beafc0ed8a27762ef6afbcdfb83ef93deb1fd0 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-create.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-running-rk3568-create.md @@ -30,6 +30,7 @@ productdefine/common 请在源码目录中通过以下步骤创建“Hello World”应用程序: 1. 创建目录,编写业务代码。 + 新建applications/sample/hello/src/helloworld.c目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改World为OHOS)。其中helloworld.h包含字符串打印函数HelloPrint的声明。当前应用程序可支持标准C及C++的代码开发。 @@ -74,6 +75,7 @@ productdefine/common ``` 2. 新建编译组织文件。 + 1. 新建applications/sample/hello/BUILD.gn文件,内容如下所示: ``` @@ -135,6 +137,7 @@ productdefine/common bundle.json文件包含两个部分,第一部分描述该部件所属子系统的信息,第二部分component则定义该部件构建相关配置。添加的时候需要指明该部件包含的模块sub_component,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test中说明,inner_kits与test没有也可以不添加。 3. 修改子系统配置文件。 + 在build/subsystem_config.json中添加新建的子系统的配置。 @@ -146,6 +149,7 @@ productdefine/common ``` 4. 修改产品配置文件。 + 在productdefine\common\products\rk3568.json中添加对应的hello部件,直接添加到原有部件后即可。 ``` diff --git a/zh-cn/device-dev/quick-start/quickstart-ide-standard-sourcecode-acquire.md b/zh-cn/device-dev/quick-start/quickstart-ide-standard-sourcecode-acquire.md index 59843fe019d59a205bf116a1708b12471c1c7d3f..aba0a3439fffb157d2b72498621bfb2d6576eeff 100644 --- a/zh-cn/device-dev/quick-start/quickstart-ide-standard-sourcecode-acquire.md +++ b/zh-cn/device-dev/quick-start/quickstart-ide-standard-sourcecode-acquire.md @@ -10,7 +10,7 @@ 2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装git客户端和git-lfs。(上述工具已在搭建环境章节安装。如已安装,请忽略) +3. 安装git客户端和git-lfs。 更新软件源: @@ -41,12 +41,13 @@ ``` -## 获取方式 +## 获取源码 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > Master主干为开发分支,开发者可通过Master主干获取最新特性。发布分支代码相对比较稳定,开发者可基于发布分支代码进行商用功能开发。 - **OpenHarmony主干代码获取** + 方式一(推荐):通过repo + ssh下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 ``` @@ -65,10 +66,11 @@ ``` - **OpenHarmony发布分支代码获取** + OpenHarmony各个版本发布分支的源码获取方式请参考[Release-Notes](../../release-notes/Readme.md)。 -### 执行prebuilts +## 执行prebuilts 在源码根目录下执行prebuilts脚本,安装编译器及二进制工具。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md index f8a8d1d3a146e7012eecc5b565b3c79329cadf9b..fe9191801bf985819cda71f947ecf89bb43482f0 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md @@ -132,7 +132,7 @@ ``` - sudo ./devicetool-linux-tool-3.0.0.300.sh + sudo ./devicetool-linux-tool-3.0.0.400.sh ``` 安装完成后,当界面输出“Deveco Device Tool successfully installed.”时,表示DevEco Device Tool安装成功。 @@ -273,6 +273,7 @@ > Master主干为开发分支,开发者可通过Master主干获取最新特性。发布分支代码相对比较稳定,开发者可基于发布分支代码进行商用功能开发。 - **OpenHarmony主干代码获取** + 方式一(推荐):通过repo + ssh下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 ``` @@ -291,6 +292,7 @@ ``` - **OpenHarmony发布分支代码获取** + OpenHarmony各个版本发布分支的源码获取方式请参考[Release-Notes](../../release-notes/Readme.md)。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-faq-burning.md b/zh-cn/device-dev/quick-start/quickstart-lite-faq-burning.md index e453b94f6f6cf01146057df9d819da873cf29349..a756edcd9dfd7ebb1611da4fb62e90aac8f98528 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-faq-burning.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-faq-burning.md @@ -4,38 +4,50 @@ ## 烧写选择串口后提示“Error: Opening COMxx: Access denied” - **现象描述** + 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 **图1** 打开串口失败图 + ![zh-cn_image_0000001226634728](figures/zh-cn_image_0000001226634728.png) - **可能原因** + 串口已经被占用。 - **解决办法** 1. 按图依次选择下拉框,查找带有serial-xx的终端。 + **图2** 查找是否存在占用串口的终端 + ![zh-cn_image_0000001226954644](figures/zh-cn_image_0000001226954644.png) 2. 点击标号中的垃圾桶图标,关闭串口。 + **图3** 关闭串口终端 + ![zh-cn_image_0000001271234761](figures/zh-cn_image_0000001271234761.png) 3. 重新点击烧写,选择串口并开始烧写程序。 + **图4** 重新启动烧写任务 + ![zh-cn_image_0000001271594765](figures/zh-cn_image_0000001271594765.png) ## Windows电脑与单板网络连接失败 - **现象描述** + 点击烧写并选择串口后,无法获取文件。 **图5** 网络不通,单板无法获取文件图 + ![zh-cn_image_0000001271234757](figures/zh-cn_image_0000001271234757.png) - **可能原因** + 单板网络与Windows电脑不联通。 Windows电脑防火墙未允许Visual Studio Code联网。 @@ -45,51 +57,67 @@ 1. 检查网线是否连接。 2. 点击Windows防火墙。 + **图6** 网络防火墙设置图 + ![zh-cn_image_0000001226634732](figures/zh-cn_image_0000001226634732.png) 3. 点击“允许应用通过防火墙”。 + **图7** 防火墙和网络保护界面图 + ![zh-cn_image_0000001271354749](figures/zh-cn_image_0000001271354749.png) 4. 查找Visual Studio Code应用。 + **图8** 查找Visual Studio Code应用图 + ![zh-cn_image_0000001271234765](figures/zh-cn_image_0000001271234765.png) 5. 勾选Visual Studio Code的专用和公用网络的访问权限。 + **图9** 允许Visual Studio Code应用访问网络 + ![zh-cn_image_0000001271474585](figures/zh-cn_image_0000001271474585.png) ## 烧写失败 - **现象描述** + 点击烧写并选择串口后,出现无法烧写的情况。 - **可能原因** + 安装IDE插件DevEco后未重启。 - **解决方法** + 重启IDE。 ## (Hi3516)串口无回显 - **现象描述** + 串口显示已连接,重启单板后,回车无任何回显。 - **可能原因1** + 串口连接错误。 - **解决办法** + 修改串口号。 - 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按[串口访问失败的步骤](#烧写选择串口后提示error-opening-comxx-access-denied)修改串口号。 + 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按“烧写选择串口后提示“Error: Opening COMxx: Access denied”修改串口号。 - **可能原因2** + 单板U-boot被损坏。 - **解决办法** + 烧写U-boot。 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 @@ -103,8 +131,11 @@ > Hi3518EV300:device\hisilicon\hispark_aries\sdk_liteos\uboot\out\boot\u-boot-hi3518ev300.bin 2. 根据USB烧写步骤烧写U-boot文件。 + 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/documentation/guide/ide-hi3516-upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/documentation/guide/ide-hi3518-upload-0000001057313128#section93591711580)中描述的烧写方法,选择对应单板的U-boot文件进行烧写。 3. 烧写完成后,登录串口如下图所示。 + **图10** U-boot烧写完成串口显示图 + ![zh-cn_image_0000001271234753](figures/zh-cn_image_0000001271234753.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-faq-compose.md b/zh-cn/device-dev/quick-start/quickstart-lite-faq-compose.md index 6ac98c5c566fd6bfcc0f5a8c676aa0e02c84ebdc..af9022ffa62633c6987cb7ca0fb7f170486b3619 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-faq-compose.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-faq-compose.md @@ -4,12 +4,15 @@ ## Linux编译服务器终端输入不识别的命令时提示“ImportError: No module named apt_pkg” - **现象描述** + Linux编译服务器终端输入不识别的命令时,提示"ImportError: No module named apt_pkg" - **可能原因** + python3 apt安装兼容性问题。 - **解决办法** + 执行如下命令重新安装python3-apt。 @@ -22,6 +25,7 @@ ## 编译构建过程中,提示找不到“python” - **现象描述** + 编译构建过程中出现以下错误: @@ -30,9 +34,11 @@ ``` - **可能原因**1 + 没有装python。 - **解决办法** + 请使用如下命令安装Python,下方以Python3.8为例。 @@ -41,11 +47,13 @@ ``` - **可能原因2** + usr/bin目录下没有python软链接 ![zh-cn_image_0000001271354745](figures/zh-cn_image_0000001271354745.png) - **解决办法** + 请运行以下命令添加软链接: @@ -64,12 +72,15 @@ ## 编译构建过程中,提示找不到“python3” - **现象描述** + ![zh-cn_image_0000001227114640](figures/zh-cn_image_0000001227114640.png) - **可能原因** + 没有装python3。 - **解决办法** + 请使用如下命令安装Python3。 @@ -81,6 +92,7 @@ ## 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH” - **现象描述** + 安装python3过程中出现以下错误: @@ -89,9 +101,11 @@ ``` - **可能原因** + 环境中未安装“gcc”。 - **解决办法** + 1. 通过命令“apt-get install gcc”在线安装。 2. 完成后,重新安装python3。 @@ -99,6 +113,7 @@ ## 安装python3过程中,提示“-bash: make: command not found” - **现象描述** + 安装python3过程中出现以下错误: @@ -107,9 +122,11 @@ ``` - **可能原因** + 环境中未安装“make”。 - **解决办法** + 1. 通过命令“apt-get install make”在线安装。 2. 完成后,重新安装python3。 @@ -117,6 +134,7 @@ ## 安装python3过程中,提示“No module named '_ctypes'” - **现象描述** + 安装python3过程中出现以下错误: @@ -125,9 +143,11 @@ ``` - **可能原因** + 环境中未安装“libffi”和“libffi-devel”。 - **解决办法** + 1. 通过命令“apt-get install libffi\* -y”,在线安装。 2. 完成后,重新安装python3。 @@ -135,6 +155,7 @@ ## 编译构建过程中,提示“No module named 'Crypto'” - **现象描述** + 编译构建过程中出现以下错误: @@ -143,9 +164,11 @@ ``` - **可能原因** + 环境中未安装“Crypto”。 - **解决办法** + 方法1:通过命令“pip3 install Crypto”,在线安装。 方法2:离线安装。 @@ -162,6 +185,7 @@ ## (Hi3861)编译构建过程中,提示“No module named 'ecdsa'” - **现象描述** + 编译构建过程中出现以下错误: @@ -170,9 +194,11 @@ ``` - **可能原因** + 环境中未安装“ecdsa”。 - **解决办法** + 方法1:通过命令“pip3 install ecdsa”,在线安装。 方法2:离线安装 @@ -189,6 +215,7 @@ ## (Hi3861)编译构建过程中,提示“Could not find a version that satisfies the requirement six>=1.9.0” - **现象描述** + 编译构建过程中出现以下错误: @@ -197,9 +224,11 @@ ``` - **可能原因** + 环境中未安装合适的“six”。 - **解决办法** + 方法1:通过命令“pip3 install six”,在线安装。 方法2:离线安装。 @@ -216,6 +245,7 @@ ## (Hi3861)编译构建过程中,提示找不到“-lgcc” - **现象描述** + 编译构建过程中出现以下错误: @@ -224,6 +254,7 @@ ``` - **可能原因** + 交叉编译器gcc_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。 @@ -232,6 +263,7 @@ ``` - **解决办法** + 重新修改gcc_riscv32的PATH,将多余的“/”删除。 @@ -243,6 +275,7 @@ ## (Hi3861)安装kconfiglib时,遇到lsb_release错误 - **现象描述** + 安装kconfiglib过程中遇到如下错误打印: @@ -251,7 +284,9 @@ ``` - **可能原因** + lsb_release模块基于的python版本与现有python版本不一致。 - **解决办法** + 执行"find / -name lsb_release",找到lsb_release位置并删除,如:"sudo rm -rf /usr/bin/lsb_release"。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-overview.md b/zh-cn/device-dev/quick-start/quickstart-lite-overview.md index 4051bf51f8aed3f6cba3f80915295824f3f4c771..291ad0accad339b86416c7656c503b7021110e6a 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-overview.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-overview.md @@ -10,12 +10,12 @@ OpenHarmony轻量和小型系统适用于内存较小的IOT设备(参考内存 考虑到开发者的开发习惯,OpenHarmony为开发者提供了以下两种入门指导: -- IDE方式:完全采用IDE(Deveco Device Tool)进行一站式开发,编译依赖工具的安装及编译、烧录、运行都通过IDE进行操作。 +- IDE方式:完全采用IDE(DevEco Device Tool)进行一站式开发,编译依赖工具的安装及编译、烧录、运行都通过IDE进行操作。 - 安装包方式:通过命令行进行编译依赖工具的下载安装,编译操作也通过命令实现。烧录、运行等操作使用IDE。OpenHarmony还为开发者提供了[Docker环境](../get-code/gettools-acquire.md),在很大程度上简化了编译前的环境配置,习惯使用安装包方式的开发者也可以选择Docker环境进行编译 。 -本文采用安装包方式进行介绍,习惯使用Deveco Device Tool的开发者可参考[标准系统快速入门(IDE方式)](../quick-start/quickstart-ide-lite.md)。 +本文采用安装包方式进行介绍,习惯使用DevEco Device Tool的开发者可参考[轻量与小型系统快速入门(IDE方式)](../quick-start/quickstart-ide-lite.md)。 ## 开发环境 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-package-directory.md b/zh-cn/device-dev/quick-start/quickstart-lite-package-directory.md new file mode 100644 index 0000000000000000000000000000000000000000..900fdcccf9837674e9c9cd72d63395884bebfd97 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-package-directory.md @@ -0,0 +1,27 @@ +## 轻量和小型系统快速入门(安装包方式) +- [轻量与小型系统入门概述](quickstart-lite-overview.md) +- [搭建轻量与小型系统环境](quickstart-lite-env-setup.md) +- 运行“Hello World” + - Hi3861开发板 + - [安装Hi3861开发板环境](quickstart-lite-steps-hi3861-setting.md) + - [编写“Hello World”程序](quickstart-lite-steps-hi3861-application-framework.md) + - [编译](quickstart-lite-steps-hi3861-building.md) + - [烧录](quickstart-lite-steps-hi3861-burn.md) + - [联网](quickstart-lite-steps-hi3861-netconfig.md) + - [调试验证](quickstart-lite-steps-hi3861-debug.md) + - [运行](quickstart-lite-steps-hi3816-running.md) + - Hi3516开发板 + - [安装Hi3516开发板环境](quickstart-lite-steps-hi3516-setting.md) + - [编写“Hello World”程序](quickstart-lite-steps-hi3516-application-framework.md) + - [编译](quickstart-lite-steps-hi3516-building.md) + - [烧录](quickstart-lite-steps-hi3516-burn.md) + - [运行](quickstart-lite-steps-hi3516-running.md) +- 常见问题 + - [hb安装异常](quickstart-lite-faq-hb.md) + - [编译异常](quickstart-lite-faq-compose.md) + - [烧录异常](quickstart-lite-faq-burning.md) +- 附录 + - 开发板介绍 + - [Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md) + - [Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md) + - [参考信息](quickstart-lite-reference.md) diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-application-framework.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-application-framework.md index ef824fc8fb8e6f7c8d7bf8cd619d1a7a34d107da..928049b41efe3db8ca86b6b36dd276421ec285d6 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-application-framework.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-application-framework.md @@ -23,6 +23,7 @@ applications/sample/hello 请在源码目录中通过以下步骤创建“Hello World”应用程序: 1. 新建目录及源码。 + 新建**applications/sample/hello/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 @@ -40,6 +41,7 @@ applications/sample/hello ``` 2. 新建编译组织文件。 + 新建**applications/sample/hello/BUILD.gn**文件,内容如下所示: @@ -55,6 +57,7 @@ applications/sample/hello ``` 3. 添加新组件。 + 修改文件**build/lite/components/applications.json**,添加组件hello_world_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): @@ -117,6 +120,7 @@ applications/sample/hello ``` 4. 修改单板配置文件。 + 修改文件**vendor/hisilicon/hispark_taurus/config.json**,新增hello_world_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-building.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-building.md index eb1637b718847ace23df761ee99bec9f58595c5d..89bf784576bed77ba4c20145d8a88ac7a376ac3e 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-building.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-building.md @@ -1,7 +1,7 @@ # 编译 -OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-lite-reference.md#使用buildsh脚本编译源码)。 +OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-lite-reference.md)。 请进入源码根目录,执行如下命令进行编译: @@ -38,6 +38,7 @@ OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build. **图1** Hi3516编译设置图例 + ![zh-cn_image_0000001271594749](figures/zh-cn_image_0000001271594749.png) 5. 编译结束后,出现“build success”字样,则证明构建成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-burn.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-burn.md index 06a58a13fc00e560c944d6469ffef54bcbdc82a4..651283b7f02ead65c9cd1680b3b3174f6d0e5176 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-burn.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-burn.md @@ -6,9 +6,10 @@ Hi3516DV300支持USB烧录、网口烧录和串口烧录三种方式,本文采 ### 导入源码 -在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-lite-env-setup.md#安装deveco-device-tool)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 +在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-lite-env-setup.md)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 1. 打开DevEco Device Tool,进入Home页,点击**Import Project**打开工程。 + ![zh-cn_image_0000001171426014](figures/zh-cn_image_0000001171426014.png) 2. 选择要导入的源码目录(需要访问Ubuntu下的源码目录),点击**Import**打开。 @@ -18,12 +19,15 @@ Hi3516DV300支持USB烧录、网口烧录和串口烧录三种方式,本文采 ![zh-cn_image_0000001271791385](figures/zh-cn_image_0000001271791385.png) 3. 如果您打开的目录不是DevEco Device Tool工程,则会出现如下提示框,点击**Import**。 + ![zh-cn_image_0000001135394334](figures/zh-cn_image_0000001135394334.png) 4. 在Select Project type界面,选择**Import from OpenHarmony Source**。 + ![zh-cn_image_0000001215743910](figures/zh-cn_image_0000001215743910.png) 5. 在Import Project界面,选择**Product**后,会自动填充对应的MCU、Board、company和kernel信息,然后**ohosVersion**选择对应的OpenHarmony源码版本。此处选择ipcamera_hispark_taurus。 + ![zh-cn_image_0000001227711014](figures/zh-cn_image_0000001227711014.png) 6. 点击**Open**打开工程或源码。 @@ -45,12 +49,14 @@ Hi3516DV300支持USB烧录、网口烧录和串口烧录三种方式,本文采 > 该操作仅在远程模式(Windows+Ubuntu混合开发环境)中需要设置,如果采用本地模式(Windows开发环境或Ubuntu开发环境),则请跳过该步骤。 3. 在DevEco Device Tool中,点击QUICK ACCESS > DevEco Home > Device,查看并记录对应的串口号。 + ![zh-cn_image_0000001216516128](figures/zh-cn_image_0000001216516128.png) > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 如果对应的串口异常,请根据[Hi3516DV300/Hi3518EV300开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/documentation/guide/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 4. 在QUICK ACCESS > DevEco Home > Projects中,点击**Settings**打开工程配置界面。 + ![zh-cn_image_0000001198566364](figures/zh-cn_image_0000001198566364.png) 5. 在“hi3516dv300”页签,设置烧录选项,包括upload_partitions、upload_port和upload_protocol。 @@ -62,12 +68,14 @@ Hi3516DV300支持USB烧录、网口烧录和串口烧录三种方式,本文采 6. 分别检查待烧录文件的烧录信息,DevEco Device Tool已预置默认的烧录文件信息,可根据实际情况进行调整。待烧录文件包括:fastboot、kernel、rootfs和userfs。 1. 在“hi3516dv300_fastboot”页签,在New Option选项中选择需要修改的项,例如partition_bin(烧录文件路径)、partition_addr(烧录文件起始地址)、partition_length(烧录文件分区长度)等。 + ![zh-cn_image_0000001198889702](figures/zh-cn_image_0000001198889702.png) 2. 然后在Partition Options中,分别修改上述步骤中选择的修改项。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 在设置烧录分区起始地址和分区长度时,应根据实际待烧录文件的大小进行设置,要求设置的烧录分区大小,要大于待烧录文件的大小;同时,各烧录文件的分区地址设置不能出现重叠。 ![zh-cn_image_0000001243290907](figures/zh-cn_image_0000001243290907.png) + 3. 按照相同的方法修改kernel、rootfs和userfs的烧录文件信息。 7. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 @@ -79,6 +87,7 @@ Hi3516DV300支持USB烧录、网口烧录和串口烧录三种方式,本文采 ![zh-cn_image_0000001267231481](figures/zh-cn_image_0000001267231481.png) 9. 在终端窗口显示如下提示信息时,按住复位键,插拔USB线,最后松开复位键启动烧录。 + ![zh-cn_image_0000001114129426](figures/zh-cn_image_0000001114129426.png) 启动烧录后,界面提示如下信息时,表示烧录成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-running.md index a830410fbf41a00b57ce137110acf5df6164ccec..aa37823b274564ff411d185529152dc07bb8aa49 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-running.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-running.md @@ -5,19 +5,22 @@ 在完成Hi3516DV300的烧录后,还需要设置BootLoader引导程序,才能运行OpenHarmony系统。 -1. 在Hi3516DV300任务中,点击**Configure bootloader(Boot OS)**进行配置即可。 +1. 在Hi3516DV300任务中,点击Configure bootloader(Boot OS)进行配置即可。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > DevEco Device Tool针对Hi3516DV300开发板的BootLoader设置进行了适配,无需开发者手动修改。 ![zh-cn_image_0000001209906547](figures/zh-cn_image_0000001209906547.png) 2. 提示如下图中的重启开发板的提示信息时,重启开发板,然后在控制台输出“SUCCESS”表示设置成功。 + ![zh-cn_image_0000001210385161](figures/zh-cn_image_0000001210385161.png) 3. 在任务栏点击**Monitor**按钮,启动串口工具。 + ![zh-cn_image_0000001164506870](figures/zh-cn_image_0000001164506870.png) 4. 当界面打印回显信息,点击Enter按钮,直到界面显示OHOS \#信息,表示系统启动成功。 + ![zh-cn_image_0000001198626874](figures/zh-cn_image_0000001198626874.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-setting.md index 6bea6069bf0347346ef1e90eda7e8c314d42c656..7ca83ab6a0b16495f32fefcf01f8590a72e8ab74 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-setting.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3516-setting.md @@ -27,4 +27,4 @@ Hi3516DV300开发板对Linux服务器通用环境配置需要的工具及其用 Hi3516DV300依赖以下工具:dosfstools、mtools、mtd-utils、Java运行时环境(JRE)和Java sdk 开发工具包。 -上述工具已在[ERROR:Invalid link:zh-cn_topic_0000001226794684.xml#xref126711502449,link:zh-cn_topic_0000001215745332.xml#section69901514104616](zh-cn_topic_0000001215745332.xml#section69901514104616)环节完成安装,此处无需再进行安装。 +上述工具已在[安装必要的库和工具](../quick-start/quickstart-lite-env-setup.md#安装必要的库和工具)环节完成安装,此处无需再进行安装。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-application-framework.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-application-framework.md index 268d097afdd10780fac6ea821645f3d932d47b71..f9adf40d8b20a2fd6ff4610a3b1416805bf7e581 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-application-framework.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-application-framework.md @@ -5,6 +5,7 @@ 1. 确定目录结构。 + 开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 例如:在app下新增业务my_first_app,其中hello_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下: @@ -22,6 +23,7 @@ ``` 2. 编写业务代码。 + 新建./applications/sample/wifi-iot/app/my_first_app下的hello_world.c文件,在hello_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动恢复模块接口SYS_RUN()启动业务。(SYS_RUN定义在ohos_init.h文件中) ``` @@ -37,9 +39,10 @@ ``` 3. 编写用于将业务构建成静态库的BUILD.gn文件。 + 新建./applications/sample/wifi-iot/app/my_first_app下的BUILD.gn文件,并完成如下配置。 - 如[ERROR:Invalid link:zh-cn_topic_0000001226794672.xml#xref7209204195912,link:#li5479332115116](#li5479332115116)所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 + 如步骤1所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 ``` @@ -58,6 +61,7 @@ - include_dirs中指定source所需要依赖的.h文件路径。 4. 添加新组件。 + 修改文件**build/lite/components/applications.json**,添加组件hello_world_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): @@ -120,6 +124,7 @@ ``` 5. 修改单板配置文件。 + 修改文件**vendor/hisilicon/hispark_pegasus/config.json**,新增hello_world_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-building.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-building.md index 3e44436ad88d4d3ba20c29d7fa873f781d32de4d..bad910ee574a34833c59b3ee228ca8cdc4a9513e 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-building.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-building.md @@ -1,7 +1,7 @@ # 编译 -OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-lite-reference.md#使用buildsh脚本编译源码)。 +OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-lite-reference.md)。 在Ubuntu环境下进入源码根目录,执行如下命令进行编译: @@ -37,6 +37,7 @@ OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build. ``` **图1** Hi3861编译设置图例 + ![zh-cn_image_0000001226634716](figures/zh-cn_image_0000001226634716.png) 5. 编译结束后,出现“build success”字样,则证明构建成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-burn.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-burn.md index 2a424c8b7840536a58cdbc541fbb3312c23e8dae..c490c8ada2df92fad78d350c56e6426f951c6847 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-burn.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-burn.md @@ -6,9 +6,10 @@ ### 导入源码 -在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-lite-env-setup.md#安装deveco-device-tool)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 +在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-lite-env-setup.md)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 1. 打开DevEco Device Tool,进入Home页,点击**Import Project**打开工程。 + ![zh-cn_image_0000001171426014](figures/zh-cn_image_0000001171426014.png) 2. 选择要导入的源码目录(需要访问Ubuntu下的源码目录),点击**Import**打开。 @@ -18,12 +19,15 @@ ![zh-cn_image_0000001227549226](figures/zh-cn_image_0000001227549226.png) 3. 如果您打开的目录不是DevEco Device Tool工程,则会出现如下提示框,点击**Import**。 + ![zh-cn_image_0000001135394334](figures/zh-cn_image_0000001135394334.png) 4. 在Select Project type界面,选择**Import from OpenHarmony Source**。 + ![zh-cn_image_0000001215743910](figures/zh-cn_image_0000001215743910.png) 5. 在Import Project界面,选择**Product**后,会自动填充对应的MCU、Board、company和kernel信息,然后**ohosVersion**选择对应的OpenHarmony源码版本。此处选择wifiiot_hispark_pegasus。 + ![zh-cn_image_0000001272109325](figures/zh-cn_image_0000001272109325.png) 6. 点击**Open**打开工程或源码。 @@ -45,12 +49,14 @@ > 该操作仅在远程模式(Windows+Ubuntu混合开发环境)中需要设置,如果采用本地模式(Windows开发环境或Ubuntu开发环境),则请跳过该步骤。 3. 在DevEco Device Tool中,点击QUICK ACCESS > DevEco Home > Device,查看并记录对应的串口号。 + ![zh-cn_image_0000001216274840](figures/zh-cn_image_0000001216274840.png) > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 如果对应的串口异常,请根据[Hi3861V100开发板串口驱动安装](https://device.harmonyos.com/cn/docs/documentation/guide/hi3861-drivers-0000001058153433)安装USB转串口的驱动程序。 4. 在QUICK ACCESS > DevEco Home > Projects中,点击**Settings**打开工程配置界面。 + ![zh-cn_image_0000001198943768](figures/zh-cn_image_0000001198943768.png) 5. 在“hi3861”页签,设置烧录选项,包括upload_port、upload_protocol和upload_partitions。 @@ -68,10 +74,13 @@ 7. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 8. 点击**Open**打开工程文件,然后在“PROJECT TASKS”中,点击hi3861下的**Upload**按钮,启动烧录。 + ![zh-cn_image_0000001216440138](figures/zh-cn_image_0000001216440138.png) 9. 启动烧录后,显示如下提示信息时,请按开发板上的RST按钮重启开发板。 + ![zh-cn_image_0000001198466090](figures/zh-cn_image_0000001198466090.png) 10. 重新上电后,界面提示如下信息时,表示烧录成功。 + ![zh-cn_image_0000001216761476](figures/zh-cn_image_0000001216761476.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-netconfig.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-netconfig.md index 4074626b3f5ce72fcd486b43bebefbd807a52526..df0476f026ea94e874217c578d28eb9ec2224d7f 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-netconfig.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-netconfig.md @@ -5,11 +5,15 @@ 1. 保持Windows工作台和WLAN模组的连接状态,在DevEco Device Tool最下方,点击“DevEco:Serial Monitor”按钮。 + **图1** 打开DevEco Device Tool串口终端示意图 + ![zh-cn_image_0000001227114644](figures/zh-cn_image_0000001227114644.png) 2. 复位Hi3861 WLAN模组,终端界面显示“ready to OS start”,则启动成功。 + **图2** Hi3861 WLAN模组复位成功示意图 + ![zh-cn_image_0000001226794704](figures/zh-cn_image_0000001226794704.png) 3. 在串口终端中,依次执行如下AT命令,启动STA模式,连接指定AP热点,并开启DHCP功能。 @@ -35,4 +39,5 @@ ``` **图3** Hi3861 WLAN模组联网成功示意图 + ![zh-cn_image_0000001226954648](figures/zh-cn_image_0000001226954648.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-setting.md index 662521525dc8ca426f6d1b1e95e1750e26e6d41f..f059ef1160e496cb83f43d5b4b124b9b91521126 100644 --- a/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-setting.md +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-hi3861-setting.md @@ -178,63 +178,63 @@ Hi3861 WLAN模组需要的工具如下表所示。 10. 下载[mpc-1.1.0](https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz) ,并解压安装。 - ``` - tar -xvf mpc-1.1.0.tar.gz && mkdir build_mpc && cd build_mpc && ../mpc-1.1.0/configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 --disable-shared && make && make install - ``` + ``` + tar -xvf mpc-1.1.0.tar.gz && mkdir build_mpc && cd build_mpc && ../mpc-1.1.0/configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 --disable-shared && make && make install + ``` 11. 打开文件夹riscv-gnu-toolchain,新建工具链输出目录。 - ``` - cd /opt && mkdir gcc_riscv32 - ``` + ``` + cd /opt && mkdir gcc_riscv32 + ``` 12. 编译binutils。 - ``` - mkdir build_binutils && cd build_binutils && ../riscv-binutils-gdb/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32/riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. - ``` + ``` + mkdir build_binutils && cd build_binutils && ../riscv-binutils-gdb/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32/riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. + ``` 13. 编译newlib。 - ``` - mkdir build_newlib && cd build_newlib && ../riscv-newlib/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" \CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. - ``` + ``` + mkdir build_newlib && cd build_newlib && ../riscv-newlib/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" \CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. + ``` 14. 编译gcc。 - ``` - mkdir build_gcc && cd build_gcc && ../riscv-gcc/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" LDFLAGS="-Wl,-z,relro,-z,now,-z,noexecstack" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --with-headers="/opt/gcc-riscv32/riscv32-unknown-elf/include" --with-mpc=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 && make -j16 && make install - ``` + ``` + mkdir build_gcc && cd build_gcc && ../riscv-gcc/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" LDFLAGS="-Wl,-z,relro,-z,now,-z,noexecstack" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --with-headers="/opt/gcc-riscv32/riscv32-unknown-elf/include" --with-mpc=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 && make -j16 && make install + ``` 15. 设置环境变量。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > 如果直接采用编译好的riscv32 gcc包,请先执行以下命令将压缩包解压到根目录: - > - > ``` - > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ - > ``` + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 如果直接采用编译好的riscv32 gcc包,请先执行以下命令将压缩包解压到根目录: + > + > ``` + > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ + > ``` - ``` - vim ~/.bashrc - ``` + ``` + vim ~/.bashrc + ``` - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - ``` - export PATH=~/gcc_riscv32/bin:$PATH - ``` + ``` + export PATH=~/gcc_riscv32/bin:$PATH + ``` 16. 生效环境变量。 - - ``` - source ~/.bashrc - ``` + + ``` + source ~/.bashrc + ``` 17. Shell命令行中输入如下命令,如果能正确显示编译器版本号,表明编译器安装成功。 - ``` - riscv32-unknown-elf-gcc -v - ``` + ``` + riscv32-unknown-elf-gcc -v + ``` diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-board-introduction-hi3516.md b/zh-cn/device-dev/quick-start/quickstart-standard-board-introduction-hi3516.md index fec43eee72f057d81f67ca087521509b32fb8135..15aec7eb2652f98587fd2756d50f3bf87a1dbe8c 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-board-introduction-hi3516.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-board-introduction-hi3516.md @@ -6,6 +6,7 @@ Hi3516DV300是新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP(Image Signal Processor)、H.265视频压缩编码器、高性能NNIE引擎,在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 **图1** Hi3516单板正面外观图 + ![zh-cn_image_0000001226922318](figures/zh-cn_image_0000001226922318.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-docker.md b/zh-cn/device-dev/quick-start/quickstart-standard-docker.md index 51a2f089be17798cbfc3ffde2c83555cf3bd016a..f1e5c764a287fcde725b1f6dcc6819f86aff1d7f 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-docker.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-docker.md @@ -1,4 +1,4 @@ -# 标准系统快速入门-安装包 +# 标准系统快速入门(安装包方式) diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-env-setup.md b/zh-cn/device-dev/quick-start/quickstart-standard-env-setup.md index e5ec2cc578573c768d394ca397c21fb95b732648..af990f632eb7627e24d7a1a960f56b1bdea36b68 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-env-setup.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-env-setup.md @@ -132,7 +132,7 @@ ``` - sudo ./devicetool-linux-tool-3.0.0.300.sh + sudo ./devicetool-linux-tool-3.0.0.400.sh ``` 安装完成后,当界面输出“Deveco Device Tool successfully installed.”时,表示DevEco Device Tool安装成功。 @@ -273,6 +273,7 @@ > Master主干为开发分支,开发者可通过Master主干获取最新特性。发布分支代码相对比较稳定,开发者可基于发布分支代码进行商用功能开发。 - **OpenHarmony主干代码获取** + 方式一(推荐):通过repo + ssh下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 ``` @@ -291,6 +292,7 @@ ``` - **OpenHarmony发布分支代码获取** + OpenHarmony各个版本发布分支的源码获取方式请参考[Release-Notes](../../release-notes/Readme.md)。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-faq-burning.md b/zh-cn/device-dev/quick-start/quickstart-standard-faq-burning.md index cc00c563c8c1264440e1ddd90ebe49ea82e37781..8cf38f261f4d8e637a7d91dcf3c1e2c635817260 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-faq-burning.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-faq-burning.md @@ -4,38 +4,50 @@ ## 烧写选择串口后提示“Error: Opening COMxx: Access denied” - **现象描述** + 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 **图1** 打开串口失败图 + ![zh-cn_image_0000001271202461](figures/zh-cn_image_0000001271202461.png) - **可能原因** + 串口已经被占用。 - **解决办法** 1. 按图依次选择下拉框,查找带有serial-xx的终端。 + **图2** 查找是否存在占用串口的终端 + ![zh-cn_image_0000001271202473](figures/zh-cn_image_0000001271202473.png) 2. 点击标号中的垃圾桶图标,关闭串口。 + **图3** 关闭串口终端 + ![zh-cn_image_0000001271202469](figures/zh-cn_image_0000001271202469.png) 3. 重新点击烧写,选择串口并开始烧写程序。 + **图4** 重新启动烧写任务 + ![zh-cn_image_0000001271562449](figures/zh-cn_image_0000001271562449.png) ## Windows电脑与单板网络连接失败 - **现象描述** + 点击烧写并选择串口后,无法获取文件。 **图5** 网络不通,单板无法获取文件图 + ![zh-cn_image_0000001226922306](figures/zh-cn_image_0000001226922306.png) - **可能原因** + 单板网络与Windows电脑不联通。 Windows电脑防火墙未允许Visual Studio Code联网。 @@ -45,29 +57,40 @@ 1. 检查网线是否连接。 2. 点击Windows防火墙。 + **图6** 网络防火墙设置图 + ![zh-cn_image_0000001227082322](figures/zh-cn_image_0000001227082322.png) 3. 点击“允许应用通过防火墙”。 + **图7** 防火墙和网络保护界面图 + ![zh-cn_image_0000001271202457](figures/zh-cn_image_0000001271202457.png) 4. 查找Visual Studio Code应用。 + **图8** 查找Visual Studio Code应用图 + ![zh-cn_image_0000001271562445](figures/zh-cn_image_0000001271562445.png) 5. 勾选Visual Studio Code的专用和公用网络的访问权限。 + **图9** 允许Visual Studio Code应用访问网络 + ![zh-cn_image_0000001271442273](figures/zh-cn_image_0000001271442273.png) ## 烧写失败 - **现象描述** + 点击烧写并选择串口后,出现无法烧写的情况。 - **可能原因** + 安装IDE插件DevEco后未重启。 - **解决方法** + 重启IDE。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-faq-compose.md b/zh-cn/device-dev/quick-start/quickstart-standard-faq-compose.md index 0ecd50095265f1bfa514b2282973f4be71b89184..b131626e75438b292390fa0315a83ec6d4cc3225 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-faq-compose.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-faq-compose.md @@ -4,12 +4,15 @@ ## Linux编译服务器终端输入不识别的命令时提示“ImportError: No module named apt_pkg” - **现象描述** + Linux编译服务器终端输入不识别的命令时,提示"ImportError: No module named apt_pkg" - **可能原因** + python3 apt安装兼容性问题。 - **解决办法** + 执行如下命令重新安装python3-apt。 @@ -22,6 +25,7 @@ ## 编译构建过程中,提示找不到“python” - **现象描述** + 编译构建过程中出现以下错误: @@ -30,9 +34,11 @@ ``` - **可能原因**1 + 没有装python。 - **解决办法** + 请使用如下命令安装Python,下方以Python3.8为例。 @@ -41,11 +47,13 @@ ``` - **可能原因2** + usr/bin目录下没有python软链接 ![zh-cn_image_0000001226922322](figures/zh-cn_image_0000001226922322.png) - **解决办法** + 请运行以下命令添加软链接: @@ -64,12 +72,15 @@ ## 编译构建过程中,提示找不到“python3” - **现象描述** + ![zh-cn_image_0000001226602414](figures/zh-cn_image_0000001226602414.png) - **可能原因** + 没有装python3。 - **解决办法** + 请使用如下命令安装Python3。 @@ -81,6 +92,7 @@ ## 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH” - **现象描述** + 安装python3过程中出现以下错误: @@ -89,9 +101,11 @@ ``` - **可能原因** + 环境中未安装“gcc”。 - **解决办法** + 1. 通过命令“apt-get install gcc”在线安装。 2. 完成后,重新安装python3。 @@ -99,6 +113,7 @@ ## 安装python3过程中,提示“-bash: make: command not found” - **现象描述** + 安装python3过程中出现以下错误: @@ -107,9 +122,11 @@ ``` - **可能原因** + 环境中未安装“make”。 - **解决办法** + 1. 通过命令“apt-get install make”在线安装。 2. 完成后,重新安装python3。 @@ -117,6 +134,7 @@ ## 安装python3过程中,提示“No module named '_ctypes'” - **现象描述** + 安装python3过程中出现以下错误: @@ -125,9 +143,11 @@ ``` - **可能原因** + 环境中未安装“libffi”和“libffi-devel”。 - **解决办法** + 1. 通过命令“apt-get install libffi\* -y”,在线安装。 2. 完成后,重新安装python3。 @@ -135,6 +155,7 @@ ## 编译构建过程中,提示“No module named 'Crypto'” - **现象描述** + 编译构建过程中出现以下错误: @@ -143,9 +164,11 @@ ``` - **可能原因** + 环境中未安装“Crypto”。 - **解决办法** + 方法1:通过命令“pip3 install Crypto”,在线安装。 方法2:离线安装。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-overview.md b/zh-cn/device-dev/quick-start/quickstart-standard-overview.md index e81b2e5784a59dd4b9da1c20f405c4145b6f394a..c3e39d1ca784e4c584d62008c10b7efb9622f1a3 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-overview.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-overview.md @@ -7,12 +7,12 @@ OpenHarmony标准系统适用于参考内存≥128MiB的设备。通过本文, 考虑到开发者的开发习惯,OpenHarmony为开发者提供了以下两种入门指导: -- IDE方式:完全采用IDE(Deveco Device Tool)进行一站式开发,编译依赖工具的安装及编译、烧录、运行都通过IDE进行操作。 +- IDE方式:完全采用IDE(DevEco Device Tool)进行一站式开发,编译依赖工具的安装及编译、烧录、运行都通过IDE进行操作。 - 安装包方式:通过命令行进行编译依赖工具的下载安装,编译操作也通过命令实现。烧录、运行等操作使用IDE。 OpenHarmony还为开发者提供了[Docker环境](../get-code/gettools-acquire.md),在很大程度上简化了编译前的环境配置,习惯使用安装包方式的开发者也可以选择Docker环境进行编译 。 -本文采用安装包方式进行介绍,习惯使用Deveco Device Tool的开发者可参考[标准系统快速入门(IDE方式)](../quick-start/quickstart-standard-ide.md)。 +本文采用安装包方式进行介绍,习惯使用DevEco Device Tool的开发者可参考[标准系统快速入门(IDE方式)](../quick-start/quickstart-standard-ide.md)。 ## 开发环境 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md b/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md new file mode 100644 index 0000000000000000000000000000000000000000..6b236d50280d1afc8fbed004103dfc7c61272713 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md @@ -0,0 +1,23 @@ +## 标准系统快速入门 +- [标准系统入门概述](quickstart-standard-overview.md) +- [搭建标准系统环境](quickstart-standard-env-setup.md) +- 运行“Hello World” + - Hi3516开发板 + - [编写“Hello World”程序](quickstart-standard-running-hi3516-create.md) + - [编译](quickstart-standard-running-hi3516-build.md) + - [烧录](quickstart-standard-running-hi3516-burning.md) + - [运行](quickstart-standard-running-hi3516-running.md) + - RK3568开发板 + - [编写“Hello World”程序](quickstart-standard-running-rk3568-create.md) + - [编译](quickstart-standard-running-rk3568-build.md) + - [烧录](quickstart-standard-running-rk3568-burning.md) + - [运行](quickstart-standard-running-rk3568-running.md) +- 常见问题 + - [hb安装异常](quickstart-standard-faq-hb.md) + - [编译异常](quickstart-standard-faq-compose.md) + - [烧录异常](quickstart-standard-faq-burning.md) +- 附录 + - 开发板介绍 + - [Hi3516开发板介绍](quickstart-standard-board-introduction-hi3516.md) + - [RK3568开发板介绍](quickstart-standard-board-introduction-rk3568.md) + - [参考信息](quickstart-standard-reference.md) diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-build.md b/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-build.md index 53eba98be6f17ecacd4e52c3ab08488f15c28bc2..608c786bf70c5c5097d70f1af479890d2e42ce2e 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-build.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-build.md @@ -1,7 +1,7 @@ # 编译 -OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-standard-reference.md#使用buildsh脚本编译源码)。 +OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-standard-reference.md)。 在Ubuntu环境下进入源码根目录,执行如下命令进行编译: @@ -38,6 +38,7 @@ OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build. **图1** Hi3516编译设置图例 + ![zh-cn_image_0000001271562433](figures/zh-cn_image_0000001271562433.png) 5. 编译结束后,出现“build success”字样,则证明构建成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-burning.md b/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-burning.md index afdbc12cf98955e4ce2120195c4b685e6c505ef1..1670d388a7453934923869ad9e34e05dd4ab6e6e 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-burning.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-burning.md @@ -6,9 +6,10 @@ ### 导入源码 -在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-standard-env-setup.md#安装deveco-device-tool)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 +在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-standard-env-setup.md)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 1. 打开DevEco Device Tool,进入Home页,点击**Import Project**打开工程。 + ![zh-cn_image_0000001171426014](figures/zh-cn_image_0000001171426014.png) 2. 选择要导入的源码目录(需要访问Ubuntu下的源码目录),点击**Import**打开。 @@ -18,12 +19,15 @@ ![zh-cn_image_0000001227711882](figures/zh-cn_image_0000001227711882.png) 3. 如果您打开的目录不是DevEco Device Tool工程,则会出现如下提示框,点击**Import**。 + ![zh-cn_image_0000001135394334](figures/zh-cn_image_0000001135394334.png) 4. 在Select Project type界面,选择**Import from OpenHarmony Source**。 + ![zh-cn_image_0000001215743910](figures/zh-cn_image_0000001215743910.png) 5. 在Import Project界面,选择**Product**后,会自动填充对应的MCU、Board、company和kernel信息,然后**ohosVersion**选择对应的OpenHarmony源码版本。此处选择Hi3516DV300。 + ![zh-cn_image_0000001271912277](figures/zh-cn_image_0000001271912277.png) 6. 点击**Open**打开工程或源码。 @@ -45,12 +49,14 @@ > 该操作仅在远程模式(Windows+Ubuntu混合开发环境)中需要设置,如果采用本地模式(Windows开发环境或Ubuntu开发环境),则请跳过该步骤。 3. 在DevEco Device Tool中,点击QUICK ACCESS > DevEco Home > Device,查看并记录对应的串口号。 + ![zh-cn_image_0000001216516128](figures/zh-cn_image_0000001216516128.png) > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 如果对应的串口异常,请根据[Hi3516DV300/Hi3518EV300开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/documentation/guide/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 4. 在QUICK ACCESS > DevEco Home > Projects中,点击**Settings**打开工程配置界面。 + ![zh-cn_image_0000001198566364](figures/zh-cn_image_0000001198566364.png) 5. 在“hi3516dv300”页签,设置烧录选项,包括upload_partitions、upload_port和upload_protocol。 @@ -62,12 +68,15 @@ 6. 分别检查待烧录文件的烧录信息,DevEco Device Tool已预置默认的烧录文件信息,可根据实际情况进行调整。待烧录文件包括:fastboot、kernel、rootfs和userfs。 1. 在“hi3516dv300_fastboot”页签,在New Option选项中选择需要修改的项,例如partition_bin(烧录文件路径)、partition_addr(烧录文件起始地址)、partition_length(烧录文件分区长度)等。 + ![zh-cn_image_0000001198889702](figures/zh-cn_image_0000001198889702.png) + 2. 然后在Partition Options中,分别修改上述步骤中选择的修改项。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 在设置烧录分区起始地址和分区长度时,应根据实际待烧录文件的大小进行设置,要求设置的烧录分区大小,要大于待烧录文件的大小;同时,各烧录文件的分区地址设置不能出现重叠。 ![zh-cn_image_0000001243290907](figures/zh-cn_image_0000001243290907.png) + 3. 按照相同的方法修改kernel、rootfs和userfs的烧录文件信息。 7. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 @@ -79,6 +88,7 @@ ![zh-cn_image_0000001267231481](figures/zh-cn_image_0000001267231481.png) 9. 在终端窗口显示如下提示信息时,按住复位键,插拔USB线,最后松开复位键启动烧录。 + ![zh-cn_image_0000001114129426](figures/zh-cn_image_0000001114129426.png) 启动烧录后,界面提示如下信息时,表示烧录成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-create.md b/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-create.md index d9632828c8155aaae5fd6be0f6400108d2a30db8..b0cef24b4d2dba209ff14b954380a9e5061f91fc 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-create.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-running-hi3516-create.md @@ -31,6 +31,7 @@ productdefine/common 1. 创建目录,编写业务代码。 + 新建applications/sample/hello/src/helloworld.c目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改World为OH)。其中helloworld.h包含字符串打印函数HelloPrint的声明。当前应用程序可支持标准C及C++的代码开发。 @@ -75,6 +76,7 @@ productdefine/common ``` 2. 新建编译组织文件。 + 1. 新建applications/sample/hello/BUILD.gn文件,内容如下所示: ``` @@ -136,6 +138,7 @@ productdefine/common bundle.json文件包含两个部分,第一部分描述该部件所属子系统的信息,第二部分component则定义该部件构建相关配置。添加的时候需要指明该部件包含的模块sub_component,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test中说明,inner_kits与test没有也可以不添加。 3. 修改子系统配置文件。 + 在build/subsystem_config.json中添加新建的子系统的配置。 @@ -147,6 +150,7 @@ productdefine/common ``` 4. 修改产品配置文件。 + 在productdefine/common/products/Hi3516DV300.json中添加对应的hello部件,直接添加到原有部件后即可。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-build.md b/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-build.md index e3c5016f842ee4a8ded521a858fd7bfe3c1203fa..1014890bb47cd8a0a9ef166a20bfc28fac0ece8c 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-build.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-build.md @@ -1,7 +1,7 @@ # 编译 -OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-standard-reference.md#使用buildsh脚本编译源码)。 +OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build.sh脚本编译方式请参考[使用build.sh脚本编译源码](../quick-start/quickstart-standard-reference.md)。 在Ubuntu环境下进入源码根目录,执行如下命令进行编译: @@ -38,6 +38,7 @@ OpenHarmony支持hb和build.sh两种编译方式。此处介绍hb方式,build. **图1** RK3568编译设置图例 + ![zh-cn_image_0000001226922302](figures/zh-cn_image_0000001226922302.png) 5. 编译结束后,出现“rk3568 build success”字样,则证明构建成功。 diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-burning.md b/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-burning.md index b0d02f482270e43a56f1417638f9bc4ffd188c3b..7fdb9d16102d59a301fbdb2bf20cd316dced9c67 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-burning.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-burning.md @@ -6,9 +6,10 @@ ### 导入源码 -在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-standard-env-setup.md#安装deveco-device-tool)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 +在编译完成后,[保证Windows系统可以远程访问Ubuntu环境](../quick-start/quickstart-standard-env-setup.md)的情况下,您还需要通过以下步骤导入源码后,方可进行烧录。 1. 打开DevEco Device Tool,进入Home页,点击**Import Project**打开工程。 + ![zh-cn_image_0000001171426014](figures/zh-cn_image_0000001171426014.png) 2. 选择要导入的源码目录(需要访问Ubuntu下的源码目录),点击**Import**打开。 @@ -18,12 +19,15 @@ ![zh-cn_image_0000001272032361](figures/zh-cn_image_0000001272032361.png) 3. 如果您打开的目录不是DevEco Device Tool工程,则会出现如下提示框,点击**Import**。 + ![zh-cn_image_0000001135394334](figures/zh-cn_image_0000001135394334.png) 4. 在Select Project type界面,选择**Import from OpenHarmony Source**。 + ![zh-cn_image_0000001215743910](figures/zh-cn_image_0000001215743910.png) 5. 在Import Project界面,选择**Product**后,会自动填充对应的MCU、Board、company和kernel信息,然后**ohosVersion**选择对应的OpenHarmony源码版本。此处选择rk3568。 + ![zh-cn_image_0000001227712350](figures/zh-cn_image_0000001227712350.png) 6. 点击**Open**打开工程或源码。 @@ -49,6 +53,7 @@ > 该操作仅在远程模式(Windows+Ubuntu混合开发环境)中需要设置,如果采用本地模式(Windows开发环境或Ubuntu开发环境),则请跳过该步骤。 4. 打开DevEco Device Tool,在QUICK ACCESS > DevEco Home > Projects中,点击**Settings**打开工程配置界面。 + ![zh-cn_image_0000001239661509](figures/zh-cn_image_0000001239661509.png) 5. 在“hh_scdy200”页签,设置烧录选项,包括upload_partitions和upload_protocol。 @@ -59,18 +64,23 @@ 6. 分别检查待烧录文件的烧录信息,DevEco Device Tool已预置默认的烧录文件信息,可根据实际情况进行调整。待烧录文件包括:loader、parameter、uboot、boot_linux、system、vendor和userdata。 1. 在“hh_scdy200_loader”页签,在New Option选项中选择需要修改的项,例如partition_bin(烧录文件路径)、partition_addr(烧录文件起始地址)、partition_length(烧录文件分区长度)等。 + ![zh-cn_image_0000001224173270](figures/zh-cn_image_0000001224173270.png) + 2. 然后在Partition Options中,分别修改上述步骤中选择的修改项。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 在设置烧录分区起始地址和分区长度时,应根据实际待烧录文件的大小进行设置,要求设置的烧录分区大小,要大于待烧录文件的大小;同时,各烧录文件的分区地址设置不能出现重叠。 ![zh-cn_image_0000001268653461](figures/zh-cn_image_0000001268653461.png) + 3. 按照相同的方法修改parameter、uboot、boot_linux、system、vendor和userdata的烧录文件信息。 7. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 8. 点击工程的Open按钮,打开工程文件,点击![zh-cn_image_0000001239221905](figures/zh-cn_image_0000001239221905.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hh_scdy200下的**Upload**按钮,启动烧录。 + ![zh-cn_image_0000001194821710](figures/zh-cn_image_0000001194821710.png) 9. 等待开发板烧录完成,当屏幕提示如下信息时,表示烧录成功。 + ![zh-cn_image_0000001194984912](figures/zh-cn_image_0000001194984912.png) diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-create.md b/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-create.md index 46f1afe408c25106591b6ad1508bf4bdcc46a417..0ad654203fc5a0fa892de27cf2d3173a2a7bbc9a 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-create.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-create.md @@ -29,6 +29,7 @@ productdefine/common 请在源码目录中通过以下步骤创建“Hello World”应用程序: 1. 创建目录,编写业务代码。 + 新建applications/sample/hello/src/helloworld.c目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改World为OH)。其中helloworld.h包含字符串打印函数HelloPrint的声明。当前应用程序可支持标准C及C++的代码开发。 @@ -73,6 +74,7 @@ productdefine/common ``` 2. 新建编译组织文件。 + 1. 新建applications/sample/hello/BUILD.gn文件,内容如下所示: ``` @@ -134,6 +136,7 @@ productdefine/common bundle.json文件包含两个部分,第一部分描述该部件所属子系统的信息,第二部分component则定义该部件构建相关配置。添加的时候需要指明该部件包含的模块sub_component,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test中说明,inner_kits与test没有也可以不添加。 3. 修改子系统配置文件。 + 在build/subsystem_config.json中添加新建的子系统的配置。 @@ -145,6 +148,7 @@ productdefine/common ``` 4. 修改产品配置文件。 + 在productdefine/common/products/rk3568.json中添加对应的hello部件,直接添加到原有部件后即可。 ``` diff --git a/zh-cn/device-dev/security/Readme-CN.md b/zh-cn/device-dev/security/Readme-CN.md index f07b6d07d8f9037d5d648d91c7e3def281fcc4fe..4f87493a19db4014a20481e3151f8798e5cde7eb 100755 --- a/zh-cn/device-dev/security/Readme-CN.md +++ b/zh-cn/device-dev/security/Readme-CN.md @@ -1,4 +1,7 @@ -# 隐私与安全 +# security + +- 隐私与安全 + - [隐私保护](security-privacy-protection.md) + + - [安全指南](security-guidelines-overall.md) -- [隐私保护](security-privacy-protection.md) -- [安全指南](security-guidelines-overall.md) diff --git "a/zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" "b/zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" rename to "zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" diff --git "a/zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" "b/zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" rename to "zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" diff --git "a/zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" "b/zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" rename to "zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" diff --git "a/zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" "b/zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" rename to "zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" diff --git "a/zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" "b/zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" rename to "zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" diff --git "a/zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" "b/zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" rename to "zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" diff --git "a/zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" "b/zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" rename to "zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" diff --git "a/zh-cn/device-dev/security/figure/DAC\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/DAC\346\265\201\347\250\213\345\233\276.png" rename to "zh-cn/device-dev/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001057233092.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001057233092.png new file mode 100644 index 0000000000000000000000000000000000000000..42300c9ca287049f03a8f90a8bba9c2cdc73e109 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001057233092.png differ diff --git "a/zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" b/zh-cn/device-dev/security/figures/zh-cn_image_0000001058270836.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" rename to zh-cn/device-dev/security/figures/zh-cn_image_0000001058270836.png diff --git "a/zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" b/zh-cn/device-dev/security/figures/zh-cn_image_0000001058382954.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" rename to zh-cn/device-dev/security/figures/zh-cn_image_0000001058382954.png diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001147250660.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147250660.png new file mode 100644 index 0000000000000000000000000000000000000000..2c729ec07bb1b74ef1936767cc3e9d19d4846835 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147250660.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001147251830.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147251830.png new file mode 100644 index 0000000000000000000000000000000000000000..59483db25632d9a37f7726549ebc18dfff446a23 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147251830.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001147410700.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147410700.png new file mode 100644 index 0000000000000000000000000000000000000000..90bf11ec3746c9fb00ea43608c5cf7d822f692e4 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147410700.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001147412742.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147412742.png new file mode 100644 index 0000000000000000000000000000000000000000..fff1da1f834037c30a874b2fd76cad402b9ff9ce Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001147412742.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001159520844.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001159520844.png new file mode 100644 index 0000000000000000000000000000000000000000..87def1af5551ba7236979df89eaabadef1d362d8 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001159520844.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001193292069.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001193292069.png new file mode 100644 index 0000000000000000000000000000000000000000..c504f5246b2988876649a3f5d0c9059c7a0b2441 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001193292069.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001193292261.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001193292261.png new file mode 100644 index 0000000000000000000000000000000000000000..a0821e9436b918bffb1ea3b3756fe6d4cc969f08 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001193292261.png differ diff --git a/zh-cn/device-dev/security/figures/zh-cn_image_0000001193330127.png b/zh-cn/device-dev/security/figures/zh-cn_image_0000001193330127.png new file mode 100644 index 0000000000000000000000000000000000000000..506644efe856fd40f9f9be9469eeaca8e0881980 Binary files /dev/null and b/zh-cn/device-dev/security/figures/zh-cn_image_0000001193330127.png differ diff --git "a/zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..fcab754c7446d4b886cc1d68d52832b1a006370d Binary files /dev/null and "b/zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..69ce9db229347ee2de2401fc0caef8f82d6f2035 Binary files /dev/null and "b/zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-note.gif b/zh-cn/device-dev/security/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda Binary files /dev/null and b/zh-cn/device-dev/security/public_sys-resources/icon-note.gif differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 Binary files /dev/null and b/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/security/public_sys-resources/icon-tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..93aa72053b510e456b149f36a0972703ea9999b7 Binary files /dev/null and b/zh-cn/device-dev/security/public_sys-resources/icon-tip.gif differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/security/public_sys-resources/icon-warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 Binary files /dev/null and b/zh-cn/device-dev/security/public_sys-resources/icon-warning.gif differ diff --git a/zh-cn/device-dev/security/security-guidelines-overall.md b/zh-cn/device-dev/security/security-guidelines-overall.md index 63804f366b4110c67b0b87ced8b24aea03dbf220..67f688e5248773928d4e6fa71002a5c1efa08269 100644 --- a/zh-cn/device-dev/security/security-guidelines-overall.md +++ b/zh-cn/device-dev/security/security-guidelines-overall.md @@ -1,275 +1,195 @@ -# 安全指南 +# 安全指南 -- [安全概述](#section1521410017353) -- [硬件安全](#section2558121318351) - - [安全机制](#section1399511541896) - - [推荐做法](#section948519243104) -- [系统安全](#section87802111361) - - [安全机制](#section149107611118) - - [推荐做法](#section1364122019112) +## 安全概述 -- [数据安全](#section2468927364) - - [安全机制](#section1378993720111) - - [推荐做法](#section1531735481112) +OpenHarmony操作系统是一个开放的系统,开发者可以通过OpenHarmony开发灵活的服务和应用,为开发者和使用者带来便利和价值。为了达到这一目的,OpenHarmony提供了一个可以有效保护应用和用户数据的执行环境。 -- [设备互联安全](#section26153183616) -- [应用安全](#section852593153614) - - [安全机制](#section55012136125) - - [推荐做法](#section6341102610123) +在这个执行环境中,芯片的安全能力、系统的安全能力、以及上层的安全服务一起协作,从硬件安全、系统安全、数据安全、设备互联安全、应用安全、安全更新多个维度提供安全保障。 -## 安全概述 + **图1** 安全保障示意图 + ![zh-cn_image_0000001058270836](figures/zh-cn_image_0000001058270836.png) -OpenHarmony操作系统是一个开放的系统,开发者可以通过OpenHarmony开发灵活的服务和应用,为开发者和使用者带来便利和价值。为了达到这一目的,OpenHarmony提供了一个可以有效保护应用和用户数据的执行环境。 -在这个执行环境中,芯片的安全能力、系统的安全能力、以及上层的安全服务一起协作,从硬件安全、系统安全、数据安全、设备互联安全、应用安全、安全更新多个维度提供安全保障。 +## 硬件安全 -**图 1** 安全保障示意图 -![](figure/安全保障示意图.png "安全保障示意图") -## 硬件安全 +### 安全机制 -### 安全机制 +- 启动可信根 + OpenHarmony设备采用PKI(Public Key Infrastructure)体系保护软件完整性,确保设备运行来源合法、软件未被篡改。 -- 启动可信根 + 在设备启动流程中,逐级进行软件签名校验形成安全启动链,任何一个环节的签名校验不通过即终止设备启动;安全启动链中最初执行签名校验的软硬件实体,需确保自身的合法、未被篡改。该实体即为设备的启动可信根。启动可信根可为固化在ROM中的一段代码,这段代码在芯片制造环节固化到芯片中,芯片制造完成后软件不可更改,在设备上电初始化的过程中,最先执行这段ROM中的代码,并由这段ROM代码执行后续的软件签名校验。 - OpenHarmony设备采用PKI(Public Key Infrastructure)体系保护软件完整性,确保设备运行来源合法、软件未被篡改。 + ROM中的代码在执行签名校验时,需确保用于校验的PKI公钥的合法性,OpenHarmony设备可采用eFuse/OTP等存储介质来存储公钥(如公钥哈希值),来保护公钥自身的合法性。公钥一般在设备制造环节,烧录到设备的eFuse/OTP中。 - 在设备启动流程中,逐级进行软件签名校验形成安全启动链,任何一个环节的签名校验不通过即终止设备启动;安全启动链中最初执行签名校验的软硬件实体,需确保自身的合法、未被篡改。该实体即为设备的启动可信根。启动可信根可为固化在ROM中的一段代码,这段代码在芯片制造环节固化到芯片中,芯片制造完成后软件不可更改,在设备上电初始化的过程中,最先执行这段ROM中的代码,并由这段ROM代码执行后续的软件签名校验。 +- 硬件隔离可信环境 + 硬件隔离的可信环境,遵循了可信计算系统的设计理念。可信环境内外形成了两个世界:可信世界与不可信世界,两者之间存在清晰而明确的隔离边界;OpenHarmony设备在可信环境中实现了核心敏感数据的保护机制,可确保即使不可信世界的操作系统存在漏洞且被利用,也依然能确保可信环境中敏感数据的安全。 - ROM中的代码在执行签名校验时,需确保用于校验的PKI公钥的合法性,OpenHarmony设备可采用eFuse/OTP等存储介质来存储公钥(如公钥哈希值),来保护公钥自身的合法性。公钥一般在设备制造环节,烧录到设备的eFuse/OTP中。 + OpenHarmony设备的可信环境,基于硬件的安全隔离机制构建,在不同的OpenHarmony设备上芯片隔离机制略有差异,较为通用的方法是采用ARM的TrustZone技术。在部分Risc-V芯片平台上,也可能采用独立安全核的形式来构建可信环境。 -- 硬件隔离可信环境 + 可信环境中,运行特定的、精简的操作系统iTrustee lite,用于管理可信环境的资源和任务调度,给OpenHarmony设备提供安全服务。密钥管理及数据安全,是可信环境中最为常见的安全服务,设备在eFuse/OTP中存有硬件唯一根密钥,可信环境可基于该密钥结合业务上下文衍生出多种密钥,给应用提供密钥管理和数据加解密相关的服务;设备核心密钥生命周期不离开可信环境。可信环境同样可提供身份认证、系统状态监控、数据安全存储等安全服务,提高设备安全性。 - 硬件隔离的可信环境,遵循了可信计算系统的设计理念。可信环境内外形成了两个世界:可信世界与不可信世界,两者之间存在清晰而明确的隔离边界;OpenHarmony设备在可信环境中实现了核心敏感数据的保护机制,可确保即使不可信世界的操作系统存在漏洞且被利用,也依然能确保可信环境中敏感数据的安全。 +- 硬件密钥引擎 + 密码学是信息安全的基础。数据加解密对计算机设备的核心诉求是:高效、安全。硬件加解密技术利用计算机硬件辅助软件,甚至直接取代软件,来处理数据的加解密。相比由软件实现的加解密计算,硬件实现的加解密计算更高效、更安全。 - OpenHarmony设备的可信环境,基于硬件的安全隔离机制构建,在不同的OpenHarmony设备上芯片隔离机制略有差异,较为通用的方法是采用ARM的TrustZone技术。在部分Risc-V芯片平台上,也可能采用独立安全核的形式来构建可信环境。 + 由硬件来实现加解密处理,意味着部分专用的硬件资源会用于处理加解密计算任务,当加解密引擎工作的时候CPU可以并发地继续执行其他计算任务,因此硬件加解密引擎可以带来极大的性能提升,同时降低CPU负载。此外,硬件密钥引擎可以带来更高的安全性,设计良好的硬件密钥引擎,哪怕软件被攻破也依然可保护密钥不泄露,甚至可对抗电磁、辐射等物理侧信道攻击。 - 可信环境中,运行特定的、精简的操作系统iTrustee lite,用于管理可信环境的资源和任务调度,给OpenHarmony设备提供安全服务。密钥管理及数据安全,是可信环境中最为常见的安全服务,设备在eFuse/OTP中存有硬件唯一根密钥,可信环境可基于该密钥结合业务上下文衍生出多种密钥,给应用提供密钥管理和数据加解密相关的服务;设备核心密钥生命周期不离开可信环境。可信环境同样可提供身份认证、系统状态监控、数据安全存储等安全服务,提高设备安全性。 + OpenHarmony设备支持硬件密钥引擎,支撑OpenHarmony系统进行数据加解密、证书验签、哈希计算等计算任务,可支持AES/RSA等主流的密码学算法。 -- 硬件密钥引擎 - 密码学是信息安全的基础。数据加解密对计算机设备的核心诉求是:高效、安全。硬件加解密技术利用计算机硬件辅助软件,甚至直接取代软件,来处理数据的加解密。相比由软件实现的加解密计算,硬件实现的加解密计算更高效、更安全。 +### 推荐做法 - 由硬件来实现加解密处理,意味着部分专用的硬件资源会用于处理加解密计算任务,当加解密引擎工作的时候CPU可以并发地继续执行其他计算任务,因此硬件加解密引擎可以带来极大的性能提升,同时降低CPU负载。此外,硬件密钥引擎可以带来更高的安全性,设计良好的硬件密钥引擎,哪怕软件被攻破也依然可保护密钥不泄露,甚至可对抗电磁、辐射等物理侧信道攻击。 +- 启动可信根可由一段固化在芯片中的代码和设备根密钥组成,前者一般在芯片制造阶段写入,设备生命周期内不可更改,负责在启动阶段校验设备软件证书;后者则是用于设备证书签名的私钥相对应的公钥,证书签名私钥不出PKI签名服务器,而公钥则需写入设备。为防止攻击者篡改公钥从而达到绕过签名认证的目的,写入OpenHarmony设备的公钥须确保不可篡改,可将公钥信息写入如熔丝等介质;考虑到熔丝空间有限,可仅存储公钥的哈希值,并由启动代码校验公钥的合法性。 - OpenHarmony设备支持硬件密钥引擎,支撑OpenHarmony系统进行数据加解密、证书验签、哈希计算等计算任务,可支持AES/RSA等主流的密码学算法。 +- 可信执行环境较为通用的做法是基于ARM TrustZone技术构建,也可根据设备的实际形态选择其他隔离机制,如TrustZone-M、独立安全核等;可信执行环境中须部署TEE OS,用于管理可信执行环境的资源及任务调度。OpenHarmony系统提供iTrustee作为TEE OS的解决方案,开发者及设备商可基于iTrustee开发并部署安全业务。 + 并非所有OpenHarmony设备都强制要求支持可信执行环境,部分运行低敏感业务的瘦资源设备可不做强制要求;可根据实际业务场景选择是否支持可信执行环境,以及实现怎样的可信执行环境。 +- 硬件密钥引擎须提供真随机数、公钥、对称密钥、哈希等密钥算法能力,通过在OpenHarmony系统中部署相应的驱动程序,给应用提供统一的密钥管理及密钥算法服务。 -### 推荐做法 -- 启动可信根可由一段固化在芯片中的代码和设备根密钥组成,前者一般在芯片制造阶段写入,设备生命周期内不可更改,负责在启动阶段校验设备软件证书;后者则是用于设备证书签名的私钥相对应的公钥,证书签名私钥不出PKI签名服务器,而公钥则需写入设备。为防止攻击者篡改公钥从而达到绕过签名认证的目的,写入OpenHarmony设备的公钥须确保不可篡改,可将公钥信息写入如熔丝等介质;考虑到熔丝空间有限,可仅存储公钥的哈希值,并由启动代码校验公钥的合法性。 -- 可信执行环境较为通用的做法是基于ARM TrustZone技术构建,也可根据设备的实际形态选择其他隔离机制,如TrustZone-M、独立安全核等;可信执行环境中须部署TEE OS,用于管理可信执行环境的资源及任务调度。OpenHarmony系统提供iTrustee作为TEE OS的解决方案,开发者及设备商可基于iTrustee开发并部署安全业务。 +## 系统安全 - 并非所有OpenHarmony设备都强制要求支持可信执行环境,部分运行低敏感业务的瘦资源设备可不做强制要求;可根据实际业务场景选择是否支持可信执行环境,以及实现怎样的可信执行环境。 -- 硬件密钥引擎须提供真随机数、公钥、对称密钥、哈希等密钥算法能力,通过在OpenHarmony系统中部署相应的驱动程序,给应用提供统一的密钥管理及密钥算法服务。 +### 安全机制 -## 系统安全 +对于128KB~128MB内存的设备,推荐使用OpenHarmony轻内核组件,在该内核下: -### 安全机制 +- 进程隔离 + 进程隔离是为了防止A进程读写B进程内存数据的情况发生,进程的隔离技术,一般都采用虚拟地址空间映射方式,通过MMU配置,进程A的虚拟地址和进程B的虚拟地址映射各自不同的实际的物理地址段,这样A进程通过访问虚拟地址访问的实际内存数据在非共享内存的情况下,只属于A进程,B进程无法直接访问。 -对于128KB\~128MB内存的设备,推荐使用OpenHarmony轻内核组件,在该内核下: + OpenHarmony由于资源有限,对于内核态和用户态的进程采用不同的方式:所有的内核态进程共享同一块VMM空间,即所有的内核态进程之间无隔离,系统启动时内核态创建两个基本进程KProcess和KIdle,KProcess进程为内核态进程的根进程,KIdle进程为KProcess进程的子进程;但是对于每一个用户态进程均拥有自己独立的VMM空间,相互之间不可见,实现进程间隔离。 -- 进程隔离 +- 自主访问控制 + 自主访问控制DAC(Discretionary Access Control)的思想是文件权限由文件拥有者来决定其他角色的访问权限。权限管控粒度分为三类:user(自身), group(组员),other(其他人),即UGO。将任意用户分类为UGO中三者之一,并采取相应的管控策略,即完成了DAC权限校验流程。 - 进程隔离是为了防止A进程读写B进程内存数据的情况发生,进程的隔离技术,一般都采用虚拟地址空间映射方式,通过MMU配置,进程A的虚拟地址和进程B的虚拟地址映射各自不同的实际的物理地址段,这样A进程通过访问虚拟地址访问的实际内存数据在非共享内存的情况下,只属于A进程,B进程无法直接访问。 + DAC机制依赖于进程的uid、gid等属性,需要以此作为文件创建以及文件访问过程中的特征id。文件创建时,创建者将自身uid写入文件,文件访问时,又以此作为文件归属的分类依据。 - OpenHarmony由于资源有限,对于内核态和用户态的进程采用不同的方式:所有的内核态进程共享同一块VMM空间,即所有的内核态进程之间无隔离,系统启动时内核态创建两个基本进程KProcess和KIdle,KProcess进程为内核态进程的根进程,KIdle进程为KProcess进程的子进程;但是对于每一个用户态进程均拥有自己独立的VMM空间,相互之间不可见,实现进程间隔离。 + 每一个应用,对应一个uid。应用在创建文件时,将自身uid信息加入被创建文件的元数据(metadata)中,并设置UGO三个组的权限。在文件访问过程中,将以访问者uid作为访问校验主体、以文件元数据中的uid权限信息作为客体,进行权限校验。 -- 自主访问控制 + 下图描述了DAC在文件访问时的鉴权过程,首先匹配进程uid和文件uid属性,其次匹配进程gid和文件gid属性,最后都匹配失败的情况,判断文件other属性是否支持进程的读、写、执行操作。同时支持忽略DAC检测机制(读、写、执行)作为一组系统特权(Capability),支持高权限(如系统服务)对低权限(三方APP)的文件管理。 - 自主访问控制DAC(Discretionary Access Control)的思想是文件权限由文件拥有者来决定其他角色的访问权限。权限管控粒度分为三类:user\(自身\), group\(组员\),other\(其他人\),即UGO。将任意用户分类为UGO中三者之一,并采取相应的管控策略,即完成了DAC权限校验流程。 + **图2** DAC流程图 + ![zh-cn_image_0000001057233092](figures/zh-cn_image_0000001057233092.png) - DAC机制依赖于进程的uid、gid等属性,需要以此作为文件创建以及文件访问过程中的特征id。文件创建时,创建者将自身uid写入文件,文件访问时,又以此作为文件归属的分类依据。 +- Capability机制 + Capability机制实际上是对root权限的具体细分。在多用户计算机系统中,一般会有一个特殊的角色拥有系统的所有权限,这个角色一般是系统管理员(root)。对于OpenHarmony这种需要支持三方应用生态的内核,需要将系统中的特权访问进行管控。系统需要对用户层访问内核的特权级系统调用进行限制。仅允许部分高权限应用进行特权操作。具体实现方式是内核spawn第一个用户程序INIT,其包含全部的特权能力,此后,INIT拉起其他应用框架服务,拉起过程中,对各应用框架进行相应的降权操作,为各应用保留必须的特权能力。 当应用去调用特权接口时,内核态就会通过进程ID查看当前访问者是否有权限访问目标接口。 - 每一个应用,对应一个uid。应用在创建文件时,将自身uid信息加入被创建文件的元数据\(metadata\)中,并设置UGO三个组的权限。在文件访问过程中,将以访问者uid作为访问校验主体、以文件元数据中的uid权限信息作为客体,进行权限校验。 +- 安全启动 + 安全启动是整个系统安全的基础,通过采用数字签名和完整性校验机制,从芯片内部固化的可信启动根开始,逐级校验每一层软件的完整性和合法性,确保最终启动的操作系统软件是厂家提供的正确合法的软件,防止攻击者对系统软件做恶意的篡改和植入,为整个系统提供初始安全的基础运行环境。 - 下图描述了DAC在文件访问时的鉴权过程,首先匹配进程uid和文件uid属性,其次匹配进程gid和文件gid属性,最后都匹配失败的情况,判断文件other属性是否支持进程的读、写、执行操作。同时支持忽略DAC检测机制(读、写、执行)作为一组系统特权(Capability),支持高权限(如系统服务)对低权限(三方APP)的文件管理。 + 在芯片上电后,由于片上ROM代码本身不可更改,因此无需校验;片上ROM基于eFuse中的非对称算法公钥hash对bootloader进行校验。这些过程都基于硬件信任根来进行,是完全可信的。经过此过程校验通过的bootloader模块可以作为后续的信任基础,此过程就是启动信任链的构造过程。Bootloader通常首先对执行环境进行一定的初始化,主要是初始化DDR以及flash读写,为进一步加载后续模块以及执行更为复杂的逻辑进行准备。Bootloader完成初始化动作后,首先完成x509证书的完整性校验,然后利用x509证书的公钥对需要校验的镜像包(kernel.bin、teeOS.bin、rootfs.bin)进行校验。 - **图 2** DAC流程图 - ![](figure/DAC流程图.png "DAC流程图") -- Capability机制 +### 推荐做法 - Capability机制实际上是对root权限的具体细分。在多用户计算机系统中,一般会有一个特殊的角色拥有系统的所有权限,这个角色一般是系统管理员\(root\)。对于OpenHarmony这种需要支持三方应用生态的内核,需要将系统中的特权访问进行管控。系统需要对用户层访问内核的特权级系统调用进行限制。仅允许部分高权限应用进行特权操作。具体实现方式是内核spawn第一个用户程序INIT,其包含全部的特权能力,此后,INIT拉起其他应用框架服务,拉起过程中,对各应用框架进行相应的降权操作,为各应用保留必须的特权能力。 当应用去调用特权接口时,内核态就会通过进程ID查看当前访问者是否有权限访问目标接口。 +- 自主访问控制和Capability机制是控制资源被谁可以访问的机制,建议所有权限设置都采用最小权限原则。 -- 安全启动 +- 安全启动必须要开启,信任根必须是基于芯片的不可更改的形式存在,并且在有安全升级的情况下,必须考虑安全升级后对于安全启动的影响,也就是安全升级后必须要更新对应镜像文件的签名信息或者hash值。 - 安全启动是整个系统安全的基础,通过采用数字签名和完整性校验机制,从芯片内部固化的可信启动根开始,逐级校验每一层软件的完整性和合法性,确保最终启动的操作系统软件是厂家提供的正确合法的软件,防止攻击者对系统软件做恶意的篡改和植入,为整个系统提供初始安全的基础运行环境。 - 在芯片上电后,由于片上ROM代码本身不可更改,因此无需校验;片上ROM基于eFuse中的非对称算法公钥hash对bootloader进行校验。这些过程都基于硬件信任根来进行,是完全可信的。经过此过程校验通过的bootloader模块可以作为后续的信任基础,此过程就是启动信任链的构造过程。Bootloader通常首先对执行环境进行一定的初始化,主要是初始化DDR以及flash读写,为进一步加载后续模块以及执行更为复杂的逻辑进行准备。Bootloader完成初始化动作后,首先完成x509证书的完整性校验,然后利用x509证书的公钥对需要校验的镜像包(kernel.bin、teeOS.bin、rootfs.bin)进行校验。 +## 数据安全 -### 推荐做法 +### 安全机制 -- 自主访问控制和Capability机制是控制资源被谁可以访问的机制,建议所有权限设置都采用最小权限原则。 -- 安全启动必须要开启,信任根必须是基于芯片的不可更改的形式存在,并且在有安全升级的情况下,必须考虑安全升级后对于安全启动的影响,也就是安全升级后必须要更新对应镜像文件的签名信息或者hash值。 +HUKS(Huawei Universal Keystore Service),提供了密钥管理、证书管理服务,当前在OpenHarmony上主要提供密钥管理服务,用于支撑HiChain(设备身份认证平台)的基础设备认证。如下是HUKS的功能结构图: -## 数据安全 + **图3** HUKS功能结构图 + ![zh-cn_image_0000001159520844](figures/zh-cn_image_0000001159520844.png) -### 安全机制 +支持算法包括: -HUKS(Huawei Universal Keystore Service),提供了密钥管理、证书管理服务,当前在OpenHarmony上主要提供密钥管理服务,用于支撑HiChain\(设备身份认证平台\)的基础设备认证。如下是HUKS的功能结构图: +- 认证加密:AES-128/192/256-GCM -**图 3** HUKS功能结构图 -![](figure/HUKS功能结构图.png "HUKS功能结构图") +- 签名验签:ED25519 -支持算法包括: +- 密钥协商:X25519 + +- 消息认证:HMAC-SHA256/512 + +- 数据摘要:SHA256/512 -- 认证加密:AES-128/192/256-GCM -- 签名验签:ED25519 -- 密钥协商:X25519 -- 消息认证:HMAC-SHA256/512 -- 数据摘要:SHA256/512 HUKS在使用中有如下约束: -- 密钥安全存储:密钥要求存储于安全存储区域,数据不可以修改,恢复出厂设置时出厂预置的密钥不能被删除。 -- 密钥访问安全:OpenHarmony通过将不同应用数据保存在不同的位置,来实现应用间数据的隔离。通过参数结构体中包含UID和进程ID,来实现不同应用间的数据隔离。 -- 不支持并发访问:HUKS本身不考虑多个应用同时调用的情况,因为HUKS只是一个lib库,也不考虑资源的互斥。如果有多个应用都会用到HUKS服务,那么应该由每个应用各自链接一份HUKS库,并由业务传入持久化数据存储的路径,以实现应用间的数据存储分开。数据存储在各应用各自存储目录下。 -### 推荐做法 +- 密钥安全存储:密钥要求存储于安全存储区域,数据不可以修改,恢复出厂设置时出厂预置的密钥不能被删除。 + +- 密钥访问安全:OpenHarmony通过将不同应用数据保存在不同的位置,来实现应用间数据的隔离。通过参数结构体中包含UID和进程ID,来实现不同应用间的数据隔离。 + +- 不支持并发访问:HUKS本身不考虑多个应用同时调用的情况,因为HUKS只是一个lib库,也不考虑资源的互斥。如果有多个应用都会用到HUKS服务,那么应该由每个应用各自链接一份HUKS库,并由业务传入持久化数据存储的路径,以实现应用间的数据存储分开。数据存储在各应用各自存储目录下。 + + +### 推荐做法 对于设备认证功能,建议使用HiChain来对接HUKS,HUKS可以向HiChain等应用提供密钥的产生、导入、导出、加密/解密、存储、销毁,证书的导入和查询,秘密信息的存储等能力。 -## 设备互联安全 + +## 设备互联安全 为了实现用户数据在设备互联场景下在各个设备之间的安全流转,需要保证设备之间相互正确可信,即设备和设备之间建立信任关系,并能够在验证信任关系后,搭建安全的连接通道,实现用户数据的安全传输。设备之间的信任关系在本文档中涉及IoT主控设备和IoT设备之间建立的可信关系。设备间可信关系建立的流程如下图所示: -**图 4** 设备间建立可信关系流程图 -![](figure/设备间建立可信关系流程图.png "设备间建立可信关系流程图") -- **IoT设备互联安全** + **图4** 设备间建立可信关系流程图 + ![zh-cn_image_0000001058382954](figures/zh-cn_image_0000001058382954.png) - 设备互联支持基于OpenHarmony的IoT设备(如AI音箱、智能家居、智能穿戴等设备)与IoT主控设备间建立点对点的信任关系,并在具备信任关系的设备间,搭建安全的连接通道,实现用户数据端到端加密传输。 +- **IoT设备互联安全** + 设备互联支持基于OpenHarmony的IoT设备(如AI音箱、智能家居、智能穿戴等设备)与IoT主控设备间建立点对点的信任关系,并在具备信任关系的设备间,搭建安全的连接通道,实现用户数据端到端加密传输。 -- **IoT主控设备的IoT业务身份标识** - IoT主控设备为不同的IoT设备管理业务生成不同的身份标识,形成不同IoT管理业务间的隔离,该标识用于IoT主控设备与IoT设备之间的认证以及通信。IoT业务身份标识为椭圆曲线公私钥对(Ed25519公私钥对)。 - - -- **IoT设备身份标识** - - IoT设备会生成各自的设备身份标识,用来与IoT主控设备通信。该身份标识同样为椭圆曲线公私钥对(Ed25519公私钥对);IoT设备私钥不出IoT设备,设备每次恢复出厂设置,会重置这个公私钥对。 - - 上述身份标识可用于IoT主控设备与IoT设备间的安全通信:当IoT主控设备与IoT设备通过信任绑定流程交换业务身份标识或设备标识后,可以进行密钥协商并建立安全通信通道。 - - -- **设备间点对点的信任绑定** - - IoT主控设备和IoT设备建立点对点信任关系的过程,实际上是相互交换IoT设备的身份标识的过程。 - - 在点对点建立信任关系的过程中,用户需要在IoT主控设备上,输入IoT设备上提供的PIN码:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置;PIN码的展示形式,可以是一个用户可读的数字,也可以是一个二维码。随后,IoT主控设备和IoT设备间使用PAKE协议完成认证和会话密钥协商过程,并在此基础上,通过协商出的会话密钥加密传输通道用于交换双方设备的身份标识公钥。 - - -- **IoT主控设备与IoT设备间的通信安全** - - 当建立过信任关系的IoT主控设备与IoT设备间进行通信时,双方在完成上述信任关系绑定后,基于本地存储的对端身份公钥相互进行认证;在每次通信时基于STS协议完成双向身份认证以及会话密钥协商,之后设备使用此会话密钥加密双方设备间的传输通道。 - - -## 应用安全 - -### 安全机制 - -- 应用签名管控 - - OpenHarmony应用的安装需要首先对包的完整性进行校验,具体策略是在开发阶段完成开发和调试后对安装包进行签名,这个签名需要使用指定的私钥,这个私钥就是跟验签用的公钥是一对的,一般的做法是OEM厂商生成一对公私钥,然后将公钥信息预置到设备中,而私钥就放在一个不联网的本地服务器上,这样可以确保私钥被泄露的风险尽量小,而应用在完成开发后就可以通过外置设备(例如USB)上传安装包到存放私钥的服务器上计算签名并下载签名结果到外置设备上。而安装应用时首先计算包的Hash值,一般采用SHA256算法,然后使用hash值和签名信息以及预置公钥进行验签,只有验签通过的应用才能安装。 - - 除了要证明应用来自云端认证过的,还需要证明来源,即这个应用来自合法开发者开发的,具体做法是,开发者向云端申请开发证书,开发完成后,用开发证书进行自签名,设备端存放这个证书的上一级证书,所以安装过程中,对自签名信息做校验,确保开发者的合法性。 - -- 应用权限控制 - - 由于OpenHarmony系统允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 - - **表 1** **OpenHarmony系统权限列表** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

OpenHarmony系统权限

-

授权方式

-

权限说明

-

ohos.permission.LISTEN_BUNDLE_CHANGE

-

system_grant(静态权限)

-

允许该应用获取应用变化消息。

-

ohos.permission.GET_BUNDLE_INFO

-

system_grant(静态权限)

-

允许该应用获取应用信息。

-

ohos.permission.INSTALL_BUNDLE

-

system_grant(静态权限)

-

允许该应用安装应用。

-

ohos.permission.CAMERA

-

user_grant(动态权限)

-

此应用可随时使用相机拍摄照片和录制视频。

-

ohos.permission.MODIFY_AUDIO_SETTINGS

-

system_grant(静态权限)

-

允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

-

ohos.permission.READ_MEDIA

-

user_grant(动态权限)

-

允许该应用读取您的视频收藏。

-

ohos.permission.MICROPHONE

-

user_grant(动态权限)

-

此应用可随时使用麦克风进行录音。

-

ohos.permission.WRITE_MEDIA

-

user_grant(动态权限)

-

允许该应用写入您的音乐收藏。

-

ohos.permission.DISTRIBUTED_DATASYNC

-

user_grant(动态权限)

-

管控分布式数据传输能力。

-

ohos.permission.DISTRIBUTED_VIRTUALDEVICE

-

user_grant(动态权限)

-

允许应用使用分布式虚拟能力

-
- - -### 推荐做法 +- **IoT主控设备的IoT业务身份标识** + IoT主控设备为不同的IoT设备管理业务生成不同的身份标识,形成不同IoT管理业务间的隔离,该标识用于IoT主控设备与IoT设备之间的认证以及通信。IoT业务身份标识为椭圆曲线公私钥对(Ed25519公私钥对)。 + + +- **IoT设备身份标识** + IoT设备会生成各自的设备身份标识,用来与IoT主控设备通信。该身份标识同样为椭圆曲线公私钥对(Ed25519公私钥对);IoT设备私钥不出IoT设备,设备每次恢复出厂设置,会重置这个公私钥对。 + + 上述身份标识可用于IoT主控设备与IoT设备间的安全通信:当IoT主控设备与IoT设备通过信任绑定流程交换业务身份标识或设备标识后,可以进行密钥协商并建立安全通信通道。 -开发者在开发过程中需明确后续应用在运行时需要运行哪些权限,并在profile.json中进行注册,然后需要对应用进行签名,确保设备在安装这些应用时能对应用的完整性和来源进行校验。 +- **设备间点对点的信任绑定** + IoT主控设备和IoT设备建立点对点信任关系的过程,实际上是相互交换IoT设备的身份标识的过程。 + + 在点对点建立信任关系的过程中,用户需要在IoT主控设备上,输入IoT设备上提供的PIN码:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置;PIN码的展示形式,可以是一个用户可读的数字,也可以是一个二维码。随后,IoT主控设备和IoT设备间使用PAKE协议完成认证和会话密钥协商过程,并在此基础上,通过协商出的会话密钥加密传输通道用于交换双方设备的身份标识公钥。 + + +- **IoT主控设备与IoT设备间的通信安全** + 当建立过信任关系的IoT主控设备与IoT设备间进行通信时,双方在完成上述信任关系绑定后,基于本地存储的对端身份公钥相互进行认证;在每次通信时基于STS协议完成双向身份认证以及会话密钥协商,之后设备使用此会话密钥加密双方设备间的传输通道。 + + +## 应用安全 + + +### 安全机制 + +- 应用签名管控 + OpenHarmony应用的安装需要首先对包的完整性进行校验,具体策略是在开发阶段完成开发和调试后对安装包进行签名,这个签名需要使用指定的私钥,这个私钥就是跟验签用的公钥是一对的,一般的做法是OEM厂商生成一对公私钥,然后将公钥信息预置到设备中,而私钥就放在一个不联网的本地服务器上,这样可以确保私钥被泄露的风险尽量小,而应用在完成开发后就可以通过外置设备(例如USB)上传安装包到存放私钥的服务器上计算签名并下载签名结果到外置设备上。而安装应用时首先计算包的Hash值,一般采用SHA256算法,然后使用hash值和签名信息以及预置公钥进行验签,只有验签通过的应用才能安装。 + + 除了要证明应用来自云端认证过的,还需要证明来源,即这个应用来自合法开发者开发的,具体做法是,开发者向云端申请开发证书,开发完成后,用开发证书进行自签名,设备端存放这个证书的上一级证书,所以安装过程中,对自签名信息做校验,确保开发者的合法性。 + + +- 应用权限控制 + 由于OpenHarmony系统允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 + + **表1** **OpenHarmony系统权限列表** + + | **OpenHarmony系统权限** | **授权方式** | **权限说明** | + | -------- | -------- | -------- | + | ohos.permission.LISTEN_BUNDLE_CHANGE | system_grant(静态权限) | 允许该应用获取应用变化消息。 | + | ohos.permission.GET_BUNDLE_INFO | system_grant(静态权限) | 允许该应用获取应用信息。 | + | ohos.permission.INSTALL_BUNDLE | system_grant(静态权限) | 允许该应用安装应用。 | + | ohos.permission.CAMERA | user_grant(动态权限) | 此应用可随时使用相机拍摄照片和录制视频。 | + | ohos.permission.MODIFY_AUDIO_SETTINGS | system_grant(静态权限) | 允许该应用修改全局音频设置,例如音量和用于输出的扬声器。 | + | ohos.permission.READ_MEDIA | user_grant(动态权限) | 允许该应用读取您的视频收藏。 | + | ohos.permission.MICROPHONE | user_grant(动态权限) | 此应用可随时使用麦克风进行录音。 | + | ohos.permission.WRITE_MEDIA | user_grant(动态权限) | 允许该应用写入您的音乐收藏。 | + | ohos.permission.DISTRIBUTED_DATASYNC | user_grant(动态权限) | 管控分布式数据传输能力。 | + | ohos.permission.DISTRIBUTED_VIRTUALDEVICE | user_grant(动态权限) | 允许应用使用分布式虚拟能力 | + + +### 推荐做法 + +开发者在开发过程中需明确后续应用在运行时需要运行哪些权限,并在profile.json中进行注册,然后需要对应用进行签名,确保设备在安装这些应用时能对应用的完整性和来源进行校验。 diff --git a/zh-cn/device-dev/security/security-privacy-protection.md b/zh-cn/device-dev/security/security-privacy-protection.md index 31bee1efdd05da8e91a29234e42d17d2d8b46513..c0d178dc9acec634f66315a7d63b01a81b77797b 100644 --- a/zh-cn/device-dev/security/security-privacy-protection.md +++ b/zh-cn/device-dev/security/security-privacy-protection.md @@ -1,127 +1,66 @@ -# 隐私保护 +# 隐私保护 -- [隐私保护概述](#section13200134331414) -- [数据分类分级](#section2371104991511) -- [通用隐私设计规则](#section10354102411162) -- [特殊品类要求](#section118861450201618) -## 隐私保护概述 +## 隐私保护概述 随着互联网及信息化的发展,个人数据在社会经济和日常生活中发挥着越来越重要的作用。与此同时,个人数据泄露的风险也在增加,消费者产品开发者需要更加有效的保护用户的个人数据,提高用户对产品的信任度。为了提升消费者的隐私体验,产品应默认设置较高级别隐私保护策略,达到保护消费者隐私的目的。 **基本概念** -- **个人数据(Personal Data)** +- **个人数据(Personal Data)** + 与一个身份已被识别或者身份可被识别的自然人(“数据主体”)相关的任何信息;身份可识别的自然人是指其身份可以通过诸如姓名、身份证号、位置数据等识别码或者通过一个或多个与自然人的身体、生理、精神、经济、文化或者社会身份相关的特定因素来直接或者间接地被识别。个人数据包括:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态等。 - 与一个身份已被识别或者身份可被识别的自然人(“数据主体”)相关的任何信息;身份可识别的自然人是指其身份可以通过诸如姓名、身份证号、位置数据等识别码或者通过一个或多个与自然人的身体、生理、精神、经济、文化或者社会身份相关的特定因素来直接或者间接地被识别。个人数据包括:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态等。 +- **敏感个人数据(Sensitive Personal Data)** + 敏感个人数据是个人数据的一个重要子集,指的是涉及数据主体的最私密领域的信息或者一旦泄露可能会给数据主体造成重大不利影响的数据。欧盟等国家和地区法律定义的敏感个人数据包括种族、政治观点、宗教和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等。 -- **敏感个人数据(Sensitive Personal Data)** + 根据业界最佳实践,敏感个人数据还包括可与自然人身份相关联的银行卡号、身份证号、护照号、口令等。敏感个人数据的处理需要更多更严格的保护措施。 - 敏感个人数据是个人数据的一个重要子集,指的是涉及数据主体的最私密领域的信息或者一旦泄露可能会给数据主体造成重大不利影响的数据。欧盟等国家和地区法律定义的敏感个人数据包括种族、政治观点、宗教和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等。 +- **公开个人数据(Public available Personal Data)** + 数据主体主动公开的个人数据,或公开网页/应用上可访问的个人数据,包括论坛公开的发帖、评论等。 - 根据业界最佳实践,敏感个人数据还包括可与自然人身份相关联的银行卡号、身份证号、护照号、口令等。敏感个人数据的处理需要更多更严格的保护措施。 +- **用户画像(User Profile)** + 指对个人数据采取的任何自动化处理的方式,包括评估某个自然人特定方面的情况,尤其是为了分析和预测该自然人的工作表现、经济状况、健康、个人喜好、兴趣、可信度、行为举止、所在位置或行迹。 -- **公开个人数据(Public available Personal Data)** +- **数据控制者(Data Controller)** + 单独或者与他人共同确定个人数据处理的目的和手段的自然人、法人、公共机构、政府部门或其他机构。 - 数据主体主动公开的个人数据,或公开网页/应用上可访问的个人数据,包括论坛公开的发帖、评论等。 +- **数据处理者(Data Processor)** + 指代表数据控制者处理个人数据的自然人、法人、公共机构、政府部门或其他机构。数据处理者必须按照数据控制者的要求对个人数据进行充分的保护。 -- **用户画像(User Profile)** +- **明示同意(Explicit consent)** + 如下几种情形GDPR法律提到可以通过数据主体明示同意的方式合法地处理数据: - 指对个人数据采取的任何自动化处理的方式,包括评估某个自然人特定方面的情况,尤其是为了分析和预测该自然人的工作表现、经济状况、健康、个人喜好、兴趣、可信度、行为举止、所在位置或行迹。 + - 处理敏感个人数据。 + - 自动化决策,包括进行用户画像。 + - 向不具备充分保护水平的国家转移个人数据,并以同意作为合法性基础。 -- **数据控制者(Data Controller)** + 实现明示同意的方式有: - 单独或者与他人共同确定个人数据处理的目的和手段的自然人、法人、公共机构、政府部门或其他机构。 + - 在收集特定数据时,弹出隐私声明告知个人数据处理相关事项,提供勾选框但不默认勾选,让数据主体勾选“我同意以上述方式处理我的个人数据”,或提供“我同意”的按钮让用户主动点击。 + - 以书面的方式明确表达同意,数据主体在书面陈述上签字。 + - 要求数据主体在系统中上传带有其签名的电子表格。 + - 采取双重验证的方式,要求数据主体邮件形式回复同意后,再次点击用于验证的邮件链接或是输入SMS验证码。 + - 用户主动输入的场景,例如用户主动输入身份证和银行卡号绑卡等场景。 -- **数据处理者(Data Processor)** - 指代表数据控制者处理个人数据的自然人、法人、公共机构、政府部门或其他机构。数据处理者必须按照数据控制者的要求对个人数据进行充分的保护。 - -- **明示同意(Explicit consent)** - - 如下几种情形GDPR法律提到可以通过数据主体明示同意的方式合法地处理数据: - - - 处理敏感个人数据。 - - 自动化决策,包括进行用户画像。 - - 向不具备充分保护水平的国家转移个人数据,并以同意作为合法性基础。 - - 实现明示同意的方式有: - - - 在收集特定数据时,弹出隐私声明告知个人数据处理相关事项,提供勾选框但不默认勾选,让数据主体勾选“我同意以上述方式处理我的个人数据”,或提供“我同意”的按钮让用户主动点击。 - - 以书面的方式明确表达同意,数据主体在书面陈述上签字。 - - 要求数据主体在系统中上传带有其签名的电子表格。 - - 采取双重验证的方式,要求数据主体邮件形式回复同意后,再次点击用于验证的邮件链接或是输入SMS验证码。 - - 用户主动输入的场景,例如用户主动输入身份证和银行卡号绑卡等场景。 - - -## 数据分类分级 +## 数据分类分级 基于数据保护目标及风险后果,即数据遭到泄露或者遭到破坏带来的法律风险对个人、组织或公众的影响对数据进行定级,分为极高、高、中、低、公开五个数据级别。 -**表1** 数据分类分级标准 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

数据级别

-

隐私风险

-

隐私属性

-

典型示例

-

极高级

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来灾难性负面影响。

-

敏感个人数据

-

DNA、种族、宗教信仰、性取向;生物识别信息;原始通信内容;银行卡密码、磁道数据。

-

高级别

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来严重负面影响。

-

敏感个人数据

-

权威社会标识(身份证、护照等);网页浏览记录;轨迹信息;云空间上传的内容数据(图库/音频/视频等)。

-

中级别

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来重大负面影响。

-

一般个人数据

-

设备标识(IMEI, SN, OAID )、用户标识(user ID);个人基本信息(姓名,地址);手机号、邮箱等。

-

低级别

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来有限负面影响。

-

一般个人数据

-

操作系统设置信息(操作系统版本,国家/地区等);设备硬件信息(设备型号,屏幕尺寸,屏幕分辨率等);网络信息(网络连接状态,接入网络信息);设备状态(登录设备时间/时长)。

-

公开(无风险)

-

对个人或组织无不利影响的可公开数据

-

非个人数据

-

公开发布的产品介绍,公开的会议信息,外部开源的代码等。

-
+**表1** 数据分类分级标准 + + | **数据级别** | 隐私风险 | 隐私属性 | **典型示例** | +| -------- | -------- | -------- | -------- | +| 极高级 | 数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来灾难性负面影响。 | 敏感个人数据 | DNA、种族、宗教信仰、性取向;生物识别信息;原始通信内容;银行卡密码、磁道数据。 | +| 高级别 | 数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来严重负面影响。 | 敏感个人数据 | 权威社会标识(身份证、护照等);网页浏览记录;轨迹信息;云空间上传的内容数据(图库/音频/视频等)。 | +| 中级别 | 数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来重大负面影响。 | 一般个人数据 | 设备标识(IMEI, SN, OAID )、用户标识(user ID);个人基本信息(姓名,地址);手机号、邮箱等。 | +| 低级别 | 数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来有限负面影响。 | 一般个人数据 | 操作系统设置信息(操作系统版本,国家/地区等);设备硬件信息(设备型号,屏幕尺寸,屏幕分辨率等);网络信息(网络连接状态,接入网络信息);设备状态(登录设备时间/时长)。 | +| 公开(无风险) | 对个人或组织无不利影响的可公开数据 | 非个人数据 | 公开发布的产品介绍,公开的会议信息,外部开源的代码等。 | 备注:隐私保护和数据分类分级的相关定义参照GDPR中的相关内容。 -## 通用隐私设计规则 + +## 通用隐私设计规则 为了指导厂商完成产品的隐私设计工作,我们整理了以下通用的隐私设计要求,作为OpenHarmony设备厂商产品隐私设计的指南和参考。 @@ -129,76 +68,73 @@ 采集个人数据时,应清晰、明确地告知用户,并确保告知用户的个人信息将被如何使用。 -- 针对不同等级的个人数据需要制定针对性的隐私处理策略。 - - 敏感个人数据的采集需要获取数据主体明示同意。 - - 一般个人数据的采集需要数据主体同意或基于其他合法授权。 - - 非个人数据与中、高或极高级别个人数据关联采集,需要数据主体同意或其他合法授权,并在隐私声明中呈现。 - -- 应制定并遵从适当的隐私政策。在收集、使用留存和第三方分享用户个人数据时需要符合所有适用法律、政策和规定。如在收集个人数据前,需充分告知用户处理个人数据的种类、目的、处理方式、保留期限等,满足数据主体权利相关要求。 +- 针对不同等级的个人数据需要制定针对性的隐私处理策略。 + - 敏感个人数据的采集需要获取数据主体明示同意。 + - 一般个人数据的采集需要数据主体同意或基于其他合法授权。 + - 非个人数据与中、高或极高级别个人数据关联采集,需要数据主体同意或其他合法授权,并在隐私声明中呈现。 +- 应制定并遵从适当的隐私政策。在收集、使用留存和第三方分享用户个人数据时需要符合所有适用法律、政策和规定。如在收集个人数据前,需充分告知用户处理个人数据的种类、目的、处理方式、保留期限等,满足数据主体权利相关要求。 根据以上要求,我们设计了正确示例以供参考。隐私通知/声明的参考示例如下: + **图1** 隐私通知/声明示例图 + ![zh-cn_image_0000001193330127](figures/zh-cn_image_0000001193330127.png) - **图 1** 隐私通知/声明示例图 - - - ![](figure/2-应用启动预授权.png) ![](figure/3-应用隐私声明.png) + **图2** 应用隐私声明 + ![zh-cn_image_0000001147250660](figures/zh-cn_image_0000001147250660.png) -- 个人数据应当基于具体、明确、合法的目的收集,不应与此目的不相符的方式作进一步处理。对于收集目的变更和用户撤销同意后再次重新使用的场景都需要用户重新同意。隐私声明变更和撤销的示例如下图: +- 个人数据应当基于具体、明确、合法的目的收集,不应与此目的不相符的方式作进一步处理。对于收集目的变更和用户撤销同意后再次重新使用的场景都需要用户重新同意。隐私声明变更和撤销的示例如下图: + **图3** 隐私通知/声明变更示例图 + ![zh-cn_image_0000001147410700](figures/zh-cn_image_0000001147410700.png) - **图 2** 隐私通知/声明变更示例图 - + **图4** 撤销同意示例图 + ![zh-cn_image_0000001147251830](figures/zh-cn_image_0000001147251830.png) - ![](figure/4-隐私声明变更通知.png) - - **图 3** 撤销同意示例图 - - - ![](figure/6-1-隐私声明撤销.png) ![](figure/6-2-隐私声明撤销.png) - -- 需要提供用户查看隐私声明的入口。例如,可以在应用的“关于”界面提供查看隐私声明的入口,如示例图所示: - - **图 4** 隐私声明查看界面示例图 - - - ![](figure/5-应用隐私声明入口.png) + **图5** 隐私声明撤销 + ![zh-cn_image_0000001193292069](figures/zh-cn_image_0000001193292069.png) +- 需要提供用户查看隐私声明的入口。例如,可以在应用的“关于”界面提供查看隐私声明的入口,如示例图所示: + **图6** 隐私声明查看界面示例图 + ![zh-cn_image_0000001193292261](figures/zh-cn_image_0000001193292261.png) **数据收集及使用最小化** 个人数据收集应与数据处理目的相关,且是适当、必要的。开发者应尽可能对个人数据进行匿名化或假名化处理,降低对数据主体的风险。仅可收集和处理与特定目的相关且必需的个人数据,不能进行与特定目的不相关的进一步处理。 -- 敏感权限申请的时候要满足权限最小化的要求,在申请权限时,只申请获取必需的信息或资源所需要的权限。如应用不需要相机权限就能够实现其功能时,则不应该向用户申请相机权限。 -- 数据收集最小化:针对数据的收集要满足最小化要求,不收集与产品提供服务无关联的数据。如提供定位服务的产品,不应收集用户的网页浏览记录。 -- 数据使用的功能要求能够使用户受益,收集的数据不能用于一些与用户正常使用无关的功能。数据收集不能有其他与用户正常使用无关的功能存在。如不得将“生物特征”、“健康数据”等敏感个人数据用于服务改进、投放广告或营销等非业务核心功能。 -- 禁止在日志中打印敏感个人数据,如需要打印一般个人数据时,应对个人数据进行匿名化或假名化处理; +- 敏感权限申请的时候要满足权限最小化的要求,在申请权限时,只申请获取必需的信息或资源所需要的权限。如应用不需要相机权限就能够实现其功能时,则不应该向用户申请相机权限。 + +- 数据收集最小化:针对数据的收集要满足最小化要求,不收集与产品提供服务无关联的数据。如提供定位服务的产品,不应收集用户的网页浏览记录。 - 优先使用可以重置的标识符,如系统提供了NetworkID和DVID作为分布式场景下的设备标识符,广告业务场景下则建议使用[OAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oaid-0000001050783198),基于应用的分析则建议使用[ODID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/odid-0000001051063255)和[AAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/aaid-0000001051142988),其他需要唯一标识符的场景可以使用UUID接口生成;可重置的标识符不能满足业务需求时,才选择序列号和MAC地址等永久性标识符。 +- 数据使用的功能要求能够使用户受益,收集的数据不能用于一些与用户正常使用无关的功能。数据收集不能有其他与用户正常使用无关的功能存在。如不得将“生物特征”、“健康数据”等敏感个人数据用于服务改进、投放广告或营销等非业务核心功能。 +- 禁止在日志中打印敏感个人数据,如需要打印一般个人数据时,应对个人数据进行匿名化或假名化处理; + 优先使用可以重置的标识符,如系统提供了NetworkID和DVID作为分布式场景下的设备标识符,广告业务场景下则建议使用[OAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oaid-0000001050783198),基于应用的分析则建议使用[ODID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/odid-0000001051063255)和[AAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/aaid-0000001051142988),其他需要唯一标识符的场景可以使用UUID接口生成;可重置的标识符不能满足业务需求时,才选择序列号和MAC地址等永久性标识符。 **数据处理选择和控制** 对个人数据处理必须要征得用户的同意或遵守其他适用的法律法规,用户对其个人数据要有充分的控制权。 -- 获取用户敏感权限的授权:产品弹窗提醒,向用户呈现需要获取的权限和权限使用目的,用户可通过选择决定是否进行授权及指定授权的方式,让用户对产品权限的授予和个人数据使用做到透明、可知、可控。如下图所示: +- 获取用户敏感权限的授权:产品弹窗提醒,向用户呈现需要获取的权限和权限使用目的,用户可通过选择决定是否进行授权及指定授权的方式,让用户对产品权限的授予和个人数据使用做到透明、可知、可控。如下图所示: + **图7** 敏感权限提示框示例图 + ![zh-cn_image_0000001147412742](figures/zh-cn_image_0000001147412742.png) - **图 5** 敏感权限提示框示例图 - +- 用户可以修改、取消授予的权限:当用户不同意某一权限或者数据收集时,应当允许用户使用与这部分权限和数据收集不相关的功能。如智慧屏产品上通信社交应用,用户可以拒绝授予相机权限,不应该影响与相机无关的功能操作,如语音通话。 - ![](figure/1-敏感权限弹窗.png) +- 用户在产品使用过程中,针对录入个人数据的场景,需要给用户提供对个人数据的增加、删除、修改、查看的操作。 -- 用户可以修改、取消授予的权限:当用户不同意某一权限或者数据收集时,应当允许用户使用与这部分权限和数据收集不相关的功能。如智慧屏产品上通信社交应用,用户可以拒绝授予相机权限,不应该影响与相机无关的功能操作,如语音通话。 -- 用户在产品使用过程中,针对录入个人数据的场景,需要给用户提供对个人数据的增加、删除、修改、查看的操作。 -- 需要给出硬件回收或返厂进行安全删除个人数据的机制或方法。 -- 对用户系统软件、应用软件的下载或升级,涉及修改用户隐私空间,用户对于这类行为需要有知情权和控制权,必须给用户提示,并提供给用户同意和取消的选项。 +- 需要给出硬件回收或返厂进行安全删除个人数据的机制或方法。 + +- 对用户系统软件、应用软件的下载或升级,涉及修改用户隐私空间,用户对于这类行为需要有知情权和控制权,必须给用户提示,并提供给用户同意和取消的选项。 **数据安全** 从技术上保证数据处理活动的安全性,包括个人数据的加密存储、安全传输等安全机制,系统应默认开启或采取安全保护措施。 -- 对于个人数据的访问需要有保护机制,主要包括身份认证和访问控制。身份认证(如用户名、密码)限定只有经过认证的用户才能访问数据,可应用于多用户场景;访问控制(如[权限控制](security-guidelines-overall.md#section852593153614))可应用于对应用程序的限制。 -- 分布式设备个人数据安全存储要满足密钥管理和存储服务(HUKS:Huawei Universal Keystore)的要求,包括:密钥安全存储、数据安全存储。 -- 个人数据在分布式设备间传输要满足设备间的信任绑定关系和数据传输通道的安全性要求。详细信息可以参考[设备互联安全](security-guidelines-overall.md#section26153183616)。 -- 认证凭证数据(密码、口令、指纹等)须加密存储。 +- 对于个人数据的访问需要有保护机制,主要包括身份认证和访问控制。身份认证(如用户名、密码)限定只有经过认证的用户才能访问数据,可应用于多用户场景;访问控制(如[权限控制](../security/security-guidelines-overall.md))可应用于对应用程序的限制。 + +- 分布式设备个人数据安全存储要满足密钥管理和存储服务(HUKS:Huawei Universal Keystore)的要求,包括:密钥安全存储、数据安全存储。 + +- 个人数据在分布式设备间传输要满足设备间的信任绑定关系和数据传输通道的安全性要求。详细信息可以参考[设备互联安全](../security/security-guidelines-overall.md#设备互联安全)。 + +- 认证凭证数据(密码、口令、指纹等)须加密存储。 **本地化处理** @@ -208,57 +144,18 @@ 产品专门给未成年人设计的,或者产品收集用户年龄从而可以识别到是在收集未成年人的个人数据,需结合目标市场国家的法律,专门分析未成年人个人数据保护的问题,收集未成年人数据前需要征得监护人的同意。 -## 特殊品类要求 + +## 特殊品类要求 针对消费者硬件产品来说,除了满足以上的通用隐私要求以外,针对特殊品类的产品还有以下的特殊要求,在产品设计过程中参照执行。 -**表2** 特殊品类隐私要求 - - - - - - - - - - - - - - - - - - - - - - - - - -

产品品类

-

隐私保护特殊要求

-

智能家居

-

安防类产品涉及的指纹、声纹、面部识别、虹膜等个人生物识别信息以及用户密码信息,属于敏感个人数据,应采用技术措施处理后(例如提取个人生物识别信息的摘要)再进行加密保存在产品本地。

-

智能家居

-

安防类产品涉及的音视频和图片,设备厂家作为数据控制者时,必须提供独立的隐私通知、应用界面必须有设备厂家品牌标识;音视频数据的传输和存储必须加密,非用户本人访问安防产品的音视频数据,必须获得用户授权。

-

智能家居/影音娱乐

-

带有摄像头的产品建议提供物理上可关闭功能,通过隐藏、遮盖、转向让消费者感知摄像头处于关闭状态。

-

智能家居/影音娱乐

-

带有麦克风的产品建议提供显性显示录音的状态,如录音开启时状态灯闪烁,录音关闭时状态灯熄灭。

-

移动办公

-

用户数据跨设备显示、传输等场景需要获得消费者的明示同意,给予消费者对其个人数据有充分的控制权。

-

车机

-

1、隐私通知及权限设置

-

避免在驾驶态让用户阅读隐私政策和权限设置。

-

车机应用需要考虑车辆使用时的安全性,应避免让用户在驾驶过程中进行复杂的权限设置或阅读隐私政策,比如HiCar应用应该在手机端完成应用基本权限设置和隐私政策阅读后再进行使用。

-

隐私声明在确认用户身份后告知。

-

车辆的数据会涉及车主、驾驶员和乘客,应保证隐私声明通知到了数据主体本人。建议做法是在确认使用者的身份后进行隐私声明,如需要用户登录的应用,应在账号登录后弹出隐私声明而不是账号登录之前。

-

2、共享应用个人数据保护

-

共享应用在车机重启后应退出,并对当前用户个人数据进行清除或加密,应用还应提供对历史数据进行彻底删除的功能。

-

3、消息提示

-

考虑车机的开放环境,应用在车机上进行消息提醒时,应避免直接将消息内容显示在车机上,正确的做法是仅提示有新的消息需要查看。

-
+**表2** 特殊品类隐私要求 + | 产品品类 | 隐私保护特殊要求 | +| -------- | -------- | +| **智能家居** | 安防类产品涉及的指纹、声纹、面部识别、虹膜等个人生物识别信息以及用户密码信息,属于敏感个人数据,应采用技术措施处理后(例如提取个人生物识别信息的摘要)再进行加密保存在产品本地。 | +| **智能家居** | 安防类产品涉及的音视频和图片,设备厂家作为数据控制者时,必须提供独立的隐私通知、应用界面必须有设备厂家品牌标识;音视频数据的传输和存储必须加密,非用户本人访问安防产品的音视频数据,必须获得用户授权。 | +| **智能家居/影音娱乐** | 带有摄像头的产品建议提供物理上可关闭功能,通过隐藏、遮盖、转向让消费者感知摄像头处于关闭状态。 | +| **智能家居/影音娱乐** | 带有麦克风的产品建议提供显性显示录音的状态,如录音开启时状态灯闪烁,录音关闭时状态灯熄灭。 | +| **移动办公** | 用户数据跨设备显示、传输等场景需要获得消费者的明示同意,给予消费者对其个人数据有充分的控制权。 | +| **车机** | 1、隐私通知及权限设置
避免在驾驶态让用户阅读隐私政策和权限设置。
车机应用需要考虑车辆使用时的安全性,应避免让用户在驾驶过程中进行复杂的权限设置或阅读隐私政策,比如HiCar应用应该在手机端完成应用基本权限设置和隐私政策阅读后再进行使用。
隐私声明在确认用户身份后告知。
车辆的数据会涉及车主、驾驶员和乘客,应保证隐私声明通知到了数据主体本人。建议做法是在确认使用者的身份后进行隐私声明,如需要用户登录的应用,应在账号登录后弹出隐私声明而不是账号登录之前。
2、共享应用个人数据保护
共享应用在车机重启后应退出,并对当前用户个人数据进行清除或加密,应用还应提供对历史数据进行彻底删除的功能。
3、消息提示
考虑车机的开放环境,应用在车机上进行消息提醒时,应避免直接将消息内容显示在车机上,正确的做法是仅提示有新的消息需要查看。 | diff --git a/zh-cn/device-dev/subsystems/Readme-CN.md b/zh-cn/device-dev/subsystems/Readme-CN.md index 2b2082482827996a282ca733eadaccebc5605fbb..280cf022c79d876dbbf5333e293e7a709b48da64 100755 --- a/zh-cn/device-dev/subsystems/Readme-CN.md +++ b/zh-cn/device-dev/subsystems/Readme-CN.md @@ -1,100 +1,103 @@ -# 子系统开发指南 +# subsystems -- [编译构建](subsys-build.md) - - [轻量和小型系统编译构建指导](subsys-build-mini-lite.md) - - [标准系统编译构建指导](subsys-build-standard-large.md) - - [构建系统编码规范和最佳实践指导](subsys-build-gn-coding-style-and-best-practice.md) - - [编译构建Kconfig可视化配置指导](subsys-build-gn-kconfig-visual-config-guid.md) +- 编译构建 + - [轻量和小型系统编译构建指导](subsys-build-mini-lite.md) + - [标准系统编译构建指导](subsys-build-standard-large.md) + - [构建系统编码规范与最佳实践](subsys-build-gn-coding-style-and-best-practice.md) + - [编译构建Kconfig可视化配置指导](subsys-build-gn-kconfig-visual-config-guid.md) - [分布式远程启动](subsys-remote-start.md) -- [图形图像](subsys-graphics.md) - - [图形图像概述](subsys-graphics-overview.md) - - [容器类组件开发指导](subsys-graphics-container-guide.md) - - [布局容器类组件开发指导](subsys-graphics-layout-guide.md) - - [普通组件开发指导](subsys-graphics-common-guide.md) - - [动画开发指导](subsys-graphics-animation-guide.md) -- [媒体](subsys-multimedia.md) - - [相机](subsys-multimedia-camera.md) - - [相机开发概述](subsys-multimedia-camera-overview.md) - - [拍照开发指导](subsys-multimedia-camera-photo-guide.md) - - [录像开发指导](subsys-multimedia-camera-record-guide.md) - - [预览开发指导](subsys-multimedia-camera-preview-guide.md) - - [音视频](subsys-multimedia-video.md) - - [音视频开发概述](subsys-multimedia-video-overview.md) - - [音视频播放开发指导](subsys-multimedia-video-play-guide.md) - - [音视频录制开发指导](subsys-multimedia-video-record-guide.md) -- [公共基础](subsys-utils.md) - - [公共基础库概述](subsys-utils-overview.md) - - [公共基础库开发指导](subsys-utils-guide.md) - - [公共基础库常见问题](subsys-utils-faqs.md) -- [AI框架](subsys-aiframework.md) - - [AI引擎框架开发指南](subsys-aiframework-guide.md) - - [搭建环境](subsys-aiframework-envbuild.md) - - [技术规范](subsys-aiframework-tech.md) - - [代码管理规范](subsys-aiframework-tech-codemanage.md) - - [命名规范](subsys-aiframework-tech-name.md) - - [接口开发规范](subsys-aiframework-tech-interface.md) - - [开发指导](subsys-aiframework-devguide.md) - - [SDK开发过程](subsys-aiframework-devguide-sdk.md) - - [插件的开发过程](subsys-aiframework-devguide-plugin.md) - - [配置文件的开发过程](subsys-aiframework-devguide-conf.md) - - [开发示例](subsys-aiframework-demo.md) - - [唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md) - - [唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md) - - [唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md) -- [数据管理](subsys-data.md) - - [关系型数据库](subsys-data-relational-database.md) - - [关系型数据库概述](subsys-data-relational-database-overview.md) - - [关系型数据库开发指导](subsys-data-relational-database-guide.md) - - [轻量级数据存储](subsys-data-storage.md) - - [轻量级数据存储概述](subsys-data-storage-overview.md) - - [轻量级数据存储开发指导](subsys-data-storage-guide.md) -- [Sensor服务](subsys-sensor.md) - - [Sensor服务子系概述](subsys-sensor-overview.md) - - [Sensor服务子系使用指导](subsys-sensor-guide.md) - - [Sensor服务子系使用实例](subsys-sensor-demo.md) -- [USB服务子系统](subsys-usbservice.md) - - [USB服务子系统概述](subsys-usbservice-overview.md) - - [USB服务子系统使用指导](subsys-usbservice-guide.md) - - [USB服务子系统使用实例](subsys-usbservice-demo.md) -- [用户程序框架](subsys-application-framework.md) - - [概述](subsys-application-framework-overview.md) - - [搭建环境](subsys-application-framework-envbuild.md) - - [开发指导](subsys-application-framework-guide.md) - - [开发实例](subsys-application-framework-demo.md) +- 图形图像 + - [图形图像概述](subsys-graphics-overview.md) + - [容器类组件开发指导](subsys-graphics-container-guide.md) + - [布局容器类组件开发指导](subsys-graphics-layout-guide.md) + - [普通组件开发指导](subsys-graphics-common-guide.md) + - [动画开发指导](subsys-graphics-animation-guide.md) +- 媒体 + - 相机 + - [相机开发概述](subsys-multimedia-camera-overview.md) + - [拍照开发指导](subsys-multimedia-camera-photo-guide.md) + - [录像开发指导](subsys-multimedia-camera-record-guide.md) + - [预览开发指导](subsys-multimedia-camera-preview-guide.md) + - 音视频 + - [音视频开发概述](subsys-multimedia-video-overview.md) + - [音视频播放开发指导](subsys-multimedia-video-play-guide.md) + - [音视频录制开发指导](subsys-multimedia-video-record-guide.md) +- 公共基础 + - [公共基础库概述](subsys-utils-overview.md) + - [公共基础库开发指导](subsys-utils-guide.md) + - [公共基础库常见问题](subsys-utils-faqs.md) +- AI框架 + - [概述](subsys-aiframework-guide.md) + - [搭建环境](subsys-aiframework-envbuild.md) + - 技术规范 + - [代码管理规范](subsys-aiframework-tech-codemanage.md) + - [命名规范](subsys-aiframework-tech-name.md) + - [接口开发规范](subsys-aiframework-tech-interface.md) + - 开发指导 + - [SDK开发过程](subsys-aiframework-devguide-sdk.md) + - [插件的开发过程](subsys-aiframework-devguide-plugin.md) + - [配置文件的开发过程](subsys-aiframework-devguide-conf.md) + - 开发示例 + - [唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md) + - [唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md) + - [唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md) +- 数据管理 + - [关系型数据库](subsys-data-relational-database.md) + - [关系型数据库概述](subsys-data-relational-database-overview.md) + - [关系型数据库开发指导](subsys-data-relational-database-guide.md) + - [轻量级数据存储](subsys-data-storage.md) + - [轻量级数据存储概述](subsys-data-storage-overview.md) + - [轻量级数据存储开发指导](subsys-data-storage-guide.md) +- Sensor服务 + - [Sensor服务概述](subsys-sensor-overview.md) + - [Sensor服务使用指导](subsys-sensor-guide.md) + - [Sensor服务使用实例](subsys-sensor-demo.md) +- USB服务 + - [USB服务概述](subsys-usbservice-overview.md) + - [USB服务使用指导](subsys-usbservice-guide.md) + - [USB服务使用实例](subsys-usbservice-demo.md) +- 用户程序框架 + - [概述](subsys-application-framework-overview.md) + - [搭建环境](subsys-application-framework-envbuild.md) + - [开发指导](subsys-application-framework-guide.md) + - [开发实例](subsys-application-framework-demo.md) - [OTA升级](subsys-ota-guide.md) -- [电话服务](subsys-tel.md) - - [电话服务概述](subsys-tel-overview.md) - - [电话服务开发指导](subsys-tel-guide.md) -- [安全](subsys-security.md) - - [概述](subsys-security-overview.md) - - [应用验签开发指导](subsys-security-sigverify.md) - - [应用权限管理开发指导](subsys-security-rightmanagement.md) - - [IPC通信鉴权开发指导](subsys-security-communicationverify.md) - - [设备安全等级管理开发指导](subsys-security-devicesecuritylevel.md) -- [启动恢复](subsys-boot.md) - - [启动恢复子系统概述](subsys-boot-overview.md) - - [init启动引导组件](subsys-boot-init.md) - - [appspawn应用孵化组件](subsys-boot-appspawn.md) - - [appspawn标准系统应用孵化组件](subsys-boot-appspawn-standard.md) - - [bootstrap服务启动组件](subsys-boot-bootstrap.md) - - [syspara系统属性组件](subsys-boot-syspara.md) - - [常见问题](subsys-boot-faqs.md) - - [参考](subsys-boot-ref.md) +- 电话服务 + - [电话服务概述](subsys-tel-overview.md) + - [电话服务开发指导](subsys-tel-guide.md) +- 安全 + - [概述](subsys-security-overview.md) + - [应用验签开发指导](subsys-security-sigverify.md) + - [应用权限管理开发指导](subsys-security-rightmanagement.md) + - [IPC通信鉴权开发指导](subsys-security-communicationverify.md) + - [设备安全等级管理开发指南](subsys-security-dslm.md) +- 启动恢复 + - [启动恢复子系统概述](subsys-boot-overview.md) + - [init启动引导组件](subsys-boot-init.md) + - [appspawn应用孵化组件](subsys-boot-appspawn.md) + - [appspawn标准系统应用孵化组件](subsys-boot-appspawn-standard.md) + - [bootstrap服务启动组件](subsys-boot-bootstrap.md) + - [syspara系统属性组件](subsys-boot-syspara.md) + - [常见问题](subsys-boot-faqs.md) + - [参考](subsys-boot-ref.md) - [测试用例开发指导](subsys-testguide-test.md) -- [DFX](subsys-dfx.md) - - [DFX概述](subsys-dfx-overview.md) - - [HiLog开发指导](subsys-dfx-hilog-rich.md) - - [HiLog\_Lite开发指导](subsys-dfx-hilog-lite.md) - - [HiTrace开发指导](subsys-dfx-hitrace.md) - - [HiCollie开发指导](subsys-dfx-hicollie.md) - - [HiSysEvent开发指导](subsys-dfx-hisysevent.md) - - [HiSysEvent打点配置指导](subsys-dfx-hisysevent-logging-config.md) - - [HiSysEvent打点指导](subsys-dfx-hisysevent-logging.md) - - [HiSysEvent订阅指导](subsys-dfx-hisysevent-listening.md) - - [HiSysEvent查询指导](subsys-dfx-hisysevent-query.md) - - [HiSysEvent工具使用指导](subsys-dfx-hisysevent-tool.md) -- [研发工具链](subsys-toolchain.md) - - [bytrace使用指导](subsys-toolchain-bytrace-guide.md) - - [hdc\_std 使用指导](subsys-toolchain-hdc-guide.md) - - [hiperf 使用指南](subsys-toolchain-hiperf.md) -- [XTS认证用例开发指导](subsys-xts-guide.md) +- DFX + - [DFX概述](subsys-dfx-overview.md) + - [HiLog开发指导](subsys-dfx-hilog-rich.md) + - [HiLog_Lite开发指导](subsys-dfx-hilog-lite.md) + - [HiTrace开发指导](subsys-dfx-hitrace.md) + - [HiCollie开发指导](subsys-dfx-hicollie.md) + - HiSysEvent开发指导 + - [HiSysEvent打点配置指导](subsys-dfx-hisysevent-logging-config.md) + - [HiSysEvent打点指导](subsys-dfx-hisysevent-logging.md) + - [HiSysEvent订阅指导](subsys-dfx-hisysevent-listening.md) + - [HiSysEvent查询指导](subsys-dfx-hisysevent-query.md) + - [HiSysEvent工具使用指导](subsys-dfx-hisysevent-tool.md) + - [HiDumper开发指导](subsys-dfx-hidumper.md) + - [HiChecker开发指导](subsys-dfx-hichecker.md) + - [Faultlogger开发指导](subsys-dfx-faultlogger.md) +- 调测工具 + - [bytrace使用指导](subsys-toolchain-bytrace-guide.md) + - [hdc_std使用指导](subsys-toolchain-hdc-guide.md) + - [hiperf使用指导](subsys-toolchain-hiperf.md) +- [XTS认证用例开发指导](subsys-xts-guide.md) \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/figure/20200721-223604(eSpace).gif b/zh-cn/device-dev/subsystems/figures/20200721-223604(eSpace).gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/20200721-223604(eSpace).gif rename to zh-cn/device-dev/subsystems/figures/20200721-223604(eSpace).gif diff --git "a/zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" "b/zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" rename to "zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" diff --git "a/zh-cn/device-dev/subsystems/figure/HiTrace\345\272\224\347\224\250\345\234\272\346\231\257.png" "b/zh-cn/device-dev/subsystems/figures/HiTrace\345\272\224\347\224\250\345\234\272\346\231\257.png" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/HiTrace\345\272\224\347\224\250\345\234\272\346\231\257.png" rename to "zh-cn/device-dev/subsystems/figures/HiTrace\345\272\224\347\224\250\345\234\272\346\231\257.png" diff --git "a/zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" "b/zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" rename to "zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" diff --git "a/zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" "b/zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" rename to "zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" diff --git "a/zh-cn/device-dev/subsystems/figure/UGO\350\247\204\345\210\231\344\277\241\346\201\257.png" "b/zh-cn/device-dev/subsystems/figures/UGO\350\247\204\345\210\231\344\277\241\346\201\257.png" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/UGO\350\247\204\345\210\231\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/subsystems/figures/UGO\350\247\204\345\210\231\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" "b/zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" rename to "zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" diff --git "a/zh-cn/device-dev/subsystems/figure/USB\346\234\215\345\212\241\346\236\266\346\236\204\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/USB\346\234\215\345\212\241\346\236\266\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/USB\346\234\215\345\212\241\346\236\266\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figures/USB\346\234\215\345\212\241\346\236\266\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figure/kconfig\344\277\235\345\255\230.PNG" "b/zh-cn/device-dev/subsystems/figures/kconfig\344\277\235\345\255\230.PNG" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/kconfig\344\277\235\345\255\230.PNG" rename to "zh-cn/device-dev/subsystems/figures/kconfig\344\277\235\345\255\230.PNG" diff --git "a/zh-cn/device-dev/subsystems/figure/kconfig\345\217\202\346\225\260\350\276\223\345\205\245.gif" "b/zh-cn/device-dev/subsystems/figures/kconfig\345\217\202\346\225\260\350\276\223\345\205\245.gif" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/kconfig\345\217\202\346\225\260\350\276\223\345\205\245.gif" rename to "zh-cn/device-dev/subsystems/figures/kconfig\345\217\202\346\225\260\350\276\223\345\205\245.gif" diff --git "a/zh-cn/device-dev/subsystems/figure/kconfig\347\225\214\351\235\242.PNG" "b/zh-cn/device-dev/subsystems/figures/kconfig\347\225\214\351\235\242.PNG" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/kconfig\347\225\214\351\235\242.PNG" rename to "zh-cn/device-dev/subsystems/figures/kconfig\347\225\214\351\235\242.PNG" diff --git "a/zh-cn/device-dev/subsystems/figure/kconfig\351\203\250\344\273\266\351\200\211\346\213\251.gif" "b/zh-cn/device-dev/subsystems/figures/kconfig\351\203\250\344\273\266\351\200\211\346\213\251.gif" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/kconfig\351\203\250\344\273\266\351\200\211\346\213\251.gif" rename to "zh-cn/device-dev/subsystems/figures/kconfig\351\203\250\344\273\266\351\200\211\346\213\251.gif" diff --git a/zh-cn/device-dev/subsystems/figure/ohos_device_security_level.png b/zh-cn/device-dev/subsystems/figures/ohos_device_security_level.png similarity index 100% rename from zh-cn/device-dev/subsystems/figure/ohos_device_security_level.png rename to zh-cn/device-dev/subsystems/figures/ohos_device_security_level.png diff --git a/zh-cn/device-dev/subsystems/figure/ohos_system_security_architecture.png b/zh-cn/device-dev/subsystems/figures/ohos_system_security_architecture.png similarity index 100% rename from zh-cn/device-dev/subsystems/figure/ohos_system_security_architecture.png rename to zh-cn/device-dev/subsystems/figures/ohos_system_security_architecture.png diff --git "a/zh-cn/device-dev/subsystems/figure/ril-adapter\346\250\241\345\235\227\346\236\266\346\236\204\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/ril-adapter\346\250\241\345\235\227\346\236\266\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/ril-adapter\346\250\241\345\235\227\346\236\266\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figures/ril-adapter\346\250\241\345\235\227\346\236\266\346\236\204\345\233\276.png" diff --git a/zh-cn/device-dev/subsystems/figure/unnaming.png b/zh-cn/device-dev/subsystems/figures/unnaming.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/unnaming.png rename to zh-cn/device-dev/subsystems/figures/unnaming.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001051782526.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001051782526.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001051782526.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001051782526.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052582522.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052582522.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052582522.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052582522.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052662559.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052662559.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052662559.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052662559.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052782555.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052782555.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052782555.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052782555.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052942531.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052942531.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052942531.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052942531.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053207924.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053207924.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053207924.gif rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053207924.gif diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053247975.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053247975.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053247975.gif rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053247975.gif diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054101094.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054101094.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054101094.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054101094.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054421113.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054421113.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054421113.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054421113.png diff --git "a/zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001055504010.gif old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001055504010.gif diff --git "a/zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001057990780.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001057990780.png diff --git "a/zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001057990796.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001057990796.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001059334449.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001059334449.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001059334449.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001059334449.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001060200050.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001060200050.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001060200050.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001060200050.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001061889268.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001061889268.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001061889268.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001061889268.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062014699.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062014699.png new file mode 100644 index 0000000000000000000000000000000000000000..b84f177a7d26094ea96ad7e28b9872217fe79ab8 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062014699.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062068389.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062068389.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062334618.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062334618.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062334618.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062334618.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062476933.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062476933.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062476933.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062476933.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062942690.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062942690.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062942690.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062942690.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001063839940.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001063839940.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001063839940.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001063839940.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077724150.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077724150.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077724150.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077724150.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077727032.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077727032.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077727032.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077727032.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001115123966.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001115123966.png new file mode 100644 index 0000000000000000000000000000000000000000..883dccf82ef3ec1828893afa314a66ca2f23c421 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001115123966.png differ diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001115980740.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001115980740.png similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001115980740.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001115980740.png diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001119924146.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001119924146.gif similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001119924146.gif rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001119924146.gif diff --git "a/zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151367828.gif old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151367828.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151367836.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151367836.gif new file mode 100644 index 0000000000000000000000000000000000000000..6db4ba71f91520200df7f59973e92ac2ef65f41b Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151367836.gif differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151375648.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151375648.png new file mode 100644 index 0000000000000000000000000000000000000000..a7335c79e316dcefaa91de546cf1604644e471df Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151375648.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151527640.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151527640.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151931738.jpg b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151931738.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b0b149f4db5af1e17aca7ee6a422da45d31b7b4d Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001151931738.jpg differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001153991438.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001153991438.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd08beb8d1de75f196c6794a0c741b9998ec80b3 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001153991438.gif differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154005784.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154005784.png new file mode 100644 index 0000000000000000000000000000000000000000..c06de34e1a7e72dc162d09b1a4fa5fcd25cefab3 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154005784.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154150422.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154150422.png new file mode 100644 index 0000000000000000000000000000000000000000..165f22644ae3f7c09b8fa8c382f001348e253a67 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154150422.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154150600.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154150600.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc8c68bcb337ee51204c5b1c2ae9392ff445330 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154150600.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154153558.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154153558.png new file mode 100644 index 0000000000000000000000000000000000000000..6350269abdc028f9b1b31d544b78f380e58d7a57 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154153558.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154167492.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154167492.png new file mode 100644 index 0000000000000000000000000000000000000000..0ac7c0924e931695308a819010668327ed8a8680 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154167492.png differ diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001166643927.jpg b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154351160.jpg similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001166643927.jpg rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154351160.jpg diff --git "a/zh-cn/device-dev/subsystems/figure/\347\263\273\347\273\237\345\217\202\346\225\260\346\223\215\344\275\234\345\216\237\350\257\255.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154900834.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\347\263\273\347\273\237\345\217\202\346\225\260\346\223\215\344\275\234\345\216\237\350\257\255.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001154900834.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001155060626.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001155060626.png new file mode 100644 index 0000000000000000000000000000000000000000..152ef05469dc22252a9bbcf4107276a1d9f5e8b8 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001155060626.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ace4cefd36637675f235df3cd596eca3ed218e6c Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001171507146.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001171507146.png new file mode 100644 index 0000000000000000000000000000000000000000..89c76ec783bc6e472511deb2ef5e758aa0326a92 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001171507146.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001171796557.jpg old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001171796557.jpg diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001181934155.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001181934155.png similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001181934155.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001181934155.png diff --git "a/zh-cn/device-dev/subsystems/figure/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\346\200\247\350\203\275\350\200\227\346\227\266\345\210\206\345\270\203.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001185815840.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\346\200\247\350\203\275\350\200\227\346\227\266\345\210\206\345\270\203.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001185815840.png diff --git "a/zh-cn/device-dev/subsystems/figure/\345\220\214\346\255\245\351\200\232\344\277\241\345\244\204\347\220\206.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001185974400.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\220\214\346\255\245\351\200\232\344\277\241\345\244\204\347\220\206.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001185974400.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001186134312.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001186134312.png new file mode 100644 index 0000000000000000000000000000000000000000..dddc8365b2905b3522d9692531d773817bb1bcab Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001186134312.png differ diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001192123772.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001192123772.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001192123772.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001192123772.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197367485.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197367485.png new file mode 100644 index 0000000000000000000000000000000000000000..c4eee0a41d7cafb81c103c21d586c8bc0ec53e27 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197367485.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197367495.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197367495.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197369959.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197369959.png new file mode 100644 index 0000000000000000000000000000000000000000..c7e8c809207f0dc8965a2f8a41b55f0ae2abe13b Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197369959.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197407385.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197407385.png diff --git "a/zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197407405.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197407405.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197415205.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197415205.png new file mode 100644 index 0000000000000000000000000000000000000000..d75201bb385d4a02d05c38174a5be216953da9c6 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197415205.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197495305.png old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197495305.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197896843.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197896843.png new file mode 100644 index 0000000000000000000000000000000000000000..4f0696becdda12d63cca3b93fac1a435511280bb Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001197896843.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200029619.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200029619.png new file mode 100644 index 0000000000000000000000000000000000000000..f84c996217cb2da97b197580d1efd571bbae0f71 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200029619.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200029923.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200029923.png new file mode 100644 index 0000000000000000000000000000000000000000..07840086475ed440a052f79d59f8761a8a1e62f5 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200029923.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\350\277\220\350\241\214\346\212\245\351\224\231\345\233\276.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200053087.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\350\277\220\350\241\214\346\212\245\351\224\231\345\233\276.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200053087.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200109273.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200109273.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a5dcafb1c14c744d60590bc7ad913569a2fa92c Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200109273.gif differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200109969.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200109969.png new file mode 100644 index 0000000000000000000000000000000000000000..646a47c2dd0c102749dff11b482493cb323a9e55 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200109969.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200110781.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200110781.gif new file mode 100644 index 0000000000000000000000000000000000000000..6739188f22a6a9b9d76cb7af02f9e9c708735106 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200110781.gif differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200114819.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200114819.png new file mode 100644 index 0000000000000000000000000000000000000000..57cd59a411623ac25836b4bd49221cc744db8d61 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200114819.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200115193.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200115193.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba0a218017bbe98e2c21c8aa724900f766987ae Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200115193.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200127655.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200127655.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4b608bbffd7ae3becdc918abd6ff2b041888e5 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200127655.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200128073.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200128073.png new file mode 100644 index 0000000000000000000000000000000000000000..0077b263cf4c1ddfaf162e4ad01d2f8c2d58d13d Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200128073.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200229829.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200229829.png new file mode 100644 index 0000000000000000000000000000000000000000..2f6a9a6026d86bfcdd6462825334b450e481f563 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200229829.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200230833.gif b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200230833.gif new file mode 100644 index 0000000000000000000000000000000000000000..9cd37267672d3bea422b98d95c413e26df330de8 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001200230833.gif differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001210683929.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001210683929.png new file mode 100644 index 0000000000000000000000000000000000000000..98917f4562e2a3beabda31362c4ff36ac8526e26 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001210683929.png differ diff --git a/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001214727595.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001214727595.png similarity index 100% rename from zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001214727595.png rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001214727595.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216312860.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216312860.png new file mode 100644 index 0000000000000000000000000000000000000000..dddc8365b2905b3522d9692531d773817bb1bcab Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216312860.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\233\276\357\274\210\350\267\250\350\256\276\345\244\207-\350\267\250\350\277\233\347\250\213\345\220\214\346\255\245\350\260\203\347\224\250\357\274\211.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216632830.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\233\276\357\274\210\350\267\250\350\256\276\345\244\207-\350\267\250\350\277\233\347\250\213\345\220\214\346\255\245\350\260\203\347\224\250\357\274\211.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216632830.png diff --git "a/zh-cn/device-dev/subsystems/figure/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\272\217\345\210\227\345\233\276.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216792790.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\272\217\345\210\227\345\233\276.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001216792790.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217051568.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217051568.png new file mode 100644 index 0000000000000000000000000000000000000000..3674b4bf84fd4319354c6e40ef4caf721f01905b Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217051568.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217371532.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217371532.png new file mode 100644 index 0000000000000000000000000000000000000000..af2b1557e1ab32e4c755059a98f75624ab99e54c Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217371532.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217526184.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217526184.png new file mode 100644 index 0000000000000000000000000000000000000000..8a3b4daf5fdd4d78948488046bc404bc9ffedbbd Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217526184.png differ diff --git "a/zh-cn/device-dev/subsystems/figure/\345\220\257\345\212\250\345\255\220\347\263\273\347\273\237\344\270\212\344\270\213\346\226\207.png" b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217858866.png similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\220\257\345\212\250\345\255\220\347\263\273\347\273\237\344\270\212\344\270\213\346\226\207.png" rename to zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001217858866.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001231373949.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001231373949.png new file mode 100644 index 0000000000000000000000000000000000000000..bec87564b4026335bff09e48f6f128076b76c5a0 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001231373949.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001231614023.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001231614023.png new file mode 100644 index 0000000000000000000000000000000000000000..fba8cd412fec208991aa70e2f026edfcb9b045b6 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001231614023.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261032707.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261032707.png new file mode 100644 index 0000000000000000000000000000000000000000..585d8aac7b4857645b78ab11effbe900e5350f9d Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261032707.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261272659.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261272659.png new file mode 100644 index 0000000000000000000000000000000000000000..ae69bbc6e37310dc0e1808a270292a7872de2b26 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261272659.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261812333.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261812333.png new file mode 100644 index 0000000000000000000000000000000000000000..76fd15e43b8ccf8566ed55cc0592d3f3e6580319 Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001261812333.png differ diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001267088285.png b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001267088285.png new file mode 100644 index 0000000000000000000000000000000000000000..bfc844a941ba5b9729230302cd9f676bce1e999c Binary files /dev/null and b/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001267088285.png differ diff --git "a/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\233\276\357\274\210\350\267\250\350\256\276\345\244\207-\350\267\250\350\277\233\347\250\213\345\220\214\346\255\245\350\260\203\347\224\250\357\274\211.png" "b/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\233\276\357\274\210\350\267\250\350\256\276\345\244\207-\350\267\250\350\277\233\347\250\213\345\220\214\346\255\245\350\260\203\347\224\250\357\274\211.png" new file mode 100644 index 0000000000000000000000000000000000000000..bec87564b4026335bff09e48f6f128076b76c5a0 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\233\276\357\274\210\350\267\250\350\256\276\345\244\207-\350\267\250\350\277\233\347\250\213\345\220\214\346\255\245\350\260\203\347\224\250\357\274\211.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\272\217\345\210\227\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\272\217\345\210\227\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..fba8cd412fec208991aa70e2f026edfcb9b045b6 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\345\272\217\345\210\227\345\233\276.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\346\200\247\350\203\275\350\200\227\346\227\266\345\210\206\345\270\203.png" "b/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\346\200\247\350\203\275\350\200\227\346\227\266\345\210\206\345\270\203.png" new file mode 100644 index 0000000000000000000000000000000000000000..ae69bbc6e37310dc0e1808a270292a7872de2b26 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\344\270\232\345\212\241\350\260\203\347\224\250\346\265\201\347\250\213\346\200\247\350\203\275\350\200\227\346\227\266\345\210\206\345\270\203.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" "b/zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" new file mode 100644 index 0000000000000000000000000000000000000000..1eda8dc4c7f8fa35620640b5eee085b510e0f4ea Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..330983e87925e92d7d27cbe7581993e81b812af7 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" differ diff --git "a/zh-cn/device-dev/subsystems/figure/\345\216\273\347\224\265\350\260\203\347\224\250\346\227\266\345\272\217\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\345\216\273\347\224\265\350\260\203\347\224\250\346\227\266\345\272\217\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\216\273\347\224\265\350\260\203\347\224\250\346\227\266\345\272\217\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figures/\345\216\273\347\224\265\350\260\203\347\224\250\346\227\266\345\272\217\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\220\214\346\255\245\351\200\232\344\277\241\345\244\204\347\220\206.png" "b/zh-cn/device-dev/subsystems/figures/\345\220\214\346\255\245\351\200\232\344\277\241\345\244\204\347\220\206.png" new file mode 100644 index 0000000000000000000000000000000000000000..585d8aac7b4857645b78ab11effbe900e5350f9d Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\345\220\214\346\255\245\351\200\232\344\277\241\345\244\204\347\220\206.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\345\220\257\345\212\250\345\255\220\347\263\273\347\273\237\344\270\212\344\270\213\346\226\207.png" "b/zh-cn/device-dev/subsystems/figures/\345\220\257\345\212\250\345\255\220\347\263\273\347\273\237\344\270\212\344\270\213\346\226\207.png" new file mode 100644 index 0000000000000000000000000000000000000000..e524495360609969011d8554d197ee04175e6b8f Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\345\220\257\345\212\250\345\255\220\347\263\273\347\273\237\344\270\212\344\270\213\346\226\207.png" differ diff --git "a/zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" "b/zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" rename to "zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..a8ca6625852cfbce3d1cd156a52fd76a299084ad Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..2111dd19967c6f8d960a4e93891ddde7f8825225 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" "b/zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" rename to "zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" "b/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" new file mode 100644 index 0000000000000000000000000000000000000000..a8954112f6b94d422bce3c1f445aa0de6c2499cc Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" "b/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" new file mode 100644 index 0000000000000000000000000000000000000000..276dfb6048e96d289c0074bd320ff7bfb4f1ab9d Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" "b/zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" new file mode 100644 index 0000000000000000000000000000000000000000..1bd6879c1955f9131cd12ea17a2d8c0e52be6ab1 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" differ diff --git "a/zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" "b/zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" "b/zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" rename to "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\347\263\273\347\273\237\345\217\202\346\225\260\346\223\215\344\275\234\345\216\237\350\257\255.png" "b/zh-cn/device-dev/subsystems/figures/\347\263\273\347\273\237\345\217\202\346\225\260\346\223\215\344\275\234\345\216\237\350\257\255.png" new file mode 100644 index 0000000000000000000000000000000000000000..54c15c441dbb8f305ff4d6031b45c2eb8cb28d6c Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\347\263\273\347\273\237\345\217\202\346\225\260\346\223\215\344\275\234\345\216\237\350\257\255.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..dc3dcd37c644867a2de9ba4209aaeeedcedecbe8 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" "b/zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..3e296c97b64e317bb92849d80588d5ab5419b31e Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..2e412ac913dc9b7bd4f1ff1729bfe017b02b4a7a Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" "b/zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" new file mode 100644 index 0000000000000000000000000000000000000000..9d8039f69db3919dd3ddf716bc58d053948479ee Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" differ diff --git "a/zh-cn/device-dev/subsystems/figures/\350\277\220\350\241\214\346\212\245\351\224\231\345\233\276.png" "b/zh-cn/device-dev/subsystems/figures/\350\277\220\350\241\214\346\212\245\351\224\231\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..015c38ba5516395527bcf6715535238f02b2bad9 Binary files /dev/null and "b/zh-cn/device-dev/subsystems/figures/\350\277\220\350\241\214\346\212\245\351\224\231\345\233\276.png" differ diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md index 7294044a11012f8037da2206151c2ecabcafe6f2..3ceb3d8dab4a1077a3476b8ae9acd92757023c24 100755 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md @@ -1,54 +1,53 @@ -# 唤醒词识别配置文件的开发示例 - -1. 代码路径//foundation/ai/engine/services/common/protocol/plugin\_config/plugin\_config\_ini/中添加唤醒词识别的配置文件 - - ``` - [base] - supported_boards = hi3516dv300 - related_sessions = asr_keyword_spotting+20001002 - - //[asr_keyword_spotting+20001002]的命名规则为[算法名称+算法version] - [asr_keyword_spotting+20001002] - AID = asr_keyword_spotting - VersionCode = 20001002 - VersionName = 2.00.01.002 - XPU = NNIE - District = China - // 编译出的插件so所在的位置 - FullPath = /usr/lib/libasr_keyword_spotting.so - Chipset = ALL - ChkSum = '' - Key = '' - ``` - -2. 代码路径//foundation/ai/engine/services/common/protocol/plugin\_config/aie\_algorithm\_type.h文件中添加唤醒词识别算法类型id。 - - ``` - // 唤醒词识别的算法类型id与唤醒词识别在ALGORITHM_TYPE_ID_LITS中的序号一一对应 - const int ALGORITHM_TYPE_KWS = 3; - ``` - -3. 代码路径//foundation/ai/engine/services/server/plugin\_manager/include/aie\_plugin\_info.h文件中添加唤醒词识别算法名称及在ALGORITHM\_TYPE\_ID\_LITS中的序号 - - ``` - const std::string ALGORITHM_ID_SAMPLE_1 = "sample_plugin_1"; - const std::string ALGORITHM_ID_SAMPLE_2 = "sample_plugin_2"; - const std::string ALGORITHM_ID_IVP = "cv_human_detect"; - // 添加唤醒词识别的算法名称asr_keyword_spotting - // 算法的变量名称与ALGORITHM_TYPE_ID_LIST中算法typeId命名相同,例如;ALGORITHM_ID_KWS - const std::string ALGORITHM_ID_KWS = "asr_keyword_spotting"; - const std::string ALGORITHM_ID_IC = "cv_image_classification"; - const std::string ALGORITHM_ID_INVALID = "invalid algorithm id"; - - const std::vector ALGORITHM_TYPE_ID_LIST = { - ALGORITHM_ID_SAMPLE_1, - ALGORITHM_ID_SAMPLE_2, - ALGORITHM_ID_IVP, - // 添加唤醒词识别在ALGORITHM_TYPE_ID_LITS中的序号,通过该序号可获得唤醒词识别的算法名称 - // 唤醒词识别的算法名称和唤醒词识别在ALGORITHM_TYPE_ID_LITS中的序号顺序需保持一致 - ALGORITHM_ID_KWS, - ALGORITHM_ID_IC, - }; - ``` - - +# 唤醒词识别配置文件的开发示例 + + +1. 代码路径//foundation/ai/engine/services/common/protocol/plugin_config/plugin_config_ini/中添加唤醒词识别的配置文件。 + + ``` + [base] + supported_boards = hi3516dv300 + related_sessions = asr_keyword_spotting+20001002 + + //[asr_keyword_spotting+20001002]的命名规则为[算法名称+算法version] + [asr_keyword_spotting+20001002] + AID = asr_keyword_spotting + VersionCode = 20001002 + VersionName = 2.00.01.002 + XPU = NNIE + District = China + // 编译出的插件so所在的位置 + FullPath = /usr/lib/libasr_keyword_spotting.so + Chipset = ALL + ChkSum = '' + Key = '' + ``` + +2. 代码路径//foundation/ai/engine/services/common/protocol/plugin_config/aie_algorithm_type.h文件中添加唤醒词识别算法类型id。 + + ``` + // 唤醒词识别的算法类型id与唤醒词识别在ALGORITHM_TYPE_ID_LIST中的序号一一对应 + const int ALGORITHM_TYPE_KWS = 3; + ``` + +3. 代码路径//foundation/ai/engine/services/server/plugin_manager/include/aie_plugin_info.h文件中添加唤醒词识别算法名称及在ALGORITHM_TYPE_ID_LIST中的序号。 + + ``` + const std::string ALGORITHM_ID_SAMPLE_1 = "sample_plugin_1"; + const std::string ALGORITHM_ID_SAMPLE_2 = "sample_plugin_2"; + const std::string ALGORITHM_ID_IVP = "cv_human_detect"; + // 添加唤醒词识别的算法名称asr_keyword_spotting + // 算法的变量名称与ALGORITHM_TYPE_ID_LIST中算法typeId命名相同,例如:ALGORITHM_ID_KWS + const std::string ALGORITHM_ID_KWS = "asr_keyword_spotting"; + const std::string ALGORITHM_ID_IC = "cv_image_classification"; + const std::string ALGORITHM_ID_INVALID = "invalid algorithm id"; + + const std::vector ALGORITHM_TYPE_ID_LIST = { + ALGORITHM_ID_SAMPLE_1, + ALGORITHM_ID_SAMPLE_2, + ALGORITHM_ID_IVP, + // 添加唤醒词识别在ALGORITHM_TYPE_ID_LIST中的序号,通过该序号可获得唤醒词识别的算法名称 + // 唤醒词识别的算法名称和唤醒词识别在ALGORITHM_TYPE_ID_LIST中的序号顺序需保持一致 + ALGORITHM_ID_KWS, + ALGORITHM_ID_IC, + }; + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md index 931a8550a5356535ded28bee08497b383afe52ce..fbe5f2ba9b659a2d614ea027ad6c041a36f2ca01 100755 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md @@ -1,91 +1,45 @@ -# 唤醒词识别插件的开发示例 - -1. 在//foundation/ai/engine/services/server/plugin的目录中添加唤醒词识别插件的接口定义,并实现AI能力的调用。如下代码片段即实现唤醒词识别的算法插件的接口定义。更多插件开发的相关代码参考路径如下://foundation/ai/engine/services/server/plugin/asr/keyword\_spotting - - ``` - #include "plugin/i_plugin.h - class KWSPlugin : public IPlugin { - public: - KWSPlugin(); - ~KWSPlugin(); - const long long GetVersion() const override; - const char* GetName() const override; - const char* GetInferMode() const override; - int32_t Prepare(long long transactionId, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override; - int32_t SetOption(int optionType, const DataInfo &amp;inputInfo) override; - int32_t GetOption(int optionType, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override; - int32_t SyncProcess(IRequest *request, IResponse *&amp;response) override; - int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override; - int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;inputInfo) override; - }; - ``` - - 上述代码实现server提供的IPlugin接口。唤醒词识别的sample中调用的client端接口与插件中的接口对应关系及其实现功能如表[1](#table567211582104)所示。 - - **表 1** 唤醒词识别中client端接口与插件接口对应关系 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

client端定义的接口

-

插件中定义的接口

-

功能

-

AieClientPrepare

-

Prepare

-

提供推理算法插件初始化功能,以唤醒词识别为例:加载唤醒词识别模型,将固定位置(/sdcard/wenwen_inst.wk)模型加载至内存。

-

AieClientSyncProcess

-

SyncProcess

-

提供同步执行推理算法的能力,以唤醒词识别为例:实现同步执行音频推理算法,判断音频中是否存在唤醒词。

-

AieClientAsyncProcess

-

AsyncProcess

-

提供异步执行推理算法的能力,当前唤醒词识别场景不涉及,但开发者可根据具体场景自行实现。

-

AieClientSetOption

-

SetOption

-

提供手动设置算法相关配置项,如置信度阈值、时延等超参数的能力,当前唤醒词识别场景未涉及。开发者可视具体场景自行实现。

-

AieClientGetOption

-

GetOption

-

提供获取算法相关配置项,以唤醒词识别为例:获取唤醒词模型中输入输出的规模,输入规模即为唤醒词识别模型要求输入的MFCC特征的维度(固定值:4000),输出规模即为结果的置信度得分维度(固定值:2)。

-

AieClientRelease

-

Release

-

提供卸载算法模型功能,以唤醒词识别为例:实现卸载相关模型,并将特征处理器中的动态内存清理。

-
- - 注意: - - 1.接口AieClientInit、AieClientDestroy分别用于与server端建立和断开连接,未调用到插件算法中,因此插件中无需定义与之对应的接口。 - - 2.唤醒词识别插件需要使用PLUGIN\_INTERFACE\_IMPL语句对外暴露函数指针,否则插件将无法被正常加载使用。 - - ``` - PLUGIN_INTERFACE_IMPL(KWSPlugin); - ``` - - +# 唤醒词识别插件的开发示例 + + +1. 在//foundation/ai/engine/services/server/plugin的目录中添加唤醒词识别插件的接口定义(IPlugin),并实现AI能力的调用。如下代码片段即实现唤醒词识别的算法插件的接口定义。更多插件开发的相关代码参考路径如下://foundation/ai/engine/services/server/plugin/asr/keyword_spotting + + ``` + #include "plugin/i_plugin.h + class KWSPlugin : public IPlugin { + public: + KWSPlugin(); + ~KWSPlugin(); + const long long GetVersion() const override; + const char* GetName() const override; + const char* GetInferMode() const override; + int32_t Prepare(long long transactionId, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override; + int32_t SetOption(int optionType, const DataInfo &amp;inputInfo) override; + int32_t GetOption(int optionType, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override; + int32_t SyncProcess(IRequest *request, IResponse *&amp;response) override; + int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override; + int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;inputInfo) override; + }; + ``` + + 上述代码实现server提供的IPlugin接口。唤醒词识别的sample中调用的client端接口与插件中的接口对应关系及其实现功能如下表所示。 + **表1** 唤醒词识别中client端接口与插件接口对应关系 + + | client端定义的接口 | 插件中定义的接口 | 功能 | + | -------- | -------- | -------- | + | AieClientPrepare | Prepare | 提供推理算法插件初始化功能,例如:加载唤醒词识别模型,将固定位置(/sdcard/wenwen_inst.wk)模型加载至内存。 | + | AieClientSyncProcess | SyncProcess | 提供同步执行推理算法的能力,例如:实现同步执行音频推理算法,判断音频中是否存在唤醒词。 | + | AieClientAsyncProcess | AsyncProcess | 提供异步执行推理算法的能力,当前唤醒词识别场景不涉及,但开发者可根据具体场景自行实现。 | + | AieClientSetOption | SetOption | 提供手动设置算法相关配置项,如置信度阈值、时延等超参数的能力,当前唤醒词识别场景未涉及。开发者可视具体场景自行实现。 | + | AieClientGetOption | GetOption | 提供获取算法相关配置项,以唤醒词识别为例:获取唤醒词模型中输入输出的规模,输入规模即为唤醒词识别模型要求输入的MFCC特征的维度(固定值:4000),输出规模即为结果的置信度得分维度(固定值:2)。 | + | AieClientRelease | Release | 提供卸载算法模型功能,以唤醒词识别为例:实现卸载相关模型,并将特征处理器中的动态内存清理。 | + + 注意: + + 1.接口AieClientInit、AieClientDestroy分别用于与server端建立和断开连接,未调用到插件算法中,因此插件中无需定义与之对应的接口。 + + 2.唤醒词识别插件需要使用PLUGIN_INTERFACE_IMPL语句对外暴露函数指针,否则插件将无法被正常加载使用。 + + + ``` + PLUGIN_INTERFACE_IMPL(KWSPlugin); + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md index 795599d87226dbe1e7150574143f4b739c042c0f..1c551c680580c8e0cebd94b6275a3d0aa47af3d7 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md @@ -1,81 +1,80 @@ -# 唤醒词识别SDK的开发示例 +# 唤醒词识别SDK的开发示例 -1. 在//foundation/ai/engine /interfaces/kits目录中添加唤醒词识别SDK的API接口定义,该接口可用三方应用的调用。如下代码片段即为唤醒词识别定义的API接口示例,其相关代码参考路径为://foundation/ai/engine /interfaces/kits/asr/keyword\_spotting。 - ``` - class KWSSdk { - public: - KWSSdk(); - virtual ~KWSSdk(); - - // 定义了创建唤醒词检测工具包的方法 - int32_t Create(); - - // 定义了同步执行唤醒词检测任务的方法 - int32_t SyncExecute(const Array &audioInput); - - // 定义了设置唤醒词检测回调器的方法 - int32_t SetCallback(const std::shared_ptr &callback); - - // 定义了销毁唤醒词工具包的方法,释放与插件的会话信息。 - int32_t Destroy(); - }; - ``` +1. 在//foundation/ai/engine /interfaces/kits目录中添加唤醒词识别SDK的API接口定义,该接口可用三方应用的调用。如下代码片段即为唤醒词识别定义的API接口示例,其相关代码参考路径为://foundation/ai/engine /interfaces/kits/asr/keyword_spotting。 + + ``` + class KWSSdk { + public: + KWSSdk(); + virtual ~KWSSdk(); + + // 定义创建唤醒词检测工具包的方法。 + int32_t Create(); + + // 定义同步执行唤醒词检测任务的方法。 + int32_t SyncExecute(const Array &audioInput); + + // 定义设置唤醒词检测回调器的方法。 + int32_t SetCallback(const std::shared_ptr &callback); + + // 定义销毁唤醒词工具包的方法,释放与插件的会话信息。 + int32_t Destroy(); + }; + ``` -2. 在//foundation/ai/engine/services/client/algorithm\_sdk的目录中增加SDK中API接口的具体实现,调用client端提供的接口,实现算法插件能力的使用。如下代码片段即为唤醒词识别的API接口中create方法的具体实现示例,更多详细代码可参考://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting。 - - ``` - int32_t KWSSdk::KWSSdkImpl::Create() - { - if (kwsHandle_ != INVALID_KWS_HANDLE) { - HILOGE("[KWSSdkImpl]The SDK has been created"); - return KWS_RETCODE_FAILURE; - } - if (InitComponents() != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]Fail to init sdk components"); - return KWS_RETCODE_FAILURE; - } - // 调用client端提供的接口AieClientInit,实现初始化引擎服务,激活跨进程调用 - int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode); - return KWS_RETCODE_FAILURE; - } - if (clientInfo_.clientId == INVALID_CLIENT_ID) { - HILOGE("[KWSSdkImpl]Fail to allocate client id"); - return KWS_RETCODE_FAILURE; - } - DataInfo inputInfo = { - .data = nullptr, - .length = 0, - }; - DataInfo outputInfo = { - .data = nullptr, - .length = 0, - }; - // 调用client端提供的接口AieClientPrepare,实现加载算法插件 - retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode); - return KWS_RETCODE_FAILURE; - } - if (outputInfo.data == nullptr || outputInfo.length <= 0) { - HILOGE("[KWSSdkImpl]The data or length of output info is invalid"); - return KWS_RETCODE_FAILURE; - } - MallocPointerGuard pointerGuard(outputInfo.data); - retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]Get handle from inputInfo failed"); - return KWS_RETCODE_FAILURE; - } - return KWS_RETCODE_SUCCESS; - } - ``` - - 上述代码为API接口的具体实现,从上述示例的代码中,SDK中create接口的具体实现即为下述示例代码中create方法,该方法调用了AI引擎框架client端开放接口AieClientInit,AieClientPrepare,从而实现与server端建立连接及加载算法模型的能力。 - - >![](../public_sys-resources/icon-note.gif) **说明:** - >SDK调用AI引擎client端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码。 +2. 在//foundation/ai/engine/services/client/algorithm_sdk的目录中增加SDK中API接口的具体实现,调用client端提供的接口,实现算法插件能力的使用。如下代码片段即为唤醒词识别的API接口中create方法的具体实现示例,更多详细代码可参考://foundation/ai/engine/services/client/algorithm_sdk/asr/keyword_spotting。 + + ``` + int32_t KWSSdk::KWSSdkImpl::Create() + { + if (kwsHandle_ != INVALID_KWS_HANDLE) { + HILOGE("[KWSSdkImpl]The SDK has been created"); + return KWS_RETCODE_FAILURE; + } + if (InitComponents() != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]Fail to init sdk components"); + return KWS_RETCODE_FAILURE; + } + // 调用client端提供的接口AieClientInit,实现初始化引擎服务,激活跨进程调用 + int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode); + return KWS_RETCODE_FAILURE; + } + if (clientInfo_.clientId == INVALID_CLIENT_ID) { + HILOGE("[KWSSdkImpl]Fail to allocate client id"); + return KWS_RETCODE_FAILURE; + } + DataInfo inputInfo = { + .data = nullptr, + .length = 0, + }; + DataInfo outputInfo = { + .data = nullptr, + .length = 0, + }; + // 调用client端提供的接口AieClientPrepare,实现加载算法插件 + retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode); + return KWS_RETCODE_FAILURE; + } + if (outputInfo.data == nullptr || outputInfo.length <= 0) { + HILOGE("[KWSSdkImpl]The data or length of output info is invalid"); + return KWS_RETCODE_FAILURE; + } + MallocPointerGuard pointerGuard(outputInfo.data); + retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]Get handle from inputInfo failed"); + return KWS_RETCODE_FAILURE; + } + return KWS_RETCODE_SUCCESS; + } + ``` + 上述代码为API接口的具体实现,从上述示例的代码中,SDK中create接口的具体实现即为上述示例代码中create方法,该方法调用了AI引擎框架client端开放接口AieClientInit,AieClientPrepare,从而实现与server端建立连接及加载算法模型的能力。 + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > SDK调用AI引擎client端接口顺序应遵循AieClientInit->AieClientPrepare->AieClientSyncProcess/AieClientAsyncProcess->AieClientRelease->AieClientDestroy,否则调用接口会返回错误码。 diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md index 054336dafd8be39390dfed958dc9d1576a3d297a..fc9b90ea1ca4a91cff0eaba6c275fcfc3dd5e08d 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md @@ -1,13 +1,14 @@ -# 开发示例 +# 开发示例 -以开发唤醒词识别为例,开发者可在Hi3516DV300开发板上,基于AI引擎框架开发唤醒词识别的sdk以及唤醒词识别的plugin,通过编译命令编出新的版本镜像并将其烧入版本。同时,开发者开发唤醒词识别的应用,该应用能够接收外部音频,将listen到的音频传入SDK中的接口,若音频中带有关键词,唤醒词识别的应用会识别出相应的词语,并打印在命令行中。 -本示例中唤醒词识别的场景中唤醒词是固定的,当开发者传入的音频包含”Hi,小问“,启动的应用就会打印"\[Hi, xiaowen\]",当不包含时,会打印'\[UNKNOWN\]"。 +以开发唤醒词识别为例,开发者可在Hi3516DV300开发板上,基于AI引擎框架开发唤醒词识别的SDK以及唤醒词识别的plugin,通过编译命令编出新的版本镜像并将其烧入版本。同时,开发者开发唤醒词识别的应用,该应用能够接收外部音频,将listen到的音频传入SDK中的接口,若音频中带有关键词,唤醒词识别的应用会识别出相应的词语,并打印在命令行中。 -- **[唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md)** -- **[唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md)** +本示例中唤醒词识别的场景中唤醒词是固定的,当开发者传入的音频包含”Hi,小问“,启动的应用就会打印"[Hi, xiaowen]",当不包含时,会打印'[UNKNOWN]"。 -- **[唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md)** +- **[唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md)** +- **[唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md)** + +- **[唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md index 3bc63cbfcf482edc79d656e60be413346ce241c7..cab853a3903266bf3e090cea7bfa6171a074104b 100755 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md @@ -1,10 +1,14 @@ -# 配置文件的开发过程 +# 配置文件的开发过程 + 开发者开发的SDK通过AlgorithmInfo结构体中algorithmVersion以及algorithmType识别出具体的插件类型,实现插件能力的调用。因此开发者需完成以下步骤: -1. 代码路径//foundation/ai/engine/services/common/protocol/plugin\_config/plugin\_config\_ini/目录中添加插件的配置文件。 -2. 代码路径//foundation/ai/engine/services/common/protocol/plugin\_config/aie\_algorithm\_type.h文件中添加算法类型。 -3. 代码路径//foundation/ai/engine/services/server/plugin\_manager/include/aie\_plugin\_info.h文件中添加唤醒词识别的算法名称及其在ALGORITHM\_TYPE\_ID\_LITS中的序号。 -具体开发过程可参考唤醒词识别配置文件开发示例。 +1. 代码路径//foundation/ai/engine/services/common/protocol/plugin_config/plugin_config_ini/目录中添加插件的配置文件。 + +2. 代码路径//foundation/ai/engine/services/common/protocol/plugin_config/aie_algorithm_type.h文件中添加算法类型。 + +3. 代码路径//foundation/ai/engine/services/server/plugin_manager/include/aie_plugin_info.h文件中添加唤醒词识别的算法名称及其在ALGORITHM_TYPE_ID_LIST中的序号。 + +具体开发过程可参考[唤醒词识别配置文件开发示例](../subsystems/subsys-aiframework-demo-conf.md)。 diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md index 2881394f58cec0b44b99f7205331b4148b04aa9f..d27df1b89c4ab2fe735014fb84364116da0bfca9 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md @@ -1,261 +1,71 @@ -# 插件的开发过程 +# 插件的开发过程 + AI引擎框架规定了一套算法插件接入规范,各插件需实现规定接口以实现获取插件版本信息、算法推理类型、同步执行算法、异步执行算法、加载算法插件、卸载算法插件、设置算法配置信息、获取指定算法配置信息等功能。(同步算法实现SyncProcess接口,异步算法实现AsyncProcess接口)。 -1)算法插件类IPlugin接口设计如下[表1](#table1329717488505)所示。 -**表 1** 算法插件类IPlugin接口设计 +1)算法插件类IPlugin接口设计如下表所示。 + + + **表1** 算法插件类IPlugin接口设计 + +| 接口名 | 接口说明 | 参数要求 | +| -------- | -------- | -------- | +| const long long GetVersion() const; | **作用**:获取插件版本信息。
**返回值**:版本号(long long) | - | +| const char \*GetInferMode() const; | **作用**:获取算法推理类型。
**返回值**:"SYNC" or "ASYNC"; | - | +| int SyncProcess(IRequest \*request,
IResponse \*&response); | **作用**:执行插件同步算法。
**返回值**:0为成功,其他返回值失败。 | **request**(NOT NULL):用于向算法插件传递请求内容;引擎服务端与插件的数据通道;
**response**(NOT NULL):作为出参用于接收算法插件发回的同步算法执行结果,引擎服务端与插件的数据通道; | +| int AsyncProcess(IRequest \*request,
IPluginAlgorithmCallback \*callback); | **作用**:执行异步算法。
**返回值**:0为成功,其他返回值失败。 | **request**(NOT NULL):用于向算法插件传递请求内容;引擎服务端与插件的数据通道。
**callback**(NOT NULL):算法插件异步执行结果通过此回调返回引擎服务端; | +| int Prepare(long long transactionId,
const DataInfo &inputInfo, DataInfo
&outputInfo); | **作用**:加载算法插件。
**返回值**:0为成功,其他返回值失败。 | **transactionId**(NOT NULL):事务ID,用于标记客户端+会话信息;
**inputInfo**(可为NULL):加载算法插件传入的一些信息;
**outputInfo**(可为NULL):调用加载接口时的出参,返回相关执行结果; | +| int Release(bool isFullUnload, long long
transactionId, const DataInfo &inputInfo); | **作用**:卸载相关算法插件。
**返回值**:0为成功,其他返回值失败。 | **isFullUnload**(NOT NULL):表示此插件是否只剩一个client调用,否则不能直接卸载插件,需等最后一个client来进行卸载;
**transactionId**(NOT NULL):事务ID,用于标记客户端+会话信息;
**inputInfo**(可为NULL):卸载算法插件传入的一些信息; | +| int SetOption(int optionType, const
DataInfo &inputInfo); | **作用**:设置配置项,可将一些算法的拓展信息通过此接口传入插件。
**返回值**:0为成功,其他返回值失败。 | **optionType** (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;
**inputInfo**(可为NULL):插件可根据需要通过此入参设置算法参数信息; | +| int GetOption(int optionType, const
DataInfo &inputInfo, DataInfo
&outputInfo); | **作用**:给定特定的optionType和inputInfo,获取其对应的配置项信息。
**返回值**:0为成功,其他返回值失败。 | **optionType**(NOT NULL):所获取配置项信息的对应算法状态位;
**inputInfo**(可为NULL):所获取配置项信息的对应算法参数信息;
**outputInfo**(可为NULL):所要获取的配置项信息返回结果; | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

接口说明

-

参数要求

-

const long long GetVersion() const;

-

作用:获取插件版本信息。

-

返回值:版本号(long long)

-

-

-

const char *GetInferMode() const;

-

作用:获取算法推理类型。

-

返回值:"SYNC" or "ASYNC";

-

-

-

int SyncProcess(IRequest *request, IResponse *&response);

-

作用:执行插件同步算法。

-

返回值:0为成功,其他返回值失败。

-

request(NOT NULL):用于向算法插件传递请求内容;引擎服务端与插件的数据通道;

-

response(NOT NULL):作为出参用于接收算法插件发回的同步算法执行结果,引擎服务端与插件的数据通道;

-

int AsyncProcess(IRequest *request, IPluginAlgorithmCallback *callback);

-

作用:执行异步算法。

-

返回值:0为成功,其他返回值失败。

-

request(NOT NULL):用于向算法插件传递请求内容;引擎服务端与插件的数据通道。

-

callback(NOT NULL):算法插件异步执行结果通过此回调返回引擎服务端;

-

int Prepare(long long transactionId, const DataInfo &inputInfo, DataInfo &outputInfo);

-

作用:加载算法插件。

-

返回值:0为成功,其他返回值失败。

-

transactionId(NOT NULL):事务ID,用于标记客户端+会话信息;

-

inputInfo(可为NULL):加载算法插件传入的一些信息;

-

outputInfo(可为NULL):调用加载接口时的出参,返回相关执行结果;

-

int Release(bool isFullUnload, long long transactionId, const DataInfo &inputInfo);

-

作用:卸载相关算法插件。

-

返回值:0为成功,其他返回值失败。

-

isFullUnload(NOT NULL):表示此插件是否只剩一个client调用,否则不能直接卸载插件,需等最后一个client来进行卸载;

-

transactionId(NOT NULL):事务ID,用于标记客户端+会话信息;

-

inputInfo(可为NULL):卸载算法插件传入的一些信息;

-

int SetOption(int optionType, const DataInfo &inputInfo);

-

作用:设置配置项,可将一些算法的拓展信息通过此接口传入插件。

-

返回值:0为成功,其他返回值失败。

-

optionType (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;

-

inputInfo(可为NULL):插件可根据需要通过此入参设置算法参数信息;

-

int GetOption(int optionType, const DataInfo &inputInfo, DataInfo &outputInfo);

-

作用:给定特定的optionType和inputInfo,获取其对应的配置项信息。

-

返回值:0为成功,其他返回值失败。

-

optionType(NOT NULL):所获取配置项信息的对应算法状态位;

-

inputInfo(可为NULL):所获取配置项信息的对应算法参数信息;

-

outputInfo(可为NULL):所要获取的配置项信息返回结果;

-
算法插件类接口:Prepare、SyncProcess、AsyncProcess、Release、SetOption、GetOption分别于客户端接口AieClientPrepare、AieClientSyncProcess、AieClientAsyncProcess、AieClientRelease、AieClientSetOption、AieClientGetOption一一对应;GetInferMode接口用于返回算法执行类型——同步或异步。 -2)算法插件回调类IPluginCallback 接口设计如[表2](#table461192635114)所示。 -**表 2** 算法插件回调类IPluginCallback 接口设计 +2)算法插件回调类IPluginCallback 接口设计如下表所示。 + + + **表2** 算法插件回调类IPluginCallback 接口设计 + +| 接口名 | 接口说明 | 参数要求 | +| -------- | -------- | -------- | +| void OnEvent(PluginEvent event,
IResponse \*response); | 作用:插件通过此回调返回异步算法执行结果。 | **event**:算法执行结果枚举,‘ON_PLUGIN_SUCCEED’或 ‘ON_PLUGIN_FAIL’(成功或者失败);
**response**:算法执行结果封装; | - - - - - - - - - - - -

接口名

-

接口说明

-

参数要求

-

void OnEvent(PluginEvent event, IResponse *response);

-

作用:插件通过此回调返回异步算法执行结果。

-

event:算法执行结果枚举,‘ON_PLUGIN_SUCCEED’或 ‘ON_PLUGIN_FAIL’(成功或者失败);

-

response:算法执行结果封装;

-
Request、Response是ai引擎服务端与算法插件进行通信的对象。Request封装了调用方的请求、输入数据等,而插件主要通过Response将运算之后的结果返回给AI引擎服务端。 -Request类的属性如下[表3](#table16273647125120)所示。 -**表 3** Request类的属性 +Request类的属性如下表所示。 + + + **表3** Request类的属性 + +| 属性名称 | 属性说明 | 默认值 | +| -------- | -------- | -------- | +| innerSequenceId_ | 类型:long long
作用:暂未启用。 | 0 | +| requestId_ | 类型:int
作用:标识请求序列,用于绑定返回运算结果。 | 0 | +| operationId_ | 类型:int
作用:目前暂未启用。 | 0 | +| transactionId_ | 类型:long long
作用:事务ID,唯一标识clientId+sessionId。 | 0 | +| algoPluginType_ | 类型:int
作用:引擎框架根据插件加载顺序分配的算法类型的ID。 | 0 | +| msg_ | 类型:DataInfo
作用:存放调用算法接口的输入数据。 | .data = nullptr
.length = 0 | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

属性名称

-

属性说明

-

默认值

-

innerSequenceId_

-

类型:long long

-

作用:暂未启用。

-

0

-

requestId_

-

类型:int

-

作用:标识请求序列,用于绑定返回运算结果。

-

0

-

operationId_

-

类型:int

-

作用:目前暂未启用。

-

0

-

transactionId_

-

类型:long long

-

作用:事务ID,唯一标识clientId+sessionId。

-

0

-

algoPluginType_

-

类型:int

-

作用:引擎框架根据插件加载顺序分配的算法类型的ID。

-

0

-

msg_

-

类型:DataInfo

-

作用:存放调用算法接口的输入数据。

-

.data = nullptr

-

.length = 0

-
+Response类的属性如下下表所示。 -Response类的属性如下[表4](#table1798597135212)所示。 -**表 4** Response类的属性 + **表4** Response类的属性 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

属性名称

-

属性说明

-

默认值

-

innerSequenceId_

-

类型:long long

-

作用:暂未启用。

-

0

-

requestId_

-

类型:int

-

作用:标识请求序列,用于绑定返回运算结果。

-

0

-

retCode__

-

类型:int

-

作用:异步执行算法推理结果码。

-

0

-

retDesc_

-

类型:string

-

作用:暂未启用。

-

-

-

transactionId_

-

类型:long long

-

作用:事务ID,唯一标识clientId+sessionId。

-

0

-

algoPluginType_

-

类型:int

-

作用:引擎框架根据插件加载顺序分配的算法类型的ID。

-

INVALID_ALGO_PLUGIN_TYPE(-1)

-

result_

-

类型:DataInfo

-

作用:存放异步算法推理结果。

-

.data = nullptr

-

.length = 0

-
+| 属性名称 | 属性说明 | 默认值 | +| -------- | -------- | -------- | +| innerSequenceId_ | 类型:long long
作用:暂未启用。 | 0 | +| requestId_ | 类型:int
作用:标识请求序列,用于绑定返回运算结果。 | 0 | +| retCode__ | 类型:int
作用:异步执行算法推理结果码。 | 0 | +| retDesc_ | 类型:string
作用:暂未启用。 | - | +| transactionId_ | 类型:long long
作用:事务ID,唯一标识clientId+sessionId。 | 0 | +| algoPluginType_ | 类型:int
作用:引擎框架根据插件加载顺序分配的算法类型的ID。 | INVALID_ALGO_PLUGIN_TYPE(-1) | +| result_ | 类型:DataInfo
作用:存放异步算法推理结果。 | .data = nullptr
.length = 0 | -具体开发过程可参考唤醒词识别插件开发示例。 +具体开发过程可参考[唤醒词识别插件开发示例](../subsystems/subsys-aiframework-demo-plugin.md)。 diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md index ed8f624d68c07f4791327fc7b161a793a07e54a8..f0b17cad1462b05a9bcabdb4ceae36d8ad06db56 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md @@ -1,162 +1,34 @@ -# SDK开发过程 +# SDK开发过程 -SDK头文件的功能实现是基于对SDK的调用映射到对client的调用。Client端提供的接口如下[表1](#table203963834718)所示。 -**表 1** Client端提供的接口 +SDK头文件的功能实现是基于对SDK的调用映射到对客户端的调用。客户端端提供的接口如下表所示。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

接口说明

-

参数要求

-

int AieClientInit(const ConfigInfo &configInfo, ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, IServiceDeadCb *cb)

-

作用:链接并初始化引擎服务,激活跨进程调用。

-

返回值:0为成功,其他返回值失败。

-

configInfo(NOT NULL):引擎相关初始化配置数据;

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

cb(可为NULL):死亡回调 对象;

-

int AieClientPrepare(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo, IClientCb *cb)

-

作用:加载算法插件。

-

返回值: 0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

inputInfo(可为NULL):加载算法插件时输入所需信息;

-

outputInfo(可为NULL):加载算法插件之后如需返回信息则通过此出参返回;

-

cb:异步算法通过此回调返回运算结果,因此异步算法此结构体不能为空;若为同步算法,传入空值即可;

-

int AieClientAsyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

-

作用:执行异步算法。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

inputInfo(可为NULL):算法运算入参;

-

int AieClientSyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo)

-

作用:执行同步算法。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

inputInfo(可为NULL):算法运算入参;

-

outputInfo(可为NULL):同步算法运算结果出参;

-

int AieClientRelease(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

-

作用:卸载算法插件。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):卸载算法插件的相关信息;

-

inputInfo(可为NULL):调用卸载接口时的输入信息;

-

int AieClientDestroy(ClientInfo &clientInfo)

-

作用:断开与服务端的链接,释放相关缓存。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):所要销毁的引擎客户端信息;

-

int AieClientSetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)

-

作用:设置配置项,可将一些算法的拓展信息通过此接口传入插件。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

optionType (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;

-

inputInfo(可为NULL):插件可根据需要通过此入参设置算法参数信息;

-

int AieClientGetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo, DataInfo &outputInfo)

-

作用:给定特定的optionType和inputInfo,获取其对应的配置项信息。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

optionType(NOT NULL):所获取配置项信息的对应算法状态位;

-

inputInfo(可为NULL):所获取配置项信息的对应算法参数信息;

-

outputInfo(可为NULL):所要获取的配置项信息返回结果;

-
-其中,ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构如下[表2](#table22154317482)所示。 + **表1** Client端提供的接口 -**表 2** ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构 +| 接口名 | 接口说明 | 参数要求 | +| -------- | -------- | -------- | +| int **AieClientInit**(const ConfigInfo &configInfo,
 ClientInfo &clientInfo, const AlgorithmInfo
 &algorithmInfo, IServiceDeadCb \*cb) | **作用**:链接并初始化引擎服务,激活跨进程调用。
**返回值**:0为成功,其他返回值失败。 | **configInfo**(NOT NULL):引擎相关初始化配置数据;
**clientInfo**(NOT NULL):引擎客户端信息;
**algorithmInfo**(NOT NULL):调用算法信息;
**cb**(可为NULL):死亡回调 对象; | +| int **AieClientPrepare**(const ClientInfo &clientInfo
, const AlgorithmInfo &algorithmInfo, const DataInfo
 &inputInfo, DataInfo &outputInfo, IClientCb \*cb) | **作用**:加载算法插件。
**返回值**: 0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):引擎客户端信息;
**algorithmInfo**(NOT NULL):调用算法信息;
**inputInfo**(可为NULL):加载算法插件时输入所需信息;
**outputInfo**(可为NULL):加载算法插件之后如需返回信息则通过此出参返回;
**cb**:异步算法通过此回调返回运算结果,因此**异步算法此结构体不能为空**;若为同步算法,传入空值即可; | +| int **AieClientAsyncProcess**(const ClientInfo &clientInfo,
 const AlgorithmInfo &algorithmInfo, const DataInfo
 &inputInfo) | **作用**:执行异步算法。
**返回值**:0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):引擎客户端信息;
**algorithmInfo**(NOT NULL):调用算法信息;
**inputInfo**(可为NULL):算法运算入参; | +| int **AieClientSyncProcess**(const ClientInfo &clientInfo,
 const AlgorithmInfo &algorithmInfo, const
 DataInfo &inputInfo, DataInfo &outputInfo) | **作用**:执行同步算法。
**返回值**:0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):引擎客户端信息;
**algorithmInfo**(NOT NULL):调用算法信息;
**inputInfo**(可为NULL):算法运算入参;
**outputInfo**(可为NULL):同步算法运算结果出参; | +| int **AieClientRelease**(const ClientInfo &clientInfo,
 const AlgorithmInfo &algorithmInfo, const
 DataInfo &inputInfo) | **作用**:卸载算法插件。
**返回值**:0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):引擎客户端信息;
**algorithmInfo**(NOT NULL):卸载算法插件的相关信息;
**inputInfo**(可为NULL):调用卸载接口时的输入信息; | +| int **AieClientDestroy**(ClientInfo &clientInfo) | **作用**:断开与服务端的链接,释放相关缓存。
**返回值**:0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):所要销毁的引擎客户端信息; | +| int **AieClientSetOption**(const ClientInfo &clientInfo,
 int optionType, const DataInfo &inputInfo) | **作用**:设置配置项,可将一些算法的拓展信息通过此接口传入插件。
**返回值**:0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):引擎客户端信息;
**optionType** (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;
**inputInfo**(可为NULL):插件可根据需要通过此入参设置算法参数信息; | +| int **AieClientGetOption**(const ClientInfo &clientInfo,
 int optionType, const DataInfo &inputInfo,
 DataInfo &outputInfo) | **作用**:给定特定的optionType和inputInfo,获取其对应的配置项信息。
**返回值**:0为成功,其他返回值失败。 | **clientInfo**(NOT NULL):引擎客户端信息;
**optionType**(NOT NULL):所获取配置项信息的对应算法状态位;
**inputInfo**(可为NULL):所获取配置项信息的对应算法参数信息;
**outputInfo**(可为NULL):所要获取的配置项信息返回结果; | - - - - - - - - - - - - - - - - - - - - - - - -

结构体名称

-

说明

-

属性

-

ConfigInfo

-

算法配置项信息。

-

const char *description:配置项信息主体;

-

ClientInfo

-

客户端信息。

-

long long clientVersion:客户端设备版本号(当前还未启用);

-

int clientId:客户端ID;

-

int sessionId:会话ID;

-

uid_t serverUid:server端UID;

-

uid_t clientUid:client端UID;

-

int extendLen:拓展信息(extendMsg)长度;

-

unsigned char *extendMsg:拓展信息主体;

-

AlgorithmInfo

-

算法信息。

-

long long clientVersion:客户端设备版本号(当前还未启用);

-

bool isAsync:是否为异步执行;

-

int algorithmType:引擎框架根据插件加载顺序分配的算法类型ID;

-

long long algorithmVersion:算法版本号;

-

bool isCloud:是否上云(当前还未启用);

-

int operateId:执行ID(当前还未启用);

-

int requestId:请求ID,标识每次request,以对应执行结果;

-

int extendLen:拓展信息(extendMsg)长度;

-

unsigned char *extendMsg:拓展信息主体;

-

DataInfo

-

算法数据入参(inputInfo)、接口调用结果出参(outputInfo)。

-

unsigned char *data:数据主体;

-

int length:数据(data)长度;

-
-具体开发过程可参考唤醒词识别SDK开发示例。 +其中,ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构如下下表所示。 + + **表2** ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构 + +| 结构体名称 | 说明 | 属性 | +| -------- | -------- | -------- | +| ConfigInfo | 算法配置项信息。 | **const char \*description**:配置项信息主体; | +| ClientInfo | 客户端信息。 | **long long clientVersion**:客户端设备版本号(当前还未启用);
**int clientId**:客户端ID;
**int sessionId:**会话ID;
**uid_t serverUid**:server端UID;
**uid_t clientUid:**client端UID;
**int extendLen**:拓展信息(extendMsg)长度;
**unsigned char \*extendMsg**:拓展信息主体; | +| AlgorithmInfo | 算法信息。 | **long long clientVersion**:客户端设备版本号(当前还未启用);
**bool isAsync**:是否为异步执行;
**int algorithmType:**引擎框架根据插件加载顺序分配的算法类型ID;
**long long algorithmVersion**:算法版本号;
**bool isCloud**:是否上云(当前还未启用);
**int operateId**:执行ID(当前还未启用);
**int requestId**:请求ID,标识每次request,以对应执行结果;
**int extendLen**:拓展信息(extendMsg)长度;
**unsigned char \*extendMsg**:拓展信息主体; | +| DataInfo | 算法数据入参(inputInfo)、
接口调用结果出参(outputInfo)。 | **unsigned char \*data:**数据主体;
**int length**:数据(data)长度; | + + +具体开发过程可参考[唤醒词识别SDK开发示例](../subsystems/subsys-aiframework-demo-sdk.md)。 diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md index 2b749285030c67c8b2528b4ca0496841d7b645b8..2d2d91edecc9b54ce3dc2cad981fb5cb27f12953 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md @@ -1,11 +1,11 @@ -# 开发指导 +# 开发指导 -为实现AI 引擎框架的接入,开发者需开发《AI引擎框架开发指南》[图1](subsys-aiframework-guide.md#fig143186187187)中的SDK模块和Plugin模块,通过调用sdk提供的接口,基于AI引擎框架实现调用plugin中算法的能力,从而实现AI能力的生命周期管理和按需部署功能。 -- **[SDK开发过程](subsys-aiframework-devguide-sdk.md)** +为实现AI 引擎框架的接入,开发者需开发上述图1中的SDK模块和Plugin模块,通过调用SDK提供的接口,基于AI引擎框架实现调用plugin中算法的能力,从而实现AI能力的生命周期管理和按需部署功能。 -- **[插件的开发过程](subsys-aiframework-devguide-plugin.md)** -- **[配置文件的开发过程](subsys-aiframework-devguide-conf.md)** +- **[SDK开发过程](subsys-aiframework-devguide-sdk.md)** +- **[插件的开发过程](subsys-aiframework-devguide-plugin.md)** +- **[配置文件的开发过程](subsys-aiframework-devguide-conf.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md b/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md index 50cd9a3f9c3e5bf420863c30218379a631400f26..6c9f583234ca9abe82f26db5949cc39f3fcad76f 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md @@ -1,5 +1,6 @@ -# 搭建环境 +# 搭建环境 -1. 准备开发板:Hi3516DV300,Hi3518EV300 -2. [下载源码](../get-code/sourcecode-acquire.md) +1. 准备开发板:Hi3516DV300或Hi3518EV300 + +2. [下载源码](../get-code/sourcecode-acquire.md) diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md b/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md index c725c6de1d82b1efa4670cedb9654b8f044d25f3..653117b888410fffbb96fceedf29abc84e313c26 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md @@ -1,9 +1,8 @@ -# AI引擎框架开发指南 +# 概述 -AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。AI业务子系统提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,完成对AI算法能力的生命周期管理和按需部署。插件管理主要实现插件的生命周期管理及插件的按需部署,快速集成AI能力插件;模块管理主要实现任务的调度及管理客户端的实例;通信管理主要实现客户端和服务端之间的跨进程通信及引擎与插件之间的数据传输。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。AI引擎框架如下[图1](#fig143186187187)所示。 -**图 1** AI引擎框架 +AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。AI业务子系统提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,完成对AI算法能力的生命周期管理和按需部署。插件管理主要实现插件的生命周期管理及插件的按需部署,快速集成AI能力插件;模块管理主要实现任务的调度及管理客户端的实例;通信管理主要实现客户端和服务端之间的跨进程通信及引擎与插件之间的数据传输。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。AI引擎框架如下图所示。 -![](figure/zh-cn_image_0000001077727032.png) - + **图1** AI引擎框架 + ![zh-cn_image_0000001200128073](figures/zh-cn_image_0000001200128073.png) diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md index f93fcf62bb5cb58aa6873e0191ac86627acd5532..659600d23bd24647f465f3e50c528c3393057e0d 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md @@ -1,40 +1,37 @@ -# 代码管理规范 +# 代码管理规范 -- [建议:插件与北向SDK在AI引擎指定的路径下进行代码开发](#section17176374131) -- [规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录](#section2551029111312) -- [规则:插件编译输出路径必须是在/usr/lib](#section97021558121310) AI引擎框架包含client、server和common三个主要模块,其中client提供server端连接管理功能,北向SDK在算法对外接口中需封装调用client提供的公共接口;server提供插件加载以及任务管理等功能,各Plugin实现由server提供的插件接口,完成插件接入;common提供与平台相关的操作方法、引擎协议以及相关工具类,供其他各模块调用。 -AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示: -**图 1** ****AI引擎代码依赖关系 +AI引擎框架各模块之间的代码依赖关系如下图所示: -![](figure/插件依赖-(2).jpg) + **图1** AI引擎代码依赖关系 -## 建议:插件与北向SDK在AI引擎指定的路径下进行代码开发 + ![zh-cn_image_0000001151931738](figures/zh-cn_image_0000001151931738.jpg) -在AI引擎框架的整体规划中,北向SDK属于client端的一部分,插件由server端调用,属于server端的一部分,因此AI引擎框架为接入的插件与北向SDK规划的路径: -- SDK代码路径://foundation/ai/engine/services/client/algorithm\_sdk +## 建议:插件与北向SDK在AI引擎指定的路径下进行代码开发 - e.g. //foundation/ai/engine/services/client/algorithm\_sdk/cv +在AI引擎框架的整体规划中,北向SDK属于client端的一部分,插件由server端调用,属于server端的一部分,因此AI引擎框架为接入的插件与北向SDK规划的路径: - e.g. //foundation/ai/engine/services/client/algorithm\_sdk/nlu +- SDK代码路径://foundation/ai/engine/services/client/algorithm_sdk + e.g. //foundation/ai/engine/services/client/algorithm_sdk/cv -- 插件代码路径://foundation/ai/engine/services/server/plugin + e.g. //foundation/ai/engine/services/client/algorithm_sdk/nlu - e.g. //foundation/ai/engine/services/server/plugin/cv +- 插件代码路径://foundation/ai/engine/services/server/plugin + e.g. //foundation/ai/engine/services/server/plugin/cv - e.g. //foundation/ai/engine/services/server/plugin/nlu + e.g. //foundation/ai/engine/services/server/plugin/nlu -## 规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录 +## 规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录 北向SDK对外接口是AI业务子系统提供能力的对外暴露方式,按照OpenHarmony的接口管理要求,需统一存放在各子系统的interfaces/kits目录中。当前AI业务子系统插件对外接口路径为//foundation/ai/engine/interfaces/kits,不同插件可在该路径下添加目录,比如增加cv插件,则在路径//foundation/ai/engine/interfaces/kits/cv下面存放接口文件。 -## 规则:插件编译输出路径必须是在/usr/lib -server端加载插件是采用dlopen方式,只支持在/usr/lib路径进行,因此插件在编译so时,需要在编译配置文件中指定输出路径为/usr/lib。 +## 规则:插件编译输出路径必须是在/usr/lib +server端加载插件是采用dlopen方式,只支持在/usr/lib路径进行,因此插件在编译so时,需要在编译配置文件中指定输出路径为/usr/lib。 diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md index 01d797b1a38c57fe3e29d2f7f1b7124183d63688..1e917c941ee29e008de14deb7d08affd2182b818 100755 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md @@ -1,29 +1,25 @@ -# 接口开发规范 +# 接口开发规范 -- [规则:SDK需按算法调用顺序,封装client对外提供接口;对于异步插件对应的SDK,需要实现client提供的回调接口IClientCb](#section15872017171616) -- [规则:SDK接口实现中,需要保存与client交互的相关通用数据](#section011283741612) -- [建议:SDK实现client定义的IServiceDeadCb接口](#section1199125331613) -- [规则:SDK与plugin需要使用编解码模块,将特定算法数据转换成AI引擎的通用数据类型](#section93139389171) -- [规则:在SDK中,对以编解码返回的出参数据类型,需要进行内存释放,否则会出现内存泄漏](#section1698441814183) -- [规则:plugin需要实现server定义的IPlugin接口,并使用宏PLUGIN\_INTERFACE\_IMPL对外提供插件函数指针](#section20850717196) -- [规则:plugin需要使用AI引擎提供的统一数据通道](#section1493821732019) -## 规则:SDK需按算法调用顺序,封装client对外提供接口;对于异步插件对应的SDK,需要实现client提供的回调接口IClientCb +## 规则:SDK需按算法调用顺序,封装client对外提供接口;对于异步插件对应的SDK,需要实现client提供的回调接口IClientCb -AI引擎的client端对外提供的接口包括AieClientInit、AieClientPrepare、AieClientSyncProcess、AieClientAsyncProcess、AieClientRelease、AieClientDestroy、AieClientSetOption、AieClientGetOption,sdk需要根据插件的北向接口按照顺序至少封装AieClientInit、AieClientPrepare、AieClientSyncProcess/AieClientAsyncProcess、AieClientRelease、AieClientDestroy五个接口,否则会出现调用问题或者内存泄漏。比如封装过程遗漏了AieClientprepare接口,则server端无法完成插件加载,故后面的接口都无法调用成功。 +AI引擎的client端对外提供的接口包括AieClientInit、AieClientPrepare、AieClientSyncProcess、AieClientAsyncProcess、AieClientRelease、AieClientDestroy、AieClientSetOption、AieClientGetOption,SDK需要根据插件的北向接口按照顺序至少封装AieClientInit、AieClientPrepare、AieClientSyncProcess/AieClientAsyncProcess、AieClientRelease、AieClientDestroy五个接口,否则会出现调用问题或者内存泄漏。比如封装过程遗漏了AieClientPrepare接口,则server端无法完成插件加载,故后面的接口都无法调用成功。 -对于异步插件,sdk需要实现IClientCb接口,用于接收来自client端的算法推理结果,并将该结果返回给三方调用者。 +对于异步插件,SDK需要实现IClientCb接口,用于接收来自client端的算法推理结果,并将该结果返回给三方调用者。 -## 规则:SDK接口实现中,需要保存与client交互的相关通用数据 + +## 规则:SDK接口实现中,需要保存与client交互的相关通用数据 AI引擎将的client端采用单例实现,对接多个SDK,因此各SDK需要保存与client交互的通用数据,用于连接server端进行任务推理、结果返回等;需保存数据包含clientInfo、algorithmInfo、configInfo三种数据类型,定义在SDK的成员变量里即可。 -## 建议:SDK实现client定义的IServiceDeadCb接口 -Server端是系统常驻进程,以系统能力的形式为多个client提供服务;client定义的IServiceDeadCb接口,是在server端异常死亡后,会被触发调用。这种异常场景,sdk可在死亡通知接口中,实现相关操作,比如停止调用或者再次拉起server端等。 +## 建议:SDK实现client定义的IServiceDeadCb接口 + +Server端是系统常驻进程,以系统能力的形式为多个client提供服务;client定义的IServiceDeadCb接口,是在server端异常死亡后,会被触发调用。这种异常场景,SDK可在死亡通知接口中,实现相关操作,比如停止调用或者再次拉起server端等。 IServiceDeadCb接口实现示例: + ``` class ServiceDeadCb : public IServiceDeadCb { public: @@ -36,14 +32,16 @@ printf("[ServiceDeadCb]OnServiceDead Callback happens"); }; ``` -如上示例,SDK可在OnServiceDead\(\)方法中实现自己的操作,比如停止所有的接口调用等等。 +如上示例,SDK可在OnServiceDead()方法中实现自己的操作,比如停止所有的接口调用等等。 + -## 规则:SDK与plugin需要使用编解码模块,将特定算法数据转换成AI引擎的通用数据类型 +## 规则:SDK与plugin需要使用编解码模块,将特定算法数据转换成AI引擎的通用数据类型 插件的推理数据,会由三方调用者通过client、server传递到插件中;不同的算法所需要的数据类型是不一致的,比如cv的需要图片数据、asr的需要语音数据;为了适配数据类型的差异,AI引擎对外提供了对基本数据类型的编解码能力,将不同数据类型转换为AI引擎可以使用的通用数据类型。 编码后的数据类型定义: + ``` struct DataInfo { unsigned char *data; @@ -60,12 +58,13 @@ int length; 2.添加build.gn中的依赖项: -include\_dirs添加"//foundation/ai/engine/services/common"。 +include_dirs添加"//foundation/ai/engine/services/common"。 deps添加"//foundation/ai/engine/services/common/utils/encdec:encdec" 。 3.编解码示例: + ``` // 编码调用函数示例:arg1,arg2,arg3等为需编码的变量,dataInfo为编码后的结果 retCode = ProcessEncode(dataInfo, arg1, arg2, arg3) //可以接收任意多个参数 @@ -75,19 +74,26 @@ retCode = ProcessDecode(dataInfo, arg1, arg2, arg3) //可以接收任意多个 注意: -- 编码和解码调用时的参数顺序需要保证一致。 -- 编码后dataInfo的内存需要调用者手动进行释放。 -- server端和client端的内存是分开管理和释放的。 -- 如果包含共享内存的指针,不需要额外处理。 -- 如果其他类型的指针,则需要解引用后使用ProcessEncode/ ProcessDecode。 -- 该编解码模块未适配class数据类型,不建议使用。 +- 编码和解码调用时的参数顺序需要保证一致。 + +- 编码后dataInfo的内存需要调用者手动进行释放。 + +- server端和client端的内存是分开管理和释放的。 + +- 如果包含共享内存的指针,不需要额外处理。 -## 规则:在SDK中,对以编解码返回的出参数据类型,需要进行内存释放,否则会出现内存泄漏 +- 如果其他类型的指针,则需要解引用后使用ProcessEncode/ ProcessDecode。 -编码得到的通用数据,本质上是将不同类型数据封装在同一块内存中,然后将这块内存的首地址与长度封装到结构体中。通过编码返回到sdk中的出参数据,在插件中申请了内存,但插件无法释放,否则sdk将无法拿到数据;因此sdk在拿到数据之后,需要对内存进行释放。 +- 该编解码模块未适配class数据类型,不建议使用。 + + +## 规则:在SDK中,对以编解码返回的出参数据类型,需要进行内存释放,否则会出现内存泄漏 + +编码得到的通用数据,本质上是将不同类型数据封装在同一块内存中,然后将这块内存的首地址与长度封装到结构体中。通过编码返回到SDK中的出参数据,在插件中申请了内存,但插件无法释放,否则SDK将无法拿到数据;因此SDK在拿到数据之后,需要对内存进行释放。 内存释放示例: + ``` DataInfo outputInfo = { .data = nullptr, @@ -101,16 +107,19 @@ outputInfo.length = 0; } ``` -## 规则:plugin需要实现server定义的IPlugin接口,并使用宏PLUGIN\_INTERFACE\_IMPL对外提供插件函数指针 -Server端管理的插件内部接口实现逻辑各不相同,为了统一插件的加载流程,AI引擎定义了插件接口IPlugin;在运行态,插件是以动态链接库的形式被AI引擎框架通过dlopen方式加载,各插件需要使用PLUGIN\_INTERFACE\_IMPL语句对外暴露函数指针,否则插件将无法被正常加载使用。 +## 规则:plugin需要实现server定义的IPlugin接口,并使用宏PLUGIN_INTERFACE_IMPL对外提供插件函数指针 -## 规则:plugin需要使用AI引擎提供的统一数据通道 +Server端管理的插件内部接口实现逻辑各不相同,为了统一插件的加载流程,AI引擎定义了插件接口IPlugin;在运行态,插件是以动态链接库的形式被AI引擎框架通过dlopen方式加载,各插件需要使用PLUGIN_INTERFACE_IMPL语句对外暴露函数指针,否则插件将无法被正常加载使用。 -AI Engine在server与插件之间,提供了一个统一的数据通道,用来处理来自sdk的推理请求和来自插件的结果返回;plugin在推理接口中,需按数据通道完成请求数据的获取以及推理结果的封装。 + +## 规则:plugin需要使用AI引擎提供的统一数据通道 + +AI Engine在server与插件之间,提供了一个统一的数据通道,用来处理来自SDK的推理请求和来自插件的结果返回;plugin在推理接口中,需按数据通道完成请求数据的获取以及推理结果的封装。 数据通道使用示例: + ``` int SyncProcess(IRequest *request, IResponse *&response) { @@ -134,4 +143,3 @@ return RETCODE_SUCCESS; ``` 示例中request和response是数据通道的内容主体,server端会将数据封装在request中,传递到插件,插件进行算法处理之后,则需要将结果封装成response进行返回。 - diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md index d424778712d4e7564116c1fd6b0cc9f5a9401d71..f81b525b0b4a464046ab809ad246015e4169e53f 100755 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md @@ -1,19 +1,17 @@ -# 命名规范 +# 命名规范 -- [SDK命名规则:领域\_关键词<\_其他信息1\_其他信息2\_…\>\_sdk.so](#section62071110121516) -- [插件命名规则:领域\_关键词<\_其他信息1\_其他信息2\_…\>.so](#section1665562841519) -## SDK命名规则:领域\_关键词<\_其他信息1\_其他信息2\_…\>\_sdk.so +## SDK命名规则:领域_关键词<_其他信息1_其他信息2_…>_sdk.so -关于领域,建议使用当前主流简称,比如图片视频相关的使用"cv",语音识别相关的使用“asr”,翻译相关的使用“translation”等,存在其他领域的可增加定义;关键词则需要恰当准确的描述所对应插件的算法能力,比如唤醒词识别,则使用keyword\_spotting;对于其他信息,比如插件支持的芯片类型、国内海外等信息,可在关键词与“SDK”之间依次添加,每个信息之间以下划线连接;北向sdk命名,必须以“SDK”结尾。 +关于领域,建议使用当前主流简称,比如图片视频相关的使用"cv",语音识别相关的使用“asr”,翻译相关的使用“translation”等,存在其他领域的可增加定义;关键词则需要恰当准确的描述所对应插件的算法能力,比如唤醒词识别,则使用keyword_spotting;对于其他信息,比如插件支持的芯片类型、国内海外等信息,可在关键词与“SDK”之间依次添加,每个信息之间以下划线连接;北向SDK命名,必须以“SDK”结尾。 -例如:唤醒词识别插件对应 的SDK,只支持麒麟9000芯片,适用于中国国内地区适用,则对应的SDK命名为:asr\_keyword\_spotting\_kirin9000\_china\_sdk.so +例如:唤醒词识别插件对应 的SDK,只支持麒麟9000芯片,适用于中国国内地区适用,则对应的SDK命名为:asr_keyword_spotting_kirin9000_china_sdk.so -## 插件命名规则:领域\_关键词<\_其他信息1\_其他信息2\_…\>.so -插件命名的领域、关键词、其他信息等名词解释与要求,均与sdk命名要求保持一致。 +## 插件命名规则:领域_关键词<_其他信息1_其他信息2_…>.so -插件与sdk存在一一对应的关系,故两者命名在领域、关键词、其他信息上要保持一致,两者唯一的不同之处在于sdk命名多了个“\_sdk”结尾;比如插件命名为“asr\_keyword\_spotting.so”,则对应北向SDK命名为“asr\_keyword\_spotting\_sdk.so”。 +插件命名的领域、关键词、其他信息等名词解释与要求,均与SDK命名要求保持一致。 -例如:唤醒词识别插件对应的SDK,只支持麒麟9000芯片,适用于中国国内地区适用,则对应的插件命名为:asr\_keyword\_spotting\_kirin9000\_china.so +插件与SDK存在一一对应的关系,故两者命名在领域、关键词、其他信息上要保持一致,两者唯一的不同之处在于SDK命名多了个“_sdk”结尾;比如插件命名为“asr_keyword_spotting.so”,则对应北向SDK命名为“asr_keyword_spotting_sdk.so”。 +例如:唤醒词识别插件对应的SDK,只支持麒麟9000芯片,适用于中国国内地区适用,则对应的插件命名为:asr_keyword_spotting_kirin9000_china.so diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md index b608040be81b0368df3bf6d167b2c7961ac35177..c591eef7a6927bd60249dbe7f2cd06ca0133a6d3 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md @@ -1,15 +1,17 @@ -# 技术规范 +# 技术规范 + **用词约定:** + **规则**:必须准守的约定 -**建议**:需要加以考虑的约定 -- **[代码管理规范](subsys-aiframework-tech-codemanage.md)** +**建议**:需要加以考虑的约定 -- **[命名规范](subsys-aiframework-tech-name.md)** -- **[接口开发规范](subsys-aiframework-tech-interface.md)** +- **[代码管理规范](subsys-aiframework-tech-codemanage.md)** +- **[命名规范](subsys-aiframework-tech-name.md)** +- **[接口开发规范](subsys-aiframework-tech-interface.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework.md b/zh-cn/device-dev/subsystems/subsys-aiframework.md index 77fa018ec4592e10ced77cbec30a0a7a9f003481..aa8f2af29402dedaa8baf40495786d2bd52edd33 100644 --- a/zh-cn/device-dev/subsystems/subsys-aiframework.md +++ b/zh-cn/device-dev/subsystems/subsys-aiframework.md @@ -1,13 +1,13 @@ -# AI框架 +# AI框架 -- **[AI引擎框架开发指南](subsys-aiframework-guide.md)** -- **[搭建环境](subsys-aiframework-envbuild.md)** -- **[技术规范](subsys-aiframework-tech.md)** +- **[概述](subsys-aiframework-guide.md)** -- **[开发指导](subsys-aiframework-devguide.md)** +- **[搭建环境](subsys-aiframework-envbuild.md)** -- **[开发示例](subsys-aiframework-demo.md)** +- **[技术规范](subsys-aiframework-tech.md)** +- **[开发指导](subsys-aiframework-devguide.md)** +- **[开发示例](subsys-aiframework-demo.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-demo.md b/zh-cn/device-dev/subsystems/subsys-application-framework-demo.md index 380e63f23978255b66f70d93f7be1199e704d14a..96b77366ad69113a49fda26e82646ccf6bc46266 100755 --- a/zh-cn/device-dev/subsystems/subsys-application-framework-demo.md +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-demo.md @@ -1,4 +1,4 @@ -# 开发实例 +# 开发实例 -开发实例可参考[开源项目中的示例](https://gitee.com/openharmony/aafwk_aafwk_lite/tree/master/frameworks/ability_lite/example) +开发实例可参考[开源项目中的示例](https://gitee.com/openharmony/aafwk_aafwk_lite/tree/master/frameworks/ability_lite/example) diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-envbuild.md b/zh-cn/device-dev/subsystems/subsys-application-framework-envbuild.md index 0d015bf975615463a85b066fc82815a84f0f95bd..740c3824704f6118034398898f4e2c2bf18b6b64 100644 --- a/zh-cn/device-dev/subsystems/subsys-application-framework-envbuild.md +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-envbuild.md @@ -1,7 +1,10 @@ -# 搭建环境 +# 搭建环境 -- 开发板:Hi3516DV300 -- [下载源码](../get-code/sourcecode-acquire.md) -- [编译用户程序框架](../../readme/包管理子系统.md) +- 开发板:Hi3516DV300 + + +- [下载源码](../get-code/sourcecode-acquire.md)[下载源码](../get-code/sourcecode-acquire.md) + +- [编译用户程序框架](../../readme/包管理子系统.md) diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md b/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md index 630bf13450e9532d0ef94901bf39539a09a983e6..9b10a5baa6caca924b177d4b92632bd8a55a9f41 100644 --- a/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md @@ -1,709 +1,422 @@ -# 开发指导 - -- [场景介绍](#section93012287133) -- [接口说明](#section11821047161319) -- [开发步骤](#section10514141679) - - [创建Service类型的Ability](#section19921154214315) - - [包管理接口使用指导](#section1724016743217) - - [Hap包打包](#section171771212328) - - -## 场景介绍 - -- 带界面的Ability的应用,比如:新闻类的应用、视频类的应用、导航类的应用、支付类的应用等等,目前我们看到的大部分应用都是带有界面的用于人机交互的应用。 - -- 不带界面的Ability应用,比如:音乐播放器能在后台播放音乐、后台提供计算服务、导航服务的各类应用等。 - -- 不管是带界面的Ability应用还是不带界面的Ability应用,都要打包成Hap包,最终发布到应用市场,用户通过应用市场下载安装相应的应用。 - -## 接口说明 - -**表 1** Ability子系统的对外接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名称

-

接口描述

-

Want *WantParseUri(const char *uri)

-

反序列化接口,由字符串生成Want对象。

-

const char *WantToUri(Want want)

-

序列化,把Want对象生成字符串。

-

void SetWantElement(Want *want, ElementName element);

-

设置ElementName对象。

-

void SetWantData(Want *want, const void *data, uint16_t dataLength)

-

设置数据。

-

bool SetWantSvcIdentity(Want *want, SvcIdentity sid)

-

设置SvcIdentity。

-

void ClearWant(Want *want)

-

清除Want的内部内存数据。

-

void SetMainRoute(const std::string &entry)

-

设置AbilitySlice主路由。

-

void SetUIContent(RootView *rootView)

-

设置布局资源。

-

void OnStart(const Want& intent)

-

Ability生命周期状态回调,Ability启动时被回调。

-

void OnStop()

-

Ability生命周期状态回调,Ability销毁时被回调。

-

void OnActive(const Want& intent)

-

Ability生命周期状态回调,Ability显示时被回调。

-

void OnInactive()

-

Ability生命周期状态回调,Ability隐藏时被回调。

-

void OnBackground()

-

Ability生命周期状态回调,Ability退到后台时被回调。

-

const SvcIdentity *OnConnect(const Want &want)

-

Service类型Ability第一次连接时被回调。

-

void OnDisconnect(const Want &want);

-

Service类型Ability断开连接被回调。

-

void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply);

-

Service类型Ability接收消息处理。

-

void Dump(const std::string &extra)

-

dump Ability信息。

-

void Present(AbilitySlice *abilitySlice, const Want &want)

-

发起AbilitySlice跳转。

-

void Terminate()

-

退出当前AbilitySlice。

-

void SetUIContent(RootView *rootView)

-

设置当前AbilitySlice所在Ability的布局资源。

-

void OnStart(const Want& want)

-

AbilitySlice生命周期状态回调,AbilitySlice启动时被回调。

-

void OnStop()

-

AbilitySlice生命周期状态回调,AbilitySlice销毁时被回调。

-

void OnActive(const Want& want)

-

AbilitySlice生命周期状态回调,AbilitySlice显示时被回调。

-

void OnInactive()

-

AbilitySlice生命周期状态回调,AbilitySlice隐藏时被回调。

-

void OnBackground()

-

AbilitySlice生命周期状态回调,AbilitySlice退到后台时被回调。

-

int StartAbility(const Want &want)

-

启动Ability。

-

int StopAbility(const Want &want)

-

停止Service类型的Ability。

-

int TerminateAbility()

-

销毁当前的Ability。

-

int ConnectAbility(const Want &want, const IAbilityConnection &conn, void *data);

-

绑定Service类型的Ability。

-

int DisconnectAbility(const IAbilityConnection &conn)

-

解绑Service类型的Ability。

-

const char *GetBundleName()

-

获取当前ability的对应应用的包名。

-

const char *GetSrcPath()

-

获取当前ability的对应应用的安装路径。

-

const char *GetDataPath()

-

获取当前ability的对应应用的数据路径。

-

int StartAbility(const Want *want)

-

启动Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

int ConnectAbility(const Want *want, const IAbilityConnection *conn, void *data);

-

绑定Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

int DisconnectAbility(const IAbilityConnection *conn);

-

解绑Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

int StopAbility(const Want *want)

-

停止Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

void (*OnAbilityConnectDone)(ElementName *elementName, SvcIdentity *serviceSid, int resultCode, void *data)

-

绑定Service Ability的回调。

-

void (*OnAbilityDisconnectDone)(ElementName *elementName, int resultCode, void *data)

-

解绑Service Ability的回调。

-

void PostTask(const Task& task)

-

投递任务到异步线程进行处理。

-

void PostQuit()

-

退出当前线程的消息循环。

-

static AbilityEventHandler* GetCurrentHandler()

-

获取当前线程的事件处理器。

-

void Run()

-

执行当前线程的消息循环。

-

#define REGISTER_AA(className)

-

注册开发者的Ability到框架中。

-

#define REGISTER_AS(className)

-

注册开发者的AbilitySlice到框架中。

-
- -## 开发步骤 - -### 创建Service类型的Ability - -1. 在my\_service\_ability.h中创建Ability的子类MyServiceAbility。 - - ``` - class MyServiceAbility: public Ability { - protected: - void OnStart(const Want& want); - const SvcIdentity *OnConnect(const Want &want) override; - void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) override; - }; - ``` - -2. 调用REGISTER\_AA宏将ServiceAbility注册到应用框架中,以便应用框架实例化开发者的MyServiceAbility。 - - ``` - #include "my_service_ability.h" - - REGISTER_AA(ServiceAbility) - - void MyServiceAbility::OnStart(const Want& want) - { - printf("ServiceAbility::OnStart\n"); - Ability::OnStart(want); - } - - const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) - { - printf("ServiceAbility::OnConnect\n"); - return Ability::OnConnect(want); - } - - void MyServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) - { - printf("ServiceAbility::MsgHandle, funcId is %u\n", funcId); - int result = 0; - if (funcId == 0) { - result = IpcIoPopInt32(request) + IpcIoPopInt32(request); - } - // push data - IpcIoPushInt32(reply, result); - } - ``` - -3. 实现Service相关的生命周期方法。Service也是一种Ability,Ability为服务提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。用户在重写的方法里,需要调用父类对应的方法。 - - OnStart\(\) - - 该方法在创建Service的时候调用,用于做一些Service初始化且耗时较短的工作,在Service的整个生命周期只会调用一次。 - - ``` - void MyServiceAbility::OnStart(const Want& want) - { - printf("ServiceAbility::OnStart\n"); - Ability::OnStart(want); - } - ``` - - - OnConnect​\(\) - - 在组件和服务连接时调用,该方法返回SvcIdentity,组件可以通过它,与服务交互。 +# 开发指导 + + +## 场景介绍 + +- 带界面的Ability的应用,比如:新闻类的应用、视频类的应用、导航类的应用、支付类的应用等等,目前我们看到的大部分应用都是带有界面的用于人机交互的应用。 + +- 不带界面的Ability应用,比如:音乐播放器能在后台播放音乐、后台提供计算服务、导航服务的各类应用等。 + +- 不管是带界面的Ability应用还是不带界面的Ability应用,都要打包成Hap包,最终发布到应用市场,用户通过应用市场下载安装相应的应用。 + + +## 接口说明 + + **表1** Ability子系统的对外接口 + +| 接口名称 | 接口描述 | +| -------- | -------- | +| Want \*WantParseUri(const char \*uri) | 反序列化接口,由字符串生成Want对象。 | +| const char \*WantToUri(Want want) | 序列化,把Want对象生成字符串。 | +| void SetWantElement(Want \*want, ElementName element); | 设置ElementName对象。 | +| void SetWantData(Want \*want, const void \*data, uint16_t dataLength) | 设置数据。 | +| bool SetWantSvcIdentity(Want \*want, SvcIdentity sid) | 设置SvcIdentity。 | +| void ClearWant(Want \*want) | 清除Want的内部内存数据。 | +| void SetMainRoute(const std::string &entry) | 设置AbilitySlice主路由。 | +| void SetUIContent(RootView \*rootView) | 设置布局资源。 | +| void OnStart(const Want& intent) | Ability生命周期状态回调,Ability启动时被回调。 | +| void OnStop() | Ability生命周期状态回调,Ability销毁时被回调。 | +| void OnActive(const Want& intent) | Ability生命周期状态回调,Ability显示时被回调。 | +| void OnInactive() | Ability生命周期状态回调,Ability隐藏时被回调。 | +| void OnBackground() | Ability生命周期状态回调,Ability退到后台时被回调。 | +| const SvcIdentity \*OnConnect(const Want &want) | Service类型Ability第一次连接时被回调。 | +| void OnDisconnect(const Want &want); | Service类型Ability断开连接被回调。 | +| void MsgHandle(uint32_t funcId, IpcIo \*request, IpcIo \*reply); | Service类型Ability接收消息处理。 | +| void Dump(const std::string &extra) | dump Ability信息。 | +| void Present(AbilitySlice \*abilitySlice, const Want &want) | 发起AbilitySlice跳转。 | +| void Terminate() | 退出当前AbilitySlice。 | +| void SetUIContent(RootView \*rootView) | 设置当前AbilitySlice所在Ability的布局资源。 | +| void OnStart(const Want& want) | AbilitySlice生命周期状态回调,AbilitySlice启动时被回调。 | +| void OnStop() | AbilitySlice生命周期状态回调,AbilitySlice销毁时被回调。 | +| void OnActive(const Want& want) | AbilitySlice生命周期状态回调,AbilitySlice显示时被回调。 | +| void OnInactive() | AbilitySlice生命周期状态回调,AbilitySlice隐藏时被回调。 | +| void OnBackground() | AbilitySlice生命周期状态回调,AbilitySlice退到后台时被回调。 | +| int StartAbility(const Want &want) | 启动Ability。 | +| int StopAbility(const Want &want) | 停止Service类型的Ability。 | +| int TerminateAbility() | 销毁当前的Ability。 | +| int ConnectAbility(const Want &want, const IAbilityConnection &conn, void \*data); | 绑定Service类型的Ability。 | +| int DisconnectAbility(const IAbilityConnection &conn) | 解绑Service类型的Ability。 | +| const char \*GetBundleName() | 获取当前ability的对应应用的包名。 | +| const char \*GetSrcPath() | 获取当前ability的对应应用的安装路径。 | +| const char \*GetDataPath() | 获取当前ability的对应应用的数据路径。 | +| int StartAbility(const Want \*want) | 启动Ability,该接口可以不需要在基于Ability开发的应用中使用。 | +| int ConnectAbility(const Want \*want, const IAbilityConnection \*conn, void \*data); | 绑定Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。 | +| int DisconnectAbility(const IAbilityConnection \*conn); | 解绑Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。 | +| int StopAbility(const Want \*want) | 停止Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。 | +| void (\*OnAbilityConnectDone)(ElementName \*elementName, SvcIdentity \*serviceSid, int resultCode, void \*data) | 绑定Service Ability的回调。 | +| void (\*OnAbilityDisconnectDone)(ElementName \*elementName, int resultCode, void \*data) | 解绑Service Ability的回调。 | +| void PostTask(const Task& task) | 投递任务到异步线程进行处理。 | +| void PostQuit() | 退出当前线程的消息循环。 | +| static AbilityEventHandler\* GetCurrentHandler() | 获取当前线程的事件处理器。 | +| void Run() | 执行当前线程的消息循环。 | +| \#define REGISTER_AA(className) | 注册开发者的Ability到框架中。 | +| \#define REGISTER_AS(className) | 注册开发者的AbilitySlice到框架中。 | + + +## 开发步骤 + + +### 创建Service类型的Ability + + +1. 在my_service_ability.h中创建Ability的子类MyServiceAbility。 + + ``` + class MyServiceAbility: public Ability { + protected: + void OnStart(const Want& want); + const SvcIdentity *OnConnect(const Want &want) override; + void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) override; + }; + ``` + +2. 调用REGISTER_AA宏将ServiceAbility注册到应用框架中,以便应用框架实例化的MyServiceAbility。 + + ``` + #include "my_service_ability.h" + + REGISTER_AA(ServiceAbility) + + void MyServiceAbility::OnStart(const Want& want) + { + printf("ServiceAbility::OnStart\n"); + Ability::OnStart(want); + } + + const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) + { + printf("ServiceAbility::OnConnect\n"); + return Ability::OnConnect(want); + } + + void MyServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) + { + printf("ServiceAbility::MsgHandle, funcId is %u\n", funcId); + int result = 0; + if (funcId == 0) { + result = IpcIoPopInt32(request) + IpcIoPopInt32(request); + } + // push data + IpcIoPushInt32(reply, result); + } + ``` + +3. 实现Service相关的生命周期方法。Service也是一种Ability,Ability为服务提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。用户在重写的方法里,需要调用父类对应的方法。 + - OnStart() + 该方法在创建Service的时候调用,用于做一些Service初始化且耗时较短的工作,在Service的整个生命周期只会调用一次。 + + + ``` + void MyServiceAbility::OnStart(const Want& want) + { + printf("ServiceAbility::OnStart\n"); + Ability::OnStart(want); + } + ``` + - OnConnect​() + 在组件和服务连接时调用,该方法返回SvcIdentity,组件可以通过它与服务交互。 + + + ``` + const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) + { + printf("ServiceAbility::OnConnect\n"); + return Ability::OnConnect(want); + } + ``` + - OnDisconnect​() + 在组件与绑定的Service断开连接时调用。 + - OnStop() + 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 + +4. 重写消息处理方法。 + MsgHandle是Service用来处理客户端消息的方法。其中funcId是客户端传过来的消息类型,request是客户端传过来的序列化请求参数。如果用户在处理完成之后想要把结果传回去,需要把结果序列化后写入reply中。 + + + ``` + void ServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) + { + printf("ServiceAbility::MsgHandle, funcId is %d\n", funcId); + int result = 0; + if (funcId == PLUS) { + result = IpcIoPopInt32(request) + IpcIoPopInt32(request); + } + // push data + IpcIoPushInt32(reply, result); + } + ``` + +5. 注册Service。 + Service也需要在应用清单文件config.json中进行注册,注册类型type需要设置为service。 + + + ``` + "abilities": [{ + "name": "ServiceAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "service", + "visible": true + } + ] + ``` + +6. 启动Service。 + - Ability为用户提供了StartAbility()方法来启动另外一个Ability,因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。 + 开发者可以通过Want的SetWantElement ()来设置目标服务信息。ElementName结构体的两个主要参数:第一个参数为包名称;第二个参数为目标Ability。 + + ``` + { + Want want = { nullptr }; + ElementName element = { nullptr }; + SetElementBundleName(&element, "com.company.appname"); + SetElementAbilityName(&element, "ServiceAbility"); + SetWantElement(&want, element); + StartAbility(want); + ClearElement(&element); + ClearWant(&want); + } + ``` + + StartAbility() 方法会立即执行,如果Service尚未运行,则系统首先会调用OnStart()。 + - 停止Service。 + Service一旦创建就会一直保持在后台运行,开发者可以通过调用StopAbility()来停止Service。 + +7. 连接Service。 + - 如果Service需要与Page Ability或其他应用组件中的Service进行交互,则应创建用于连接的Service。Service支持其他Ability通过ConnectAbility()与其进行连接,ConnectAbility()需要传入目标Service的Want,以及IAbilityConnection的实例来处理回调。IAbilityConnection提供了两个方法供用户实现,OnAbilityConnectDone()用来处理连接的回调,OnAbilityDisconnectDone()用来处理断开连接的回调。 + + ``` + { + // ability创建IAbilityConnection对象和定义IAbilityConnection的两个方法实现 + IAbilityConnection abilityConnection = new IAbilityConnection(); + abilityConnection->OnAbilityConnectDone = OnAbilityConnectDone; + abilityConnection->OnAbilityDisconnectDone = OnAbilityDisconnectDone; + + void OnAbilityConnectDone(ElementName *elementName, SvcIdentity *serviceSid, + int resultCode, void *data) + { + if (resultCode != 0) { + return; + } + // push data + IpcIo request; + char dataBuffer[IPC_IO_DATA_MAX]; + IpcIoInit(&request, dataBuffer, IPC_IO_DATA_MAX, 0); + IpcIoPushInt32(&request, 10); + IpcIoPushInt32(&request, 6); + + // send and getReply + IpcIo reply; + uintptr_t ptr = 0; + if (Transact(nullptr, *serviceSid, 0, &request, &reply, + LITEIPC_FLAG_DEFAULT, &ptr) != LITEIPC_OK) { + printf("transact error\n"); + return; + } + int result = IpcIoPopInt32(&reply); + printf("execute add method, result is %d\n", result); + if (ptr != 0) { + FreeBuffer(nullptr, reinterpret_cast(ptr)); + } + } + + void OnAbilityDisconnectDone(ElementName *elementName, + int resultCode, void *data) + { + printf("elementName is %s, %s\n", + elementName->bundleName, elementName->abilityName); + } + } + ``` + - 发起connect和disconnect。 + + ``` + { + // ability发起connect + Want want = { nullptr }; + ElementName element = { nullptr }; + SetElementBundleName(&element, "com.company.appname"); + SetElementAbilityName(&element, "ServiceAbility"); + SetWantElement(&want, element); + ConnectAbility(want, *abilityConnection, this); + + // ability发起disconnect + DisconnectAbility(*abilityConnection); + } + ``` + + +### 包管理接口使用指导 - ``` - const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) - { - printf("ServiceAbility::OnConnect\n"); - return Ability::OnConnect(want); - } - ``` - - - OnDisconnect​\(\) - - 在组件与绑定的Service断开连接时调用。 - - - OnStop\(\) - - 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 - -4. 重写消息处理方法。 - - MsgHandle是Service用来处理客户端消息的方法。其中funcId是客户端传过来的消息类型,request是客户端传过来的序列化请求参数。如果用户在处理完成之后想要把结果传回去,需要把结果序列化后写入reply中。 - - ``` - void ServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) - { - printf("ServiceAbility::MsgHandle, funcId is %d\n", funcId); - int result = 0; - if (funcId == PLUS) { - result = IpcIoPopInt32(request) + IpcIoPopInt32(request); - } - // push data - IpcIoPushInt32(reply, result); - } - ``` - -5. 注册Service。 - - Service也需要在应用清单文件config.json中进行注册,注册类型type需要设置为service。 - - ``` - "abilities": [{ - "name": "ServiceAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "service", - "visible": true - } - ] - ``` - -6. 启动Service。 - - Ability为用户提供了StartAbility\(\)方法来启动另外一个Ability,因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。 - - 开发者可以通过Want的SetWantElement \(\)来设置目标服务信息。ElementName结构体的两个主要参数:第一个参数为包名称;第二个参数为目标Ability。 - - ``` - { - Want want = { nullptr }; - ElementName element = { nullptr }; - SetElementBundleName(&element, "com.company.appname"); - SetElementAbilityName(&element, "ServiceAbility"); - SetWantElement(&want, element); - StartAbility(want); - ClearElement(&element); - ClearWant(&want); - } - ``` - - StartAbility\(\) 方法会立即执行,如果Service尚未运行,则系统首先会调用OnStart\(\)。 - - - 停止Service。 - - Service一旦创建就会一直保持在后台运行,开发者可以通过调用StopAbility\(\)来停止Service。 - -7. 连接Service。 - - 如果Service需要与Page Ability或其他应用组件中的Service进行交互,则应创建用于连接的Service。Service支持其他Ability通过ConnectAbility\(\)与其进行连接,ConnectAbility\(\)需要传入目标Service的Want,以及IAbilityConnection的实例来处理回调。IAbilityConnection提供了两个方法供用户实现,OnAbilityConnectDone\(\)用来处理连接的回调,OnAbilityDisconnectDone\(\)用来处理断开连接的回调。 - - ``` - { - // ability创建IAbilityConnection对象和定义IAbilityConnection的两个方法实现 - IAbilityConnection abilityConnection = new IAbilityConnection(); - abilityConnection->OnAbilityConnectDone = OnAbilityConnectDone; - abilityConnection->OnAbilityDisconnectDone = OnAbilityDisconnectDone; - - void OnAbilityConnectDone(ElementName *elementName, SvcIdentity *serviceSid, - int resultCode, void *data) - { - if (resultCode != 0) { - return; - } - // push data - IpcIo request; - char dataBuffer[IPC_IO_DATA_MAX]; - IpcIoInit(&request, dataBuffer, IPC_IO_DATA_MAX, 0); - IpcIoPushInt32(&request, 10); - IpcIoPushInt32(&request, 6); - - // send and getReply - IpcIo reply; - uintptr_t ptr = 0; - if (Transact(nullptr, *serviceSid, 0, &request, &reply, - LITEIPC_FLAG_DEFAULT, &ptr) != LITEIPC_OK) { - printf("transact error\n"); - return; - } - int result = IpcIoPopInt32(&reply); - printf("execute add method, result is %d\n", result); - if (ptr != 0) { - FreeBuffer(nullptr, reinterpret_cast(ptr)); - } - } - - void OnAbilityDisconnectDone(ElementName *elementName, - int resultCode, void *data) - { - printf("elementName is %s, %s\n", - elementName->bundleName, elementName->abilityName); - } - } - ``` - - - 发起connect和disconnect。 - - ``` - { - // ability发起connect - Want want = { nullptr }; - ElementName element = { nullptr }; - SetElementBundleName(&element, "com.company.appname"); - SetElementAbilityName(&element, "ServiceAbility"); - SetWantElement(&want, element); - ConnectAbility(want, *abilityConnection, this); - - // ability发起disconnect - DisconnectAbility(*abilityConnection); - } - ``` - - - -### 包管理接口使用指导 **安装应用** -安装接口只能给内置的系统应用使用。根据应用的安装路径,可以在安装应用时进行选择: - -- 将应用安装到系统默认的文件目录/storage/app/。 -- 将应用安装到系统外挂的存储介质中,例如micro sdcard。 -这两种选择可以在创建InstallParam实例的时候指定,当InstallParam的成员变量installLocation为 INSTALL\_LOCATION\_INTERNAL\_ONLY时,意味着应用将会被安装到/storage/app/目录下;当InstallParam的成员变量installLocation为INSTALL\_LOCATION\_PREFER\_EXTERNAL时,意味着应用将被安装到存储介质,其安装目录是/sdcard/app/。由于安装应用的过程是异步的,所以需要使用类似信号量的机制来确保安装的回调可以被执行。 + 安装接口只能给内置的系统应用使用。根据应用的安装路径,可以在安装应用时进行选择: +- 将应用安装到系统默认的文件目录/storage/app/。 -安装应用的步骤如下(示例代码以安装到系统目录为例): +- 将应用安装到系统外挂的存储介质中,例如micro sdcard。 -1. 将经过安全签名的应用放置于指定的目录下。 -2. 创建InstallParam实例和信号量。 - ``` - InstallParam installParam = { - .installLocation = INSTALL_LOCATION_INTERNAL_ONLY, // 安装到系统目录 - .keepData = false - }; - static sem_t g_sem; - ``` +这两种选择可以在创建InstallParam实例的时候指定,当InstallParam的成员变量installLocation为 INSTALL_LOCATION_INTERNAL_ONLY时,意味着应用将会被安装到/storage/app/目录下;当InstallParam的成员变量installLocation为INSTALL_LOCATION_PREFER_EXTERNAL时,意味着应用将被安装到存储介质,其安装目录是/sdcard/app/。由于安装应用的过程是异步的,所以需要使用类似信号量的机制来确保安装的回调可以被执行。 -3. 定义回调函数。 - ``` - static void InstallCallback(const uint8_t resultCode, const void *resultMessage) - { - std::string strMessage = reinterpret_cast(resultMessage); - if (!strMessage.empty()) { - printf("install resultMessage is %s, %d\n", strMessage.c_str(),resultCode); - } - sem_post(&g_sem); - } - ``` + 安装应用的步骤如下(示例代码以安装到系统目录为例): +1. 将经过安全签名的应用放置于指定的目录下。 -4. 调用Install接口。 +2. 创建InstallParam实例和信号量。 + + ``` + InstallParam installParam = { + .installLocation = INSTALL_LOCATION_INTERNAL_ONLY, // 安装到系统目录 + .keepData = false + }; + static sem_t g_sem; + ``` - ``` - const uint32_t WAIT_TIMEOUT = 30; - sem_init(&g_sem, 0, 0); - std::string installPath = “/storage/bundle/demo.hap”; // hap包的存储路径 - bool result = Install(installPath.c_str(), &installParam, InstallCallback); - struct timespec ts = {}; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += WAIT_TIMEOUT; // 超时即释放信号量 - sem_timedwait(&g_sem, &ts); - ``` +3. 定义回调函数。 + + ``` + static void InstallCallback(const uint8_t resultCode, const void *resultMessage) + { + std::string strMessage = reinterpret_cast(resultMessage); + if (!strMessage.empty()) { + printf("install resultMessage is %s, %d\n", strMessage.c_str(),resultCode); + } + sem_post(&g_sem); + } + ``` + +4. 调用Install接口。 + + ``` + const uint32_t WAIT_TIMEOUT = 30; + sem_init(&g_sem, 0, 0); + std::string installPath = “/storage/bundle/demo.hap”; // hap包的存储路径 + bool result = Install(installPath.c_str(), &installParam, InstallCallback); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += WAIT_TIMEOUT; // 超时即释放信号量 + sem_timedwait(&g_sem, &ts); + ``` **卸载应用** -卸载应用的时候可以选择是否保留应用的数据,开发者可以通过创建的InstallParam实例的成员变量keepData来确定。当keepData为true, 卸载应用之后将保留应用的数据,当keepData为false时,卸载应用之后将不会保留应用的数据。 -1. 创建InstallParam实例和信号量。 + 卸载应用的时候可以选择是否保留应用的数据,开发者可以通过创建的InstallParam实例的成员变量keepData来确定。当keepData为true, 卸载应用之后将保留应用的数据,当keepData为false时,卸载应用之后将不会保留应用的数据。 +1. 创建InstallParam实例和信号量。 + + ``` + static sem_t g_sem; + InstallParam installParam = { + .installLocation = 1, + .keepData = false // 不保留应用数据 + }; + ``` + +2. 定义回调函数。 + + ``` + static void UninstallCallback(const uint8_t resultCode, const void *resultMessage) + { + std::string strMessage = reinterpret_cast(resultMessage); + if (!strMessage.empty()) { + printf("uninstall resultMessage is %s\n", strMessage.c_str()); + g_resultMessage = strMessage; + } + g_resultCode = resultCode; + sem_post(&g_sem); + } + ``` + +3. 调用Uninstall接口。 + + ``` + sem_init(&g_sem, 0, 0); + const uint32_t WAIT_TIMEOUT = 30; + std::string BUNDLE_NAME = “com.example.demo”; // 卸载应用的包名 + Uninstall(BUNDLE_NAME.c_str(), &installParam, UninstallCallback); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += WAIT_TIMEOUT; + sem_timedwait(&g_sem, &ts); + ``` - ``` - static sem_t g_sem; - InstallParam installParam = { - .installLocation = 1, - .keepData = false // 不保留应用数据 - }; - ``` -2. 定义回调函数。 - - ``` - static void UninstallCallback(const uint8_t resultCode, const void *resultMessage) - { - std::string strMessage = reinterpret_cast(resultMessage); - if (!strMessage.empty()) { - printf("uninstall resultMessage is %s\n", strMessage.c_str()); - g_resultMessage = strMessage; - } - g_resultCode = resultCode; - sem_post(&g_sem); - } - ``` - -3. 调用Uninstall接口。 +**查询已安装应用的包信息** - ``` - sem_init(&g_sem, 0, 0); - const uint32_t WAIT_TIMEOUT = 30; - std::string BUNDLE_NAME = “com.huawei.demo”; // 卸载应用的包名 - Uninstall(BUNDLE_NAME.c_str(), &installParam, UninstallCallback); - struct timespec ts = {}; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += WAIT_TIMEOUT; - sem_timedwait(&g_sem, &ts); - ``` + 开发者可以利用BundleManager提供的接口GetBundleInfo来查询系统内已安装应用的包信息。 +1. 创建以及初始化BundleInfo。 + + ``` + BundleInfo bundleInfo; + (void) memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)); + ``` + +2. 调用GetBundleInfo接口,指定查询应用的包名,同时指定flag来确定获取的BundleInfo中是否含有元能力信息(实例代码以含有元能力信息为例)。 + + ``` + std::string BUNDLE_NAME = "com.example.demo"; + uint8_t ret = GetBundleInfo(BUNDLE_NAME.c_str(), 1, &bundleInfo); // flags = 1,获取包信息中含有元能力信息 + ``` + +3. 使用完获取的BundleInfo之后,要及时清理掉其内部所占用的内存空间避免内存泄漏。 + + ``` + ClearBundleInfo(&bundleInfo); + ``` + + +### Hap包打包 + + + 打包工具一般集成到开发工具或者IDE中,开发者一般不涉及直接使用该工具,下面的介绍开发者可以作为了解。打包工具的jar包在开源代码中的位置:developtools/packing_tool/jar。 +- 打包命令行参数 + **表2** 打包所需要的资源文件描述 + + | 命令参数 | 对应的资源文件 | 说明 | 是否可缺省 | + | -------- | -------- | -------- | -------- | + | --mode | - | 为“hap”字段,打包生成hap | 否 | + | --json-path | 清单文件config.json | - | 否 | + | --resources-path | 资源文件resources | - | 是 | + | --assets-path | 资源文件assets | - | 是 | + | --lib-path | 依赖库TONGGUO 文件 | - | 是 | + | --shared-libs-path | 共享库文件 | 针对系统应用的共享库,特殊情况下使用 | 是 | + | --ability-so-path | 主功能so文件 | - | 是 | + | --index-path | 资源索引 | 资源索引文件由资源生成工具生成,由资源流水线会集成该工具 | 是 | + | --out-path | - | 生成的hap包输出路径,默认为当前目录 | 是 | + | --force | - | 是否覆盖原有同名文件,默认为false | 是 | + +- 打包示例 + + **图1** 开发视图 -**查询已安装应用的包信息** + ![zh-cn_image_0000001154005784](figures/zh-cn_image_0000001154005784.png) -开发者可以利用BundleManager提供的接口GetBundleInfo来查询系统内已安装应用的包信息。 - -1. 创建以及初始化BundleInfo。 - - ``` - BundleInfo bundleInfo; - (void) memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)); - ``` - -2. 调用GetBundleInfo接口,指定查询应用的包名,同时指定flag来确定获取的BundleInfo中是否含有元能力信息(实例代码以含有元能力信息为例)。 - - ``` - std::string BUNDLE_NAME = "com.huawei.demo"; - uint8_t ret = GetBundleInfo(BUNDLE_NAME.c_str(), 1, &bundleInfo); // flags = 1,获取包信息中含有元能力信息 - ``` - -3. 使用完获取的BundleInfo之后,要及时清理掉其内部所占用的内存空间避免内存泄漏。 - - ``` - ClearBundleInfo(&bundleInfo); - ``` - - -### Hap包打包 - -打包工具一般集成到开发工具或者ide中,开发者一般不涉及直接使用该工具,下面的介绍开发者可以作为了解。打包工具的jar包在开源代码中的位置:developtools/packing\_tool/jar。 - -- 打包命令行参数 - - **表 2** 打包所需要的资源文件描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

命令参数

-

对应的资源文件

-

说明

-

是否可缺省

-

--mode

-

-

-

为“hap”字段,打包生成hap

-

-

--json-path

-

清单文件config.json

-

-

-

-

--resources-path

-

资源文件resources

-

-

-

-

--assets-path

-

资源文件assets

-

-

-

-

--lib-path

-

依赖库文件

-

-

-

-

--shared-libs-path

-

共享库文件

-

针对系统应用的共享库,特殊情况下使用

-

-

--ability-so-path

-

主功能so文件

-

-

-

-

--index-path

-

资源索引

-

资源索引文件由资源生成工具生成,由资源流水线会集成该工具

-

-

--out-path

-

-

-

生成的hap包输出路径,默认为当前目录

-

-

--force

-

-

-

是否覆盖原有同名文件,默认为false

-

-
- -- 打包示例 - - 开发视图 - - ![](figure/zh-cn_image_0000001062942690.png) - - - 编译视图 - - ![](figure/zh-cn_image_0000001062334618.png) - - - 使用打包工具执行以下命令打包: - - ![](figure/zh-cn_image_0000001062476933.png) - - ``` - $ java -jar hmos_app_packing_tool.jar --mode hap --json-path ./config.json --assets-path ./assets/ --ability-so-path ./libentry.so --index-path ./resources.index --out-path out/entry.hap --force true - ``` + + **图2** 编译视图 + ![zh-cn_image_0000001154167492](figures/zh-cn_image_0000001154167492.png) + + **图3** 使用打包工具执行以下命令打包: + ![zh-cn_image_0000001200127655](figures/zh-cn_image_0000001200127655.png) + + + ``` + $ java -jar hmos_app_packing_tool.jar --mode hap --json-path ./config.json --assets-path ./assets/ --ability-so-path ./libentry.so --index-path ./resources.index --out-path out/entry.hap --force true + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md b/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md index f78a9d8711ba2aa05cfe89dfba5fa275062b7f56..89266e3b2ccd625b018c4cd848ca137075496419 100644 --- a/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md @@ -1,140 +1,128 @@ -# 概述 +# 概述 -- [基本概念](#section72601941194812) -- [Ability子系统](#section14633111813374) -- [包管理子系统](#section1341146154412) -- [运作机制](#section94302021112717) -- [约束与限制](#section89534912527) -用户程序框架是OpenHarmony为开发者提供开发OpenHarmony应用的开发框架,包含两个模块:Ability子系统和包管理子系统。 +用户程序框架是OpenHarmony为开发者提供开发OpenHarmony应用的开发框架,包含两个子系统:Ability子系统和包管理子系统。 -## 基本概念 -开发者在开发前需要先了解以下基本概念,方便开发者更好的理解OpenHarmony用户程序框架。 - -## Ability子系统 - -Ability子系统是管理OpenHarmony应用运行状态的开发框架。 - -**图 1** Ability子系统框架图 -![](figure/Ability子系统框架图.png "Ability子系统框架图") - -- **Ability**:系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability。 - - **Page类型的Ability**:带有界面,为用户提供人机交互的能力。 +## 基本概念 - - **Service类型的Ability**:不带界面,为用户提供后台任务机制。 +开发者在开发前需要先了解以下基本概念,方便开发者更好的理解OpenHarmony用户程序框架。 +### Ability子系统 -- **AbilitySlice**:单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。 + Ability子系统是管理OpenHarmony应用运行状态的开发框架。 + + **图1** Ability子系统框架图 + + ![zh-cn_image_0000001151375648](figures/zh-cn_image_0000001151375648.png) - **图 2** Ability与AbilitySlice的关系图 - ![](figure/Ability与AbilitySlice的关系图.png "Ability与AbilitySlice的关系图") + +- **Ability**:系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability。 + - **Page类型的Ability**:带有界面,为用户提供人机交互的能力。 + - **Service类型的Ability**:不带界面,为用户提供后台任务机制。 -- **生命周期**:Ability被调度到启动、激活、隐藏和退出等各个状态的统称。 +- **AbilitySlice**:单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。 + + **图2** Ability与AbilitySlice的关系图 + + ![zh-cn_image_0000001197415205](figures/zh-cn_image_0000001197415205.png) - **图 3** Ability生命周期流转 +- **生命周期**:Ability被调度到启动、激活、隐藏和退出等各个状态的统称。 + + **图3** Ability生命周期流转 + ![zh-cn_image_0000001197896843](figures/zh-cn_image_0000001197896843.png) + - **OnStart()** + 系统首次创建Page实例时触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。 + + - **OnActive()** + Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。 + + 当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用OnInactive()回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用OnActive()回调。因此,开发者通常需要成对实现OnActive()和OnInactive(),并在OnActive()中获取在OnInactive()中被释放的资源。 + + - **OnInactive()** + 当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。 + + - **OnBackground()** + 如果Page不再对用户可见,系统将可能根据资源状况调用此回调,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。 + + - **OnForeground()** + 处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用OnForeground()回调使Page回到INACTIVE状态,然后调用OnActive()回调使Page回到ACTIVE状态。开发者应当在此回调中重新申请在OnBackground()中释放的资源。轻量化设备目前不支持该接口。 + + - **OnStop()** + 此回调表示系统正在销毁Page。销毁Page的可能原因包括: + + - 用户通过系统管理能力显式关闭Page,例如使用任务管理器关闭Page。 + - 用户行为触发Page的TerminateAbility()方法调用,例如使用应用的退出功能。 + - 配置变更导致系统暂时销毁Page并重建。 + - 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。 + +- **AbilityKit**:Ability框架提供给开发者的开发包,开发者基于该开发包可以开发出基于Ability组件的应用。基于Ability组件开发的应用有两种类型:基于Javascript语言开发的Ability(JS Ability)和基于C/C++语言开发的Ability(Native Ability)。JS应用开发框架是开发者开发JS Ability所用到框架,是在AbilityKit基础封装的包含JS UI组件的一套方便开发者能够迅速开发Ability应用的框架。 + +- **AbilityLoader**:负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。 + +- **AbilityManager**:负责AbilityKit和Ability管理服务进行IPC的通信。 + +- **EventHandler**:AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。 + +- **AbilityManagerService**:元能力运行管理服务。该服务用于协调各Ability运行关系、及生命周期进行调度的系统服务。其中,服务启动模块负责Ability管理服务的启动、注册等。服务接口管理模块负责Ability管理服务对外能力的管理。进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。连接管理模块是Ability管理服务对Service类型Ability连接管理的模块。 + +- **AppSpawn**:负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。 + + +### 包管理子系统 - ![](figure/图片1.png) - - - **OnStart\(\)** - - 系统首次创建Page实例时触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。 - - - **OnActive\(\)** - - Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。 - - 当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用OnInactive\(\)回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用OnActive\(\)回调。因此,开发者通常需要成对实现OnActive\(\)和OnInactive\(\),并在OnActive\(\)中获取在OnInactive\(\)中被释放的资源。 - - - **OnInactive\(\)** - - 当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。 - - - **OnBackground\(\)** - - 如果Page不再对用户可见,系统将可能根据资源状况调用此回调,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。 - - - **OnForeground\(\)** - - 处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用OnForeground\(\)回调使Page回到INACTIVE状态,然后调用OnActive\(\)回调使Page回到ACTIVE状态。开发者应当在此回调中重新申请在OnBackground\(\)中释放的资源。轻量化设备目前不支持该接口。 - - - **OnStop\(\)** - - 此回调表示系统正在销毁Page。销毁Page的可能原因包括: - - - 用户通过系统管理能力显式关闭Page,例如使用任务管理器关闭Page。 - - 用户行为触发Page的TerminateAbility\(\)方法调用,例如使用应用的退出功能。 - - 配置变更导致系统暂时销毁Page并重建。 - - 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。 - - -- **AbilityKit**:Ability框架提供给开发者的开发包,开发者基于该开发包可以开发出基于Ability组件的应用。基于Ability组件开发的应用有两种类型:基于Javascript语言开发的Ability(JS Ability)和基于C/C++语言开发的Ability(Native Ability)。JS应用开发框架是开发者开发JS Ability所用到框架,是在AbilityKit基础封装的包含js UI组件的一套方便开发者能够迅速开发Ability应用的框架。 -- **AbilityLoader**:负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。 - -- **AbilityManager**:负责AbilityKit和Ability管理服务进行IPC的通信。 - -- **EventHandler**:AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。 - -- **AbilityManagerService**:元能力运行管理服务。该服务用于协调各Ability运行关系、及生命周期进行调度的系统服务。其中,服务启动模块负责Ability管理服务的启动、注册等。服务接口管理模块负责Ability管理服务对外能力的管理。进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。连接管理模块是Ability管理服务对Service类型Ability连接管理的模块 - -- **AppSpawn**:负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。 +包管理子系统是OpenHarmony为开发者提供的安装包管理框架。 + **图4** 包管理子系统框架图 -## 包管理子系统 + ![zh-cn_image_0000001197495305](figures/zh-cn_image_0000001197495305.png) -包管理子系统是OpenHarmony为开发者提供的安装包管理框架。 + +- **BundleKit**:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化listen接口。 -**图 4** 包管理子系统框架图 -![](figure/包管理子系统框架图.png "包管理子系统框架图") +- **包扫描器**:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。 -- **BundleKit**:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化listen接口。 -- **包扫描器**:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。 -- **包安装子模块**:安装,卸载,升级一个包;包安装服务是一个单独进程和包管理服务通过IPC进行通信,该服务用于创建、删除安装目录和数据目录等,具有较高的权限。 +- **包安装子模块**:安装,卸载,升级一个包。包安装服务是一个单独进程和包管理服务通过IPC进行通信,该服务用于创建、删除安装目录和数据目录等,具有较高的权限。 -- **包管理子模块**:管理安装包相关的信息,存储持久化包信息。 +- **包管理子模块**:管理安装包相关的信息,存储持久化包信息。 -- **包安全管理子模块**:签名检查、权限授予、权限管理。 +- **包安全管理子模块**:签名检查、权限授予、权限管理。 -## 运作机制 +## 运作机制 -Ability子系统的核心模块是Ability管理服务、包管理子系统的核心模块是包管理服务,这两个服务是系统级服务,借助系统服务框架Samgr实现服务的注册与发现,并对其他进程提供Ability管理服务和包管理服务。Ability管理服务和包管理服务通过AbilityKit和BundleKit以接口的形式向外提供服务。 +Ability子系统的核心模块是Ability管理服务、包管理子系统的核心模块是包管理服务,这两个服务是系统级服务,借助系统服务框架SAMgr实现服务的注册与发现,并对其他进程提供Ability管理服务和包管理服务。Ability管理服务和包管理服务通过AbilityKit和BundleKit以接口的形式向外提供服务。 -**图 5** Ability管理服务和包管理服务启动 -![](figure/Ability管理服务和包管理服务启动.png "Ability管理服务和包管理服务启动") + **图5** Ability管理服务和包管理服务启动 + + ![zh-cn_image_0000001062014699](figures/zh-cn_image_0000001062014699.png) Ability管理服务和包管理服务启动后,就可以安装OpenHarmony应用和启动运行OpenHarmony应用。 -**图 6** 应用启动流程 -![](figure/应用启动流程.png "应用启动流程") + **图6** 应用启动流程 + + ![zh-cn_image_0000001062068389](figures/zh-cn_image_0000001062068389.png) 桌面为Ability管理服务启动的第一个OpenHarmony应用。桌面启动后,用户可以在桌面上点击安装的OpenHarmony应用并启动该应用。上图6为从桌面启动一个已安装应用的交互流程。 从图中可知,Ability管理服务负责协调Ability之间的显示隐藏,包管理服务负责Ability信息的存储查询。 -## 约束与限制 - -- 语言版本 - - - C++11版本或以上 - - -- 框架针对不同的芯片平台和底层OS能力,规格有所区别 - - - Cortex-M RAM/ROM: - - - RAM:建议大于20K - - - ROM: \> 300K (包含JS应用开发框架,UIKit及引擎等强相关子系统) - - Cortex-A RAM/ROM: +## 约束与限制 - - RAM:建议大于2M +- 语言版本 - - ROM:\> 2M (包含JS应用开发框架,UIKit及引擎等强相关子系统) + - C++11版本或以上 +- 框架针对不同的芯片平台和底层OS能力,规格有所区别 + - Cortex-M RAM/ROM: + - RAM:建议大于20K + - ROM: > 300K (包含JS应用开发框架,UIKit及引擎等强相关子系统) + - Cortex-A RAM/ROM: + - RAM:建议大于2M + - ROM:> 2M (包含JS应用开发框架,UIKit及引擎等强相关子系统) diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework.md b/zh-cn/device-dev/subsystems/subsys-application-framework.md index 178c2f17a9cae8229098822c0f98158a0dfeed9f..585ccb7c1338219e9a598834765b390f4d458860 100644 --- a/zh-cn/device-dev/subsystems/subsys-application-framework.md +++ b/zh-cn/device-dev/subsystems/subsys-application-framework.md @@ -1,11 +1,11 @@ -# 用户程序框架 +# 用户程序框架 -- **[概述](subsys-application-framework-overview.md)** -- **[搭建环境](subsys-application-framework-envbuild.md)** -- **[开发指导](subsys-application-framework-guide.md)** +- **[概述](subsys-application-framework-overview.md)** -- **[开发实例](subsys-application-framework-demo.md)** +- **[搭建环境](subsys-application-framework-envbuild.md)** +- **[开发指导](subsys-application-framework-guide.md)** +- **[开发实例](subsys-application-framework-demo.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-boot-appspawn.md b/zh-cn/device-dev/subsystems/subsys-boot-appspawn.md index be45c896a216556c76349bad47f744857da3ac8f..839f4e385eb7fd998662d0551df1d8d03644331e 100755 --- a/zh-cn/device-dev/subsystems/subsys-boot-appspawn.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-appspawn.md @@ -1,47 +1,103 @@ -# appspawn应用孵化组件 - -appspawn被init启动后,向IPC框架注册服务名称,之后等待接收进程间消息,根据消息解析结果启动应用服务并赋予其对应权限。 - -appspawn注册的服务名称为“appspawn”,可通过包含“base\\startup\\appspawn\_lite\\services\\include\\appspawn\_service.h“头文件,获取服务名称对应的宏APPSPAWN\_SERVICE\_NAME定义。在安全子系统限制规则下,目前仅Ability Manager Service有权限可以向appspawn发送的进程间消息。 - -appspawn接收的消息为json格式,如下所示: - -"\{\\"bundleName\\":\\"testvalid1\\",\\"identityID\\":\\"1234\\",\\"uID\\":1000,\\"gID\\":1000,\\"capability\\":\[0\]\}" - -**表 1** 字段说明 - - - - - - - - - - - - - - - - - - - - - - -

字段名

-

说明

-

bundleName

-

即将启动的应用服务进程名,长度≥7字节,≤127字节。

-

identityID

-

AMS为新进程生成的标识符,由appspawn透传给新进程,长度≥1字节,≤24字节。

-

uID

-

即将启动的应用服务进程的uID,必须为正值。

-

gID

-

即将启动的应用服务进程的gID,必须为正值。

-

capability

-

即将启动的应用服务进程所需的capability权限,数量≤10个。

-
+# appspawn应用孵化组件 + +## 概述 + +appspawn被init启动后,等待接收进程间消息,根据消息内容启动应用服务并赋予其对应权限。 + + +## 功能简介 + +- 安全控制  支持为app设置SELinux标签。 + +- 应用进程控制 + - 支持为app设置AccessToken。 + - 支持重启前,appspawn停止后,可同时停止所有已孵化的app进程。 + +- 冷启动 + 支持应用通过aa命令冷启动应用。 + + ``` + param set appspawn.cold.boot true // 打开冷启动状态 + aa start -d 12345 -a $name -b $package -C + 参考: + aa start -d 12345 -a ohos.acts.startup.sysparam.function.MainAbility -b ohos.acts.startup.sysparam.function -C + ``` + + +## 基本概念 + +appspawn注册的服务名称为“appspawn”, appspawn 通过监听本地socket,接收来自客户端的请求消息。消息类型为AppProperty的结构体, 定义路径为:“base/startup/appspawn_standard/interfaces/innerkits/include/sclient_socket.h“。 + + **表1** 字段说明 + +| 字段名 | 说明 | +| -------- | -------- | +| processName | 即将启动的应用服务进程名,最大256字节。 | +| bundleName | 即将启动的应用程序包名,最大256字节。 | +| soPath | 应用程序指定的动态库的路径,最大256字节。 | +| uid | 即将启动的应用进程的uid,必须为正值。 | +| gid | 即将启动的应用进程的gid,必须为正值。 | +| gidTable | 即将启动的应用进程组信息,长度由gidCount指定,最大支持64个进程组,必须为正值。 | +| gidCount | 即将启动的应用进程组个数。 | +| accessTokenId | 应用进程权限控制的token id。 | +| apl | 应用进程权限控制的apl,最大32字节。 | + + +## 开发指导 + +接口定义路径: “base/startup/appspawn_standard/interfaces/innerkits/include/client_socket.h“,表 2为接口说明。 + + +### 接口说明 + + **表2** 字段说明 + +| 字段名 | 说明 | +| -------- | -------- | +| CreateClient | 创建client。 | +| CloseClient | 关闭client。 | +| ConnectSocket | 向appspawn服务发起连接请求。 | +| WriteSocketMessage | 发送消息到appspawn服务。 | +| ReadSocketMessage | 接收来自appspawn服务的消息。 | + + +## 开发实例 + +接口使用参考方式: + + +``` +std::shared_ptr clientSocket = std::make_unique("AppSpawn"); + if (clientSocket == nullptr) { + return -1; + } + if (clientSocket->CreateClient() != ERR_OK) { + return -1; + } + if (clientSocket->ConnectSocket() != ERR_OK) { + return -1;; + } + // property 构造AppProperty + clientSocket->WriteSocketMessage((void *)&property, sizeof(AppSpawn::AppProperty)); + // 读结果 + int pid; + clientSocket->ReadSocketMessage((void *)&pid, sizeof(pid)); + // 如果失败,返回pid如果小于等于0,则错误,否则返回应用的进程id +``` + + +## 常见问题 + + +### 冷启动失败 + +**现象描述** + +通过命令冷启动应用失败。 + +**解决方法** + +1. 确认是否打开冷启动设置 + +2. 确认冷启动命令是否正确 diff --git a/zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md b/zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md index 0f50ea7a38e8d29a7f41922b38deb2017802cd82..529a4d4eb0cb00c68b465f7169e7432f3748ead8 100755 --- a/zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md @@ -1,54 +1,33 @@ -# bootstrap服务启动组件 +# bootstrap服务启动组件 -- [接口说明](#section1633115419401) -- [开发实例](#section2055311316228) -bootstrap服务启动组件实现了服务的自动初始化,即服务的初始化函数无需显式调用,而是将其使用宏定义的方式申明,就会在系统启动时自动被执行。实现原理是将服务启动的函数通过宏申明之后,放在预定义好的zInit代码段中,系统启动的时候调用OHOS\_SystemInit接口,遍历该代码段并调用其中的函数。因此,需要在链接脚本中添加zInit段,并且在main函数里调用OHOS\_SystemInit接口。 +bootstrap服务启动组件实现了服务的自动初始化,即服务的初始化函数无需显式调用,而是将其使用宏定义的方式申明,就会在系统启动时自动被执行。实现原理是将服务启动的函数通过宏申明之后,放在预定义好的zInit代码段中,系统启动的时候调用OHOS_SystemInit接口,遍历该代码段并调用其中的函数。因此,需要在链接脚本中添加zInit段,并且在main函数里调用OHOS_SystemInit接口。 + zInit段的添加可参考已有的Hi3861平台的链接脚本,文件路径为vendor/hisi/hi3861/hi3861/build/link/link.ld.S。 + 用于实现服务的自动初始化的宏定义接口请参见启动恢复子系统的[API接口文档](https://device.harmonyos.com/cn/docs/develop/apiref/init-0000001054598113)。 -## 接口说明 + +## 接口说明 bootstrap服务启动: -**表 1** 主要的服务自动初始化宏 - - - - - - - - - - - - - - - - - - - -

接口名

-

描述

-

SYS_SERVICE_INIT(func)

-

标识核心系统服务的初始化启动入口。

-

SYS_FEATURE_INIT(func)

-

标识核心系统功能的初始化启动入口。

-

APP_SERVICE_INIT(func)

-

标识应用层服务的初始化启动入口。

-

APP_FEATURE_INIT(func)

-

标识应用层功能的初始化启动入口。

-
- -## 开发实例 - -服务自动初始化宏使用实例: + **表1** 主要的服务自动初始化宏 + +| 接口名 | 描述 | +| -------- | -------- | +| SYS_SERVICE_INIT(func) | 标识核心系统服务的初始化启动入口。 | +| SYS_FEATURE_INIT(func) | 标识核心系统功能的初始化启动入口。 | +| APP_SERVICE_INIT(func) | 标识应用层服务的初始化启动入口。 | +| APP_FEATURE_INIT(func) | 标识应用层功能的初始化启动入口。 | + +## 开发实例 + + 服务自动初始化宏使用实例: + ``` void SystemServiceInit(void) { printf("Init System Service\n"); @@ -76,4 +55,3 @@ APP_FEATURE_INIT(AppFeatureInit); // Init App Service // Init App Feature ``` - diff --git a/zh-cn/device-dev/subsystems/subsys-boot-faqs.md b/zh-cn/device-dev/subsystems/subsys-boot-faqs.md index aa99975af2e18e7609139850230ade8b8ef894cc..91aa7c2bf1e6bffc440d7994d21a69d282cbf58e 100644 --- a/zh-cn/device-dev/subsystems/subsys-boot-faqs.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-faqs.md @@ -1,17 +1,15 @@ -# 常见问题 +# 常见问题 -- [系统启动过程中打印“parse failed!”错误后停止启动](#section2041345718513) -- [系统启动过程未结束就自动重启,如此反复持续](#section57381816168) -- [参数正确的情况下调用SetParameter/GetParameter返回失败](#section129991227141512) -## 系统启动过程中打印“parse failed!”错误后停止启动 +## 系统启动过程中打印“parse failed!”错误后停止启动 **现象描述** -系统启动过程中,打印“\[Init\] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示: +系统启动过程中,打印“[Init] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示: -**图 1** 运行报错图 -![](figure/运行报错图.png "运行报错图") + **图1** 运行报错图 + + ![zh-cn_image_0000001200053087](figures/zh-cn_image_0000001200053087.png) **可能原因** @@ -21,7 +19,8 @@ 仔细检查init.cfg文件,确保其格式符合json格式要求。 -## 系统启动过程未结束就自动重启,如此反复持续 + +## 系统启动过程未结束就自动重启,如此反复持续 **现象描述** @@ -29,19 +28,22 @@ **可能原因** -被init启动的服务都有一个叫做“importance”的属性(详见[init启动引导组件表3](subsys-boot-init.md#table14737791471)描述)。 +被init启动的服务都有一个叫做“importance”的属性(详见[第2章表3](../subsystems/subsys-boot-init.md)第二章节表3描述)。 + +- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。 -- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。 -- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。 +- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。 因此出现上述现象的可能原因:有“importance”属性为1的服务在每次启动的过程中都会退出(可能是进程崩溃或出错自动退出),导致init进程自动重启单板。 **解决办法** -1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。 -2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。 +1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。 -## 参数正确的情况下调用SetParameter/GetParameter返回失败 +2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。 + + +## 参数正确的情况下调用SetParameter/GetParameter返回失败 **现象描述** @@ -54,4 +56,3 @@ **解决办法** 无需处理 - diff --git a/zh-cn/device-dev/subsystems/subsys-boot-init.md b/zh-cn/device-dev/subsystems/subsys-boot-init.md index da099a6475bb20633aff0baa29f9639fe3c5fdca..2f83aef6c1a94913afc6d72c005d98811aba7248 100755 --- a/zh-cn/device-dev/subsystems/subsys-boot-init.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-init.md @@ -1,28 +1,29 @@ -# init启动引导组件 +# init启动引导组件 -## 功能说明 - init启动引导组件负责在系统启动阶段启动关键服务进程。 若用户需要新增随开机自启动的系统服务,可添加新的配置文件xxx.cfg,系统会自动分析对应的cfg文件,并按照cfg文件启动对应的服务。 +## 功能说明 -- init启动引导的配置文件 +init启动引导组件负责在系统启动阶段启动关键服务进程。 若用户需要新增随开机自启动的系统服务,可添加新的配置文件xxx.cfg,系统会自动分析对应的cfg文件,并按照cfg文件启动对应的服务。 - init启动引导组件配置文件包含了所有需要由init进程启动的系统关键服务的服务名、可执行文件路径、权限和其他信息,烧写单板后可在“/etc/“目录下找到,文件名称为init.cfg,采用json格式,文件大小目前限制在100KB以内。 +- init启动引导的配置文件 + init启动引导组件配置文件包含了所有需要由init进程启动的系统关键服务的服务名、可执行文件路径、权限和其他信息,烧写单板后可在“/etc/“目录下找到,文件名称为init.cfg,采用json格式,文件大小目前限制在100KB以内。 init进程启动后读取/etc/init.cfg,然后解析其json格式内容,并根据解析结果依次加载系统服务。 各模块需要添加关键服务时,也可以添加模块对应的cfg文件,编译时拷贝文件到/system/etc/init目录下,init进程会解析改cfg文件,并启动对应的服务。 -- init服务启动控制(仅标准系统以上提供) - +- init服务启动控制(仅标准系统以上提供) init会根据用户的服务配置,把服务分成三类,在不同的阶段进行启动。 - “boot”类型:对应系统中需要优先启动的服务,这类服务在init完成init阶段后启动。 - “normal”类型:默认配置,对应系统中的普通服务,这类服务在init命令执行完成后启动。 - - "condition"类型:对应有特殊要求的服务,可以直接通过start xxx 命令执行启动,一般在条件job或者在init的某个阶段使用命令启动。 + - “condition”类型:对应有特殊要求的服务,可以直接通过start xxx 命令执行启动,一般在条件job或者在init的某个阶段使用命令启动。 服务间或服务与命令之间存在依赖关系,需要通过"condition"描述服务,例如: + + ``` - "services" : [{ + "services" : [{ "name" : "service1", "path" : ["/bin/process1", "param1", "param2"], "uid" : 1, @@ -42,313 +43,215 @@ "on-restart" : "services:service1_restart" } }, - ``` -- init服务并行控制(仅标准系统以上提供) +- init服务并行控制(仅标准系统以上提供) init提供服务并行处理能力,启动服务在不同的阶段执行job的能力。 - “on-start”:在服务进程被fock后执行,不同服务的on-start job可以并行执行(在服务的子进程中执行,只对改进程产生影响)。 - “on-stop”:在服务停止时执行。 - - "on-restart":在服务重启时执行。 - -- init 按需启动(仅标准系统以上提供) + - “on-restart”:在服务重启时执行。 +- init 按需启动(仅标准系统以上提供) 由init管理的服务支持按需启动,按需启动的服务不会在系统启动过程中主动被拉起,而是当某些事件发生时才会被init按需拉起,触发服务启动的事件可能是被init监听的相关socket有消息上报、samgr收到客户端的请求需要拉起SA服务等情况。 - "ondemand" 属性是按需启动的服务的标志,一个服务配置了该属性值为true的时候,服务不再需要配置start命令来拉起,而是被监听的相应事件发生时才会被拉起。 + "ondemand" :按需启动服务的标志,一个服务配置了该属性值为true的时候,服务不再需要配置start命令来拉起,而是被监听的相应事件发生时才会被拉起。 - SA进程按需启动 - 1. 应用请求SA句柄时samgr需识别SA所属进程是否可动态拉起。 - 2. 如需拉起,则需阻塞请求,等init拉起SA进程并注册SA后再返回所请求的SA句柄。 - + 1. 应用请求SA句柄时samgr需识别SA所属进程是否可动态拉起。 + 2. 如需拉起,则需阻塞请求,等init拉起SA进程并注册SA后再返回所请求的SA句柄。 - socket进程按需启动 - 1. init在pre-fork阶段为socket类进程创建好socket,init中监听创建好的socket上的网络事件。 - 2. socket上有报文事件后,init拉起socket进程进行报文处理,init进程取消socket数据的监听,由socket进程处理。 - 3. socket进程无报文处理后,可以自动退出,退出后init回收该子进程并重新监听socket网络数据。 - - - 热插拔服务进程按需启动 -
  进程可根据系统参数的变化进行热插拔事件按需启动处理。 - -- init 进程启动&回收能力增强 + 1. init在pre-fork阶段为socket类进程创建好socket,init中监听创建好的socket上的网络事件。 + 2. socket上有报文事件后,init拉起socket进程进行报文处理,init进程取消socket数据的监听,由socket进程处理。 + 3. socket进程无报文处理后,可以自动退出,退出后init回收该子进程并重新监听socket网络数据。 + - 热插拔服务进程按需启动  进程可根据系统参数的变化进行热插拔事件按需启动处理。 +- init 进程启动&回收能力增强 进程启动时,支持在配置文件中配置服务进程的绑核、优先级、MAC信息以及AccessToken信息。 - - init提供修改*.cfg配置文件, 为服务进程提供cpu绑核功能。 - - init提供修改*.cfg配置文件, 为服务进程提供优先级设置。 - - init提供修改*.cfg配置文件, 为服务提供设置AccessToken, 为系统服务进程设置其分布式Capability能力(仅标准系统以上提供)。 - - init提供修改*.cfg配置文件, 为服务提供抑制机制。 - -- init FD代持(仅标准系统以上提供) + - init提供修改\*.cfg配置文件, 为服务进程提供cpu绑核功能。 + - init提供修改\*.cfg配置文件, 为服务进程提供优先级设置。 + - init提供修改\*.cfg配置文件, 为服务提供设置AccessToken, 为系统服务进程设置其分布式Capability能力(仅标准系统以上提供)。 + - init提供修改\*.cfg配置文件, 为服务提供抑制机制。 +- init FD代持(仅标准系统以上提供) FD代持是按需启动的一个辅助扩展机制,按需启动进程可以保持退出前的fd状态句柄不丢失。按需启动进程退出前可将fd发送给init代持,再次启动后再从init获取fd。 init提供了相关接口供服务调用,服务进程退出前调用接口将fd通过支持IPC通信的socket发送给init代持,待该服务重新启动时,init将持有的该服务相关的fd句柄通过同样的方式返回给服务。 -- init job - +- init job init提供job能力,一个job就是一组命令的集合。job可以在init.cfg中配置,也可以在模块的自定义cfg中配置。init解析程序会把相同名字job的命令合并到一个job中。同一名字的job只能保证init.cfg中的命令优先执行,其他cfg间的命令执行顺序不保证。 - 普通job:一般是init启动的固定阶段,如“pre-init“,”init“,”post-init“等,这类job在init启动的固定阶段执行。 - - 自定义job:用户自定义的job,这类job按照一定的规则进行触发。 - - job:用户任意定义,可以通过trigger命令执行。 - - 控制job(仅标准系统以上提供):按条件触发处理的能力。在job中可以设置触发条件,当对应的属性值满足设置的条件时,就会触发job执行。触发条件支持&&和||操作,可以根据不同的属性就行组合。 + - job:用户任意定义,可以通过trigger命令执行。 + - 控制job(仅标准系统以上提供):按条件触发处理的能力。在job中可以设置触发条件,当对应的属性值满足设置的条件时,就会触发job执行。触发条件支持&&和||操作,可以根据不同的属性就行组合。 -## 开发指导 - 1. 配置jobs数组。 +## 开发指导 - init启动引导组件将系统启动分为三个阶段: +1. 配置jobs数组。 + init启动引导组件将系统启动分为三个阶段: - - “pre-init”阶段:启动系统服务之前需要先执行的操作,例如挂载文件系统、创建文件夹、修改权限等。 - - “init”阶段:系统服务启动阶段。 - - “post-init”阶段:系统服务启动完后还需要执行的操作。 + - “pre-init”阶段:启动系统服务之前需要先执行的操作,例如挂载文件系统、创建文件夹、修改权限等。 + - “init”阶段:系统服务启动阶段。 + - “post-init”阶段:系统服务启动完后还需要执行的操作。 - ``` + + ``` "jobs" : [{ - "name" : "pre-init", - "cmds" : [ - "mkdir /testdir", - "chmod 0700 /testdir", - "chown 99 99 /testdir", - "mount vfat /dev/mmcblk0p0 /testdir2 noexec nosuid" // mount命令,格式为:mount 文件系统类型 source target flags data - ] - }, { - "name" : "init", - "cmds" : [ - "start service1", - ] - }, { - "name" : "post-init", - "cmds" : [] - } - ] - ``` + "name" : "pre-init", + "cmds" : [ + "mkdir /testdir", + "chmod 0700 /testdir", + "chown 99 99 /testdir", + "mount vfat /dev/mmcblk0p0 /testdir2 noexec nosuid" // mount命令,格式为:mount 文件系统类型 source target flags data + ] + }, { + "name" : "init", + "cmds" : [ + "start service1", + ] + }, { + "name" : "post-init", + "cmds" : [] + } + ] + ``` + + **表1** 执行job介绍 + + | job名 | 说明 | + | -------- | -------- | + | pre-init | 最先执行的job,如果开发者的进程在启动之前需要首先执行一些操作(例如创建文件夹),可以把操作放到pre-init中先执行。 | + | init | 中间执行的job,例如服务启动。 | + | post-init | 最后被执行的job,如果开发者的进程在启动完成之后需要有一些处理(如驱动初始化后再挂载设备),可以把这类操作放到该job执行。单个job最多支持30条命令(当前仅支持start/mkdir/chmod/chown/mount/loadcfg),命令名称和后面的参数(参数长度≤128字节)之间有且只能有一个空格。 | + + **表2** 命令集说明 + + | 命令 | 命令格式和示例 | 说明 | + | -------- | -------- | -------- | + | mkdir | mkdir 目标文件夹
如:mkdir /storage/myDirectory | 创建文件夹命令,mkdir和目标文件夹之间有且只能有一个空格。 | + | chmod | chmod 权限 目标
如:chmod 0600 /storage/myFile.txt
chmod 0750 /storage/myDir | 修改权限命令,chmod权限目标之间间隔有且仅有一个空格,权限必须为0xxx格式。 | + | chown | chown uid gid 目标
如:chown 900 800 /storage/myDir
chown 100 100 /storage/myFile.txt | 修改属组命令,chown uid gid目标之间间隔有且仅有一个空格。 | + | mount | mount fileSystemType src dst flags data
如:mount vfat /dev/mmcblk0 /sdc rw,umask=000
mount jffs2 /dev/mtdblock3 /storage nosuid | 挂载命令,各参数之间有且仅有一个空格。flags当前仅支持nodev、noexec、nosuid、rdonly,data为可选字段。 | + | start | start serviceName
如:start foundation
start shell | 启动服务命令,start后面跟着service名称,该service名称必须能够在services数组中找到。 | + | loadcfg | loadcfg filePath
如:loadcfg /patch/fstab.cfg | 加载其他cfg文件命令。后面跟着的目标文件大小不得超过50KB,且目前仅支持加载/patch/fstab.cfg,其他文件路径和文件名均不支持。/patch/fstab.cfg文件的每一行都是一条命令,命令类型和格式必须符合本表格描述,命令条数不得超过20条。 | + +2. 配置services数组,service集合(数组形式),包含了init进程需要启动的所有系统服务(最多支持100个)。 + + ``` + "services" : [{ + "name" : "service1", + "path" : ["/bin/process1", "param1", "param2"], + "uid" : 1, + "gid" : 1, + "once" : 0, + "importance" : 1, + "caps" : [0, 1, 2, 5], + "start-mode" : "condition", + "cpucore" : [0], + "critical" : [0, 5, 10], + "apl" : "normal", + "d-caps" : ["OHOS_DMS"] + "jobs" : { + "on-boot" : "boot", + "on-start" : "services:service1_start", + "on-stop" : "services:service1_stop", + "on-restart" : "services:service1_restart" + } + }, { + "name" : "service2", + "path" : "/bin/process2", + "uid" : 2, + "gid" : 2, + "once" : 1, + "importance" : 0, + "caps" : [ ], + "cpucore" : 0, + "critical" : [ ], + "apl" : "normal", + "d-caps" : [ ] + }] + ``` + + **表3** service字段说明 + + | 字段名 | 说明 | + | -------- | -------- | + | name | 当前服务的服务名,须确保非空且长度<=32字节。 | + | path | 当前服务的可执行文件全路径和参数,数组形式。须确保第一个数组元素为可执行文件路径、数组元素个数<=20、每个元素为字符串形式以及每个字符串长度<=64字节。 | + | uid | 当前服务进程的uid值。 | + | gid | 当前服务进程的gid值。 | + | once | 当前服务进程是否为一次性进程:
1:一次性进程,当该进程退出时,init不会重新启动该服务进程
0 : 常驻进程,当该进程退出时,init收到SIGCHLD信号并重新启动该服务进程;
注意,对于常驻进程,若在4分钟之内连续退出5次,第5次退出时init将不会再重新拉起该服务进程。 | + | importance | 标准系统中:服务进程优先级, 取值范围[-20, 19];小型系统中:0 : 非重要进程1 : 重要进程 | + | caps | 当前服务所需的capability值,根据安全子系统已支持的capability,评估所需的capability,遵循最小权限原则配置(当前最多可配置100个值)。 | + | critical | critical服务启动失败后, 需要M秒内重新拉起, 拉起失败N次后, 直接重启系统, N默认为4, M默认20。(仅标准系统以上提供 "critical" : [0, 2, 10]; 类型为int型数组)。
0:不使能;
1:使能。 | + | cpucore | 服务需要的绑定的cpu核心数, 类型为int型数组。 | + | d-caps | 分布式能力 (仅标准系统以上提供)。 | + | apl | 能力特权级别:system_core, normal, system_basic。 默认system_core (仅标准系统以上提供)。 | + | start-mode | 服务的启动模式,具体描述:init服务启动控制(仅标准系统以上提供)。 | + | jobs | 当前服务在不同阶段可以执行的job。具体说明可以看:init服务并行控制(仅标准系统以上提供)。 | + +3. 服务中socket配置和按需启动。 + 服务中支持配置 "socket" 属性,该属性以一个JSON对象的格式配置。配置有 "socket" 属性的服务,init将会为其创建socket,以是否为按需启动服务来区分其创建的时机。 + - 按需启动的服务,init会在解析到该服务时,根据解析到的socket配置进行创建。 + - 正常启动的服务,init会在拉起该服务时,执行服务可执行文件之前创建其配置的socket。 + + 无论服务是否按需启动,其真正被拉起后,都需要通过特定接口获取init为其创建的socket句柄,进而接手该socket的管理,成为服务自有的socket。 + 除以上socket的配置和创建流程,对于按需启动的服务,init还有不同行为。当init在创建根据服务的socket配置创建完socket后,将会判断服务的ondemand属性是否为true(按需启动服务),若是则会调用接口对socket进行轮询监听,直到socket有消息上报,此时将停止监听并拉起对应服务,由服务接管该socket并处理消息。 + + 下面以ueventd服务为例介绍服务中socket和按需启动的配置以及各字段的含义。 + ``` + "services" : [{ + "name" : "ueventd", + "path" : ["/system/bin/ueventd"], + "socket" : [{ + "name" : "ueventd", + "family" : "AF_NETLINK", + "type" : "SOCK_DGRAM", + "protocol" : "NETLINK_KOBJECT_UEVENT", + "permissions" : "0660", + "uid" : "system", + "gid" : "system", + "option" : [ + "SOCKET_OPTION_PASSCRED", + "SOCKET_OPTION_RCVBUFFORCE", + "SOCK_CLOEXEC", + "SOCK_NONBLOCK" + ] + }], + "critical" : [ 0, 15, 5], + "ondemand" : true, + "start-mode" : "condition" + }] + ``` + **表4**socket字段说明 + |字段名 | 说明 | + | -------- | -------- | + |name|当前socket的命名,不要求必须与服务同名,与服务名同样须满足非空且长度<=32字节。| + |family|socket所属的地址族,目前支持的为服务创建的socket有AF_UNIX和AF_NETLINK族。| + |type|socket的类型,目前支持的类型有基于连接的SOCK_SEQPACKET和SOCK_STREAM,还有基于UDP无连接的SOCK_DGRAM。| + |protocol|socket通信遵循的协议类型,在无特殊需求的情况下,该值可配置为default缺省值,因为socket接口会自动根据socket地址族和类型选择合适的协议。此处除了default,还支持了NETLINK_KOBJECT_UEVENT协议类型。| + |permissions|socket节点文件的权限。此项配置仅对如AF_UNIX地址族等有实体节点文件的socket类型有效。| + |uid|socket节点文件的用户ID。此项配置仅对如AF_UNIX地址族等有实体节点文件的socket类型有效。| + |gid|socket节点文件的组ID。此项配置仅对如AF_UNIX地址族等有实体节点文件的socket类型有效。| + |option|socket的可选配置。在调用setsockopt接口时传入设置,目前支持的option选项有SOCKET_OPTION_PASSCRED、SOCKET_OPTION_RCVBUFFORCE、SOCK_CLOEXEC和SOCK_NONBLOCK。| + + **表5** 接口介绍 + + | 函数名 | 函数解释 | 参数解释 | + | -------- | -------- | -------- | + | int \*ServiceGetFd(const char \*service
Name, size_t \*outfdCount) | 获取init代持的fd | 返回值:成功返回fd数组指针,失败返回NULL。备注:需手动释放
参数:
serviceName: 服务名
outfdCount: 返回的fd数组长度 | + | int ServiceSaveFd(const char \*service
Name, int \*fds, int fdCount) | 请求init代持fd | 返回值:成功返回0,失败返回-1
参数:
serviceName: 服务名
fds: 需要init代持的fd数组指针
fdCount: fd数组长度 | + | int ServiceControlWithExtra(const char \*
serviceName, int action, const char \*
extArgv[], int extArgc) | 配置服务参数 | 返回值:成功返回0,失败返回-1
参数:
serviceName: 服务名
action: 服务行为("start", "stop", "restart")
extArgv: 参数数组
extArgc: 参数个数 | + | int ServiceControl(const char \*serviceName,
 int action) | 控制服务行为 | 返回值:成功返回0,失败返回-1
参数:
serviceName: 服务名
action: 服务行为("start", "stop", "restart") | + + +## 开发实例 + +init启动引导程序,此处以要新增一个名为MySystemApp的系统服务为例进行说明,使用如下配置: -**表 1** 执行job介绍 - - - - - - - - - - - - - - -

job名

-

说明

-

pre-init

-

最先执行的job,如果开发者的进程在启动之前需要首先执行一些操作(例如创建文件夹),可以把操作放到pre-init中先执行。

-

init

-

中间执行的job,例如服务启动。

-

post-init

-

最后被执行的job,如果开发者的进程在启动完成之后需要有一些处理(如驱动初始化后再挂载设备),可以把这类操作放到该job执行。单个job最多支持30条命令(当前仅支持start/mkdir/chmod/chown/mount/loadcfg),命令名称和后面的参数(参数长度≤128字节)之间有且只能有一个空格。

-
- -**表 2** 命令集说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

命令

-

命令格式和示例

-

说明

-

mkdir

-

mkdir 目标文件夹

-

如:mkdir /storage/myDirectory

-

创建文件夹命令,mkdir和目标文件夹之间有且只能有一个空格。

-

chmod

-

chmod 权限 目标

-

如:chmod 0600 /storage/myFile.txt

-

chmod 0750 /storage/myDir

-

修改权限命令,chmod权限目标之间间隔有且仅有一个空格,权限必须为0xxx格式。

-

chown

-

chown uid gid 目标

-

如:chown 900 800 /storage/myDir

-

chown 100 100 /storage/myFile.txt

-

修改属组命令,chown uid gid目标之间间隔有且仅有一个空格。

-

mount

-

mount fileSystemType src dst flags data

-

如:mount vfat /dev/mmcblk0 /sdc rw,umask=000

-

mount jffs2 /dev/mtdblock3 /storage nosuid

-

挂载命令,各参数之间有且仅有一个空格。flags当前仅支持nodev、noexec、nosuid、rdonly,data为可选字段。

-

start

-

start serviceName

-

如:start foundation

-

start shell

-

启动服务命令,start后面跟着service名称,该service名称必须能够在services数组中找到。

-

loadcfg

-

loadcfg filePath

-

如:loadcfg /patch/fstab.cfg

-

加载其他cfg文件命令。后面跟着的目标文件大小不得超过50KB,且目前仅支持加载/patch/fstab.cfg,其他文件路径和文件名均不支持。/patch/fstab.cfg文件的每一行都是一条命令,命令类型和格式必须符合本表格描述,命令条数不得超过20条。

-
- - 2. 配置services数组,service集合(数组形式),包含了init进程需要启动的所有系统服务(最多支持100个)。 - -``` - "services" : [{ - "name" : "service1", - "path" : ["/bin/process1", "param1", "param2"], - "uid" : 1, - "gid" : 1, - "once" : 0, - "importance" : 1, - "caps" : [0, 1, 2, 5], - "start-mode" : "condition", - "cpucore" : [0], - "critical" : [0, 5, 10], - "apl" : "normal", - "d-caps" : ["OHOS_DMS"] - "jobs" : { - "on-boot" : "boot", - "on-start" : "services:service1_start", - "on-stop" : "services:service1_stop", - "on-restart" : "services:service1_restart" - } - }, { - "name" : "service2", - "path" : "/bin/process2", - "uid" : 2, - "gid" : 2, - "once" : 1, - "importance" : 0, - "caps" : [ ], - "cpucore" : 0, - "critical" : [ ], - "apl" : "normal", - "d-caps" : [ ] - }] -``` - -**表 3** service字段说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

字段名

-

说明

-

name

-

当前服务的服务名,须确保非空且长度<=32字节。

-

path

-

当前服务的可执行文件全路径和参数,数组形式。须确保第一个数组元素为可执行文件路径、数组元素个数<=20、每个元素为字符串形式以及每个字符串长度<=64字节。

-

uid

-

当前服务进程的uid值。

-

gid

-

当前服务进程的gid值。

-

once

-

当前服务进程是否为一次性进程:

-

1:一次性进程,当该进程退出时,init不会重新启动该服务进程

-

0 : 常驻进程,当该进程退出时,init收到SIGCHLD信号并重新启动该服务进程;

-

注意,对于常驻进程,若在4分钟之内连续退出5次,第5次退出时init将不会再重新拉起该服务进程。

-

importance

-

标准系统中:
服务进程优先级, 取值范围[-20, 19];
小型系统中:
0 : 非重要进程
1 : 重要进程

-

caps

-

当前服务所需的capability值,根据安全子系统已支持的capability,评估所需的capability,遵循最小权限原则配置(当前最多可配置100个值)。

-

critical

-

critical服务启动失败后, 需要M秒内重新拉起, 拉起失败N次后, 直接重启系统, N默认为4, M默认20。(仅标准系统以上提供 "critical" : [0, 2, 10]; 类型为int型数组)。

-

0:不使能;

-

1:使能。

-

cpucore

-

服务需要的绑定的cpu核心数, 类型为int型数组。

-

d-caps

-

分布式能力 (仅标准系统以上提供)。

-

apl

-

能力特权级别:system_core, normal, system_basic。 默认system_core (仅标准系统以上提供)。

-

start-mode

-

服务的启动模式,具体描述:init服务启动控制(仅标准系统以上提供)。

-

jobs

-

当前服务在不同阶段可以执行的job。具体说明可以看:init服务并行控制(仅标准系统以上提供)。

-
- - **表 4** 接口介绍 - - | 函数名 | 函数解释 |参数解释 | - | :---------- | :---------- |:--------| - | int *ServiceGetFd(const char *serviceName, size_t *outfdCount) | 获取init代持的fd | 返回值:成功返回fd数组指针,失败返回NULL。备注:需手动释放
参数:
serviceName: 服务名
outfdCount: 返回的fd数组长度 | - | int ServiceSaveFd(const char *serviceName, int *fds, int fdCount) | 请求init代持fd | 返回值:成功返回0,失败返回-1
参数:
serviceName: 服务名
fds: 需要init代持的fd数组指针
fdCount: fd数组长度 - | int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc) | 配置服务参数 | 返回值:成功返回0,失败返回-1
参数:
serviceName: 服务名
action: 服务行为("start", "stop", "restart")
extArgv: 参数数组
extArgc: 参数个数 - | int ServiceControl(const char *serviceName, int action) | 控制服务行为 | 返回值:成功返回0,失败返回-1
参数:
serviceName: 服务名
action: 服务行为("start", "stop", "restart") - -## 开发实例 - - init启动引导程序,此处以要新增一个名为MySystemApp的系统服务为例进行说明,使用如下配置: ``` { @@ -392,44 +295,60 @@ 完成配置后,编译出包烧写单板: -1. 启动后使用task -a(liteos-a版本)或ps命令(linux版本)查看是否MySystemApp系统服务进程已启动。 -2. 使用kill命令将上述新增的MySystemApp进程杀死,观察该进程是否会被重新拉起(此处应该为重新拉起)。 -3. 使用kill命令将上述新增的MySystemApp进程杀死,观察是否会导致单板重启(此处应该为不重启)。 +1. 启动后使用task -a(liteos-a版本)或ps命令(linux版本)查看是否MySystemApp系统服务进程已启动。 + +2. 使用kill命令将上述新增的MySystemApp进程杀死,观察该进程是否会被重新拉起(此处应该为重新拉起)。 + +3. 使用kill命令将上述新增的MySystemApp进程杀死,观察是否会导致单板重启(此处应该为不重启)。 + + +## 常见问题 + + +### 服务不存在 + +**现象描述** + +内核Log打印 "Failed get servName"。 + +**原因分析** + +kernel log 的输出,都是由init 打印。在init 中查找对应的代码位置。发现是服务不存在。 + +**解决方法** + +1. 确认服务是否在cfg中正确配置。 + +2. 服务的cfg文件是否正常加载。 + +3. cfg文件格式是否正确。 + + +### 请求其他服务代持fd,init有报错 -## 常见问题 +**现象描述** -### 服务不存在 +内核Log打印 "Service ' xxx '(pid = xxx) is not valid or request with unexpected process(pid = xxx)"。。 -   **现象描述**
-    内核Log打印 "Failed get servName"。 +**原因分析** -   **原因分析**
-     kernel log 的输出,都是由init 打印。在init 中查找对应的代码位置。发现是服务不存在。 +kernel log 的输出,都是由init 打印。在init 中查找对应的代码位置。发现是其他服务代持fd。 -   **解决方法**
-     1. 确认服务是否在cfg中正确配置。
-     2. 服务的cfg文件是否正常加载。
-     3. cfg文件格式是否正确。 +**解决方法** -### 请求其他服务代持fd,init有报错 +只支持代持本服务的fd, 不允许让其他服务代持fd。 -  **现象描述** -     内核Log打印 "Service \' xxx \'(pid = xxx) is not valid or request with unexpected process(pid = xxx)"。 +### 服务没有配置ondemand 选项 -   **原因分析**
-     kernel log 的输出,都是由init 打印。在init 中查找对应的代码位置。发现是其他服务代持fd。 +**现象描述** -   **解决方法**
-     只支持代持本服务的fd, 不允许让其他服务代持fd。 +内核Log打印 "service : %s had started already"。 -### 服务没有配置ondemand 选项 +**原因分析** -   **现象描述**
-     内核Log打印 "service : %s had started already"。 +kernel log 的输出,都是由init 打印。在init 中查找对应的代码位置。发现是服务没有配置ondemand。 -   **原因分析**
-     kernel log 的输出,都是由init 打印。在init 中查找对应的代码位置。发现是服务没有配置ondemand。 +**解决方法** -   **解决方法**
-     服务对应的.cfg文件正确配置如: "ondemand" : true。 \ No newline at end of file +服务对应的.cfg文件正确配置如: "ondemand" : true。 diff --git a/zh-cn/device-dev/subsystems/subsys-boot-overview.md b/zh-cn/device-dev/subsystems/subsys-boot-overview.md index d1602e8d6ab69ec3de160e5eaba0b6e2bf202b50..e65733dbe60ae3e77293d2917604e3372b696c06 100644 --- a/zh-cn/device-dev/subsystems/subsys-boot-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-overview.md @@ -1,89 +1,67 @@ -# 启动恢复子系统概述 +# 启动恢复子系统概述 -- [启动恢复子系统上下文](#section167378304212) -- [约束与限制](#section2029921310472) -## 启动恢复子系统上下文 +## 启动恢复子系统上下文 下图是启动子系统上下文结构图: -![](figure/启动子系统上下文.png) + **图1** 下图是启动子系统上下文结构图: + + ![zh-cn_image_0000001217858866](figures/zh-cn_image_0000001217858866.png) 系统上电加载内核后,按照以下流程完成系统各个服务和应用的启动: -1. 内核加载init进程,一般在bootloader启动内核时通过设置内核的cmdline来指定init的位置。 -2. init进程启动后,会挂载tmpfs,procfs,创建基本的dev设备节点,提供最基本的根文件系统。 -3. init也会启动ueventd监听内核热插拔设备事件,为这些设备创建dev设备节点;包括block设备各个分区设备都是通过此事件创建。 -4. init进程挂载block设备各个分区(system,vendor)后,开始扫描各个系统服务的init启动脚本,并拉起各个SA服务。 -5. samgr是各个SA的服务注册中心,每个SA启动时,都需要向samgr注册,每个SA会分配一个ID,应用可以通过该ID访问SA。 -6. foundation是一个特殊的SA服务进程,提供了用户程序管理框架及基础服务;由该进程负责应用的生命周期管理。 -7. 由于应用都需要加载JS的运行环境,涉及大量准备工作,因此appspawn作为应用的孵化器,在接收到foundation里的应用启动请求时,可以直接孵化出应用进程,减少应用启动时间。 +1. 内核加载init进程,一般在bootloader启动内核时通过设置内核的cmdline来指定init的位置。 -启动子系统内部涉及以下组件: +2. init进程启动后,会挂载tmpfs,procfs,创建基本的dev设备节点,提供最基本的根文件系统。 + +3. init也会启动ueventd监听内核热插拔设备事件,为这些设备创建dev设备节点;包括block设备各个分区设备都是通过此事件创建。 -- init启动引导组件 +4. init进程挂载block设备各个分区(system,vendor)后,开始扫描各个系统服务的init启动脚本,并拉起各个SA服务。 - init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见[init启动引导组件表2](subsys-boot-init.md#table122681439144112)描述)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。 +5. samgr是各个SA的服务注册中心,每个SA启动时,都需要向samgr注册,每个SA会分配一个ID,应用可以通过该ID访问SA。 -- ueventd启动引导组件 +6. foundation是一个特殊的SA服务进程,提供了用户程序管理框架及基础服务;由该进程负责应用的生命周期管理。 - ueventd负责监听内核设备驱动插拔的netlink事件,根据事件类型动态管理相应设备的dev节点。 +7. 由于应用都需要加载JS的运行环境,涉及大量准备工作,因此appspawn作为应用的孵化器,在接收到foundation里的应用启动请求时,可以直接孵化出应用进程,减少应用启动时间。 -- appspawn应用孵化组件 - 负责接收**用户程序框架**的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。 +启动子系统内部涉及以下组件: -- bootstrap服务启动组件 +- init启动引导组件 + init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见[第2章表2](../subsystems/subsys-boot-init.md)描述)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。 - 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。 +- ueventd启动引导组件 + ueventd负责监听内核设备驱动插拔的netlink事件,根据事件类型动态管理相应设备的dev节点。 -- syspara系统属性组件 +- appspawn应用孵化组件 + 负责接收**用户程序框架**的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。 - 系统属性组件,根据OpenHarmony产品兼容性规范提供获取设备信息的接口,如:产品名、品牌名、厂家名等,同时提供设置/读取系统属性的接口。 +- bootstrap服务启动组件 + 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用bootstrap标识的入口函数,并启动系统服务。 +- syspara系统属性组件 + 系统属性组件,根据OpenHarmony产品兼容性规范提供获取设备信息的接口,如:产品名、品牌名、厂家名等,同时提供设置/读取系统属性的接口。 -## 约束与限制 -启动恢复子系统源代码目录和适配平台: +## 约束与限制 -**表 1** 启动恢复子系统源代码目录和适配平台 + 启动恢复子系统源代码目录和适配平台: - - - - - - - - - - - - - - - - - - -

名称

-

适配平台

-

base/startup/appspawn_lite

-

小型系统设备(参考内存≥1MB),如Hi3516DV300 、Hi3518EV300

-

base/startup/bootstrap_lite

-

轻量系统设备(参考内存≥128KB),如Hi3861V100

-

base/startup/init_lite

-

小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300

-

base/startup/syspara_lite

-
  • 轻量系统设备(参考内存≥128KB),如Hi3861V100
  • 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300
-
+ **表1** 启动恢复子系统源代码目录和适配平台 -- init启动引导组件: - - 每个系统服务启动时都需要编写各自的启动脚本文件init.cfg,定义各自的服务名、可执行文件路径、权限和其他信息。 - - 每个系统服务各自安装其启动脚本到/system/etc/init目录下,init进程统一扫码执行。 +| 名称 | 适配平台 | +| -------- | -------- | +| base/startup/appspawn_lite | 小型系统设备(参考内存≥1MB),如Hi3516DV300 、Hi3518EV300 | +| base/startup/bootstrap_lite | 轻量系统设备(参考内存≥128KB),如Hi3861V100 | +| base/startup/init_lite | 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300 | +| base/startup/syspara_lite | - 轻量系统设备(参考内存≥128KB),如Hi3861V100
- 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300 | -- 新芯片平台移植时,平台相关的初始化配置需要增加平台相关的初始化配置文件/vendor/etc/init/init.\{hardware\}.cfg;该文件完成平台相关的初始化设置,如安装ko驱动,设置平台相关的/proc节点信息。 - - 配置文件init.cfg仅支持json格式。 +- init启动引导组件: + - 每个系统服务启动时都需要编写各自的启动脚本文件init.cfg,定义各自的服务名、可执行文件路径、权限和其他信息。 + - 每个系统服务各自安装其启动脚本到/system/etc/init目录下,init进程统一扫码执行。 -- bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。 +- 新芯片平台移植时,平台相关的初始化配置需要增加平台相关的初始化配置文件/vendor/etc/init/init.{hardware}.cfg;该文件完成平台相关的初始化设置,如安装ko驱动,设置平台相关的/proc节点信息。 + - 配置文件init.cfg仅支持json格式。 +- bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。 diff --git a/zh-cn/device-dev/subsystems/subsys-boot-ref.md b/zh-cn/device-dev/subsystems/subsys-boot-ref.md index 2b7c482cdc54a5a5d970ef5c541be2280c7c8460..0d66f28f6a4630721984de8cc73495674b0883ea 100755 --- a/zh-cn/device-dev/subsystems/subsys-boot-ref.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-ref.md @@ -1,40 +1,15 @@ -# 参考 +# 参考 -- [包结构说明](#section3523121414020) -## 包结构说明 +## 包结构说明 包结构见下表所示。 -**表 1** 包结构说明 - - - - - - - - - - - - - - - - - - - -

名称

-

对应功能描述

-

/bin/init

-

init启动引导程序对应的可执行文件

-

/bin/appspawn

-

appspawn应用孵化程序对应的可执行文件

-

/etc/init.cfg

-

init启动引导程序的配置文件

-

/usr/lib/libsysparam.so

-

syspara系统属性组件的输出文件

-
+ **表1** 包结构说明 +| **名称** | **对应功能描述** | +| -------- | -------- | +| /bin/init | init启动引导程序对应的可执行文件 | +| /bin/appspawn | appspawn应用孵化程序对应的可执行文件 | +| /etc/init.cfg | init启动引导程序的配置文件 | +| /usr/lib/libsysparam.so | syspara系统属性组件的输出文件 | diff --git a/zh-cn/device-dev/subsystems/subsys-boot-syspara.md b/zh-cn/device-dev/subsystems/subsys-boot-syspara.md index 62d799ef526a02b4d17aad57d40cf60e67e70f38..f5ce784775bd766dfa13e5f2d81d18b5a1117ef4 100755 --- a/zh-cn/device-dev/subsystems/subsys-boot-syspara.md +++ b/zh-cn/device-dev/subsystems/subsys-boot-syspara.md @@ -1,142 +1,59 @@ -# syspara系统属性组件 +# syspara系统属性组件 -- [系统参数简介](#section381564832813) -- [系统参数定义规则](#section431671411293) - - [系统参数值定义文件](#section885018321291) - - [系统参数DAC访问控制定义文件](#section1333155762915) - - [系统参数定义文件安装方法](#section43801513193014) - - [系统参数值定义文件的加载顺序](#section89971332173017) -- [shell命令使用说明](#section2039119283111) -- [syspara系统接口说明](#section0137175692616) -- [开发实例](#section118404913233) - -## 系统参数简介 +## 系统参数简介 syspara系统为各系统服务提供简单易用的键值对访问接口,使得各个系统服务可以通过各自的系统参数来进行业务功能的配置。系统参数的访问和操作有以下几个基本原语 -**图 1** 系统参数操作原语 -![](figure/系统参数操作原语.png "系统参数操作原语") - -**表 1** 系统参数操作原语说明 - - - - - - - - - - - - - - - - - - - -

功能

-

说明

-

get

-

获取系统参数的值

-

set

-

设置系统参数的值

-

wait

-

同步等待系统参数的值变更

-

watch

-

异步观察系统参数的值变更

-
+ **图1** 系统参数操作原语 + + ![zh-cn_image_0000001154900834](figures/zh-cn_image_0000001154900834.png) + + **表1** 系统参数操作原语说明 + +| 功能 | 说明 | +| -------- | -------- | +| get | 获取系统参数的值 | +| set | 设置系统参数的值 | +| wait | 同步等待系统参数的值变更 | +| watch | 异步观察系统参数的值变更 | 系统参数名称采用点分格式由多段组成,每一段由字母、数字、下划线组成,总长度不超过96字节;系统参数名称分为两类: -**表 2** 系统参数名称 - - - - - - - - - - - - - - - - - - - -

类别

-

名称

-

示例

-

说明

-

参数名称

-

Parameter Name

-

const.product.name

-

完整的系统参数名称,末尾不是"."。

-

参数目录

-

Parameter Directory

-

const.product.

-

以"."结尾,标识相同前缀的所有系统参数集合。

-
+ **表2** 系统参数名称 + +| 类别 | 名称 | 示例 | 说明 | +| -------- | -------- | -------- | -------- | +| 参数名称 | Parameter Name | const.product.**name** | 完整的系统参数名称,末尾不是"."。 | +| 参数目录 | Parameter Directory | const.product**.** | 以"."结尾,标识相同前缀的所有系统参数集合。 | 系统参数一共分为三大类: -**表 3** 系统参数分类 - - - - - - - - - - - - - - - - - - - - -

类别

-

前缀

-

说明

-

常量

-

const.

-

常量参数,一旦赋值后续不会再变更;值最大长度为4096字节(包括结束符)。

-

可写

-

其它

-

可写参数,重启后丢失,值最大长度96字节(包括结束符)。

-

可持久化

-

persist.

-

可写并可持久化保存参数,重启后不会丢失,值最大长度96字节(包括结束符)。

-
- -每个系统参数名称总体格式如下:\[**const**|**persist**\].**$sub\_system**.**$desc**。 - -$sub\_system为子系统或模块的名称。 + **表3** 系统参数分类 + +| 类别 | 前缀 | 说明 | +| -------- | -------- | -------- | +| 常量 | **const.** | 常量参数,一旦赋值后续不会再变更;值最大长度为4096字节(包括结束符)。 | +| 可写 | 其它 | 可写参数,重启后丢失,值最大长度96字节(包括结束符)。 | +| 可持久化 | **persist.** | 可写并可持久化保存参数,重启后不会丢失,值最大长度96字节(包括结束符)。 | + +每个系统参数名称总体格式如下:[**const**|**persist**].**$sub_system**.**$desc**。 + +$sub_system为子系统或模块的名称。 $desc为子系统或模块下参数的描述字符,可以为点分格式进行分级描述。 -## 系统参数定义规则 + +## 系统参数定义规则 每个子系统定义各自模块的系统参数,包括系统参数名称、默认值以及系统参数的权限访问信息。 -### 系统参数值定义文件 + +### 系统参数值定义文件 系统参数值定义文件后缀名为**".para"**,其格式示例如下: + ``` # This is comment const.product.name=OHOS-PRODUCT @@ -148,9 +65,10 @@ const.test.withblank=My Value 注意:系统参数值不支持注释及换行。 + ``` # 不支持 -const.test.withcomment=MyValue # This should be ommitted +const.test.withcomment=MyValue # This should be omitted # 不支持 const.test.multiline="This is a multiline parameter. Line2 value. @@ -159,45 +77,20 @@ Last line." 系统参数必须通过完整的系统参数命令来赋值,赋值方式分为三大类: -**表 4** 系统参数赋值方式 - - - - - - - - - - - - - - - - - - - - -

类别

-

示例

-

说明

-

字符串

-

const.product.name=OHOS-PRODUCT

-

不支持多行字符串,不支持注释。

-

数字

-

const.os.version.api=26

-

数字不需要引号。

-

布尔

-

const.telephony.enable=false

-

布尔型的可以为0,1,false,true。

-
- -### 系统参数DAC访问控制定义文件 + **表4** 系统参数赋值方式 + +| 类别 | 示例 | 说明 | +| -------- | -------- | -------- | +| 字符串 | const.product.name=OHOS-PRODUCT | 不支持多行字符串,不支持注释。 | +| 数字 | const.os.version.api=26 | 数字不需要引号。 | +| 布尔 | const.telephony.enable=false | 布尔型的可以为0,1,false,true。 | + + +### 系统参数DAC访问控制定义文件 当前系统参数的访问权限控制通过自主访问控制(**Discretionary Access Control**)方式管理,访问权限定义文件后缀名为**".para.dac"**,示例如下: + ``` const.product.="root:root:660" ``` @@ -206,13 +99,16 @@ const.product.="root:root:660" UGO规则信息每一位的定义如下: -**图 2** UGO规则信息 -![](figure/UGO规则信息.png "UGO规则信息") + **图2** UGO规则信息 + + ![zh-cn_image_0000001155060626](figures/zh-cn_image_0000001155060626.png) -### 系统参数定义文件安装方法 + +### 系统参数定义文件安装方法 .para和.para.dac文件都安装到/etc/param/目录下,GN脚本示例如下: + ``` ohos_prebuilt_etc("ohos.para") { source = "//base/startup/init_lite/services/etc/ohos.para" @@ -227,246 +123,77 @@ ohos_prebuilt_etc("ohos.para.dac") { } ``` -### 系统参数值定义文件的加载顺序 + +### 系统参数值定义文件的加载顺序 系统参数值的加载顺序如下: -**表 5** 系统参数加载顺序 - - - - - - - - - - - - - - - - - - - - - - - - -

类别

-

路径

-

说明

-

内核参数

-

/proc/cmdline

-

内核参数中ohospara.xxx=valXXX类型的参数都转换成ohos.boot.xxx=valXXX系统参数

-

OS固定值

-

/system/etc/param/ohos_const/*.para

-

OS固定系统参数值参数优先加载。

-

vendor参数值

-

/vendor/etc/param/*.para

-

厂商参数值定义文件次优先级加载,可以覆盖system参数值定义。

-

system参数值

-

/system/etc/param/*.para

-

最后加载system参数值定义文件,文件中的系统参数值如果已经存在,则忽略掉。

-
- -## shell命令使用说明 + **表5** 系统参数加载顺序 + +| 类别 | 路径 | 说明 | +| -------- | -------- | -------- | +| 内核参数 | /proc/cmdline | 内核参数中ohospara.xxx=valXXX类型的参数都转换成ohos.boot.xxx=valXXX系统参数 | +| OS固定值 | /system/etc/param/ohos_const/\*.para | OS固定系统参数值参数优先加载。 | +| vendor参数值 | /vendor/etc/param/\*.para | 厂商参数值定义文件次优先级加载,可以覆盖system参数值定义。 | +| system参数值 | /system/etc/param/\*.para | 最后加载system参数值定义文件,文件中的系统参数值如果已经存在,则忽略掉。 | + + +## shell命令使用说明 通过shell命令中可直接操作系统参数: -**表 6** 系统参数shell命令说明 - - - - - - - - - - - - - - - - - - - -

功能

-

说明

-

param get [key]

-

获取指定key名称的系统参数值;如果不指定任何name,则返回所有系统参数值。

-

param set key value

-

设置指定key名称的参数值为value

-

param wait key value

-

同步等待指定key名称的系统参数值与value匹配。value可支持模糊匹配,如"*"表示任何值,"val*"表示只匹配前三个val字符。

-

param dump

-

显示系统参数的统计信息。

-
- -## syspara系统接口说明 - -**表 7** 系统属性接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int GetParameter(const char* key, const char* def, char* value, unsigned int len)

-

获取系统参数。

-

int SetParameter(const char* key, const char* value)

-

设置/更新系统参数。

-

const char* GetDeviceType(void)

-

返回当前设备类型。

-

const char* GetManufacture(void)

-

返回当前设备生产厂家信息。

-

const char* GetBrand(void)

-

返回当前设备品牌信息。

-

const char* GetMarketName(void)

-

返回当前设备传播名。

-

const char* GetProductSeries(void)

-

返回当前设备产品系列名。

-

const char* GetProductModel(void)

-

返回当前设备认证型号。

-

const char* GetSoftwareModel(void)

-

返回当前设备内部软件子型号。

-

const char* GetHardwareModel(void)

-

返回当前设备硬件版本号。

-

const char* GetHardwareProfile(void)

-

返回当前设备硬件profile。

-

const char* GetSerial(void)

-

返回当前设备序列号(SN号)。

-

const char* GetOSFullName(void)

-

返回操作系统名。

-

const char* GetDisplayVersion(void)

-

返回当前设备用户可见的软件版本号。

-

const char* GetBootloaderVersion(void)

-

返回当前设备Bootloader版本号。

-

const char* GetSecurityPatchTag(void)

-

返回安全补丁标签。

-

const char* GetAbiList(void)

-

返回当前设备支持的指令集(Abi)列表。

-

int GetSdkApiVersion(void)

-

返回与当前系统软件匹配的SDK API 版本号。

-

int GetFirstApiVersion(void)

-

返回系统软件首版本SDK API 版本号。

-

const char* GetIncrementalVersion(void)

-

返回差异版本号。

-

const char* GetVersionId(void)

-

返回版本id。

-

const char* GetBuildType(void)

-

返回构建类型。

-

const char* GetBuildUser(void)

-

返回构建账户用户名。

-

const char* GetBuildHost(void)

-

返回构建主机名。

-

const char* GetBuildTime(void)

-

返回构建时间。

-

const char* GetBuildRootHash(void)

-

返回当前版本hash。

-

const char* GetOsReleaseType(void)

-

返回系统发布类型

-

int GetDevUdid(char *udid, int size)

-

获取设备udid

-
- -## 开发实例 + + **表6** 系统参数shell命令说明 + +| 功能 | 说明 | +| -------- | -------- | +| param get [**key**] | 获取指定key名称的系统参数值;如果不指定任何name,则返回所有系统参数值。 | +| param set **key value** | 设置指定key名称的参数值为value | +| param wait **keyvalue** | 同步等待指定key名称的系统参数值与value匹配。value可支持模糊匹配,如"\*"表示任何值,"val\*"表示只匹配前三个val字符。 | +| param dump | 显示系统参数的统计信息。 | + + +## syspara系统接口说明 + + **表7** 系统属性接口说明 + +| 接口名 | 描述 | +| -------- | -------- | +| int GetParameter(const char\* key, const char\* def, char\* value, unsigned int len) | 获取系统参数。 | +| int SetParameter(const char\* key, const char\* value) | 设置/更新系统参数。 | +| const char\* GetDeviceType(void) | 返回当前设备类型。 | +| const char\* GetManufacture(void) | 返回当前设备生产厂家信息。 | +| const char\* GetBrand(void) | 返回当前设备品牌信息。 | +| const char\* GetMarketName(void) | 返回当前设备传播名。 | +| const char\* GetProductSeries(void) | 返回当前设备产品系列名。 | +| const char\* GetProductModel(void) | 返回当前设备认证型号。 | +| const char\* GetSoftwareModel(void) | 返回当前设备内部软件子型号。 | +| const char\* GetHardwareModel(void) | 返回当前设备硬件版本号。 | +| const char\* GetHardwareProfile(void) | 返回当前设备硬件profile。 | +| const char\* GetSerial(void) | 返回当前设备序列号(SN号)。 | +| const char\* GetOSFullName(void) | 返回操作系统名。 | +| const char\* GetDisplayVersion(void) | 返回当前设备用户可见的软件版本号。 | +| const char\* GetBootloaderVersion(void) | 返回当前设备Bootloader版本号。 | +| const char\* GetSecurityPatchTag(void) | 返回安全补丁标签。 | +| const char\* GetAbiList(void) | 返回当前设备支持的指令集(Abi)列表。 | +| int GetSdkApiVersion(void) | 返回与当前系统软件匹配的SDK API 版本号。 | +| int GetFirstApiVersion(void) | 返回系统软件首版本SDK API 版本号。 | +| const char\* GetIncrementalVersion(void) | 返回差异版本号。 | +| const char\* GetVersionId(void) | 返回版本id。 | +| const char\* GetBuildType(void) | 返回构建类型。 | +| const char\* GetBuildUser(void) | 返回构建账户用户名。 | +| const char\* GetBuildHost(void) | 返回构建主机名。 | +| const char\* GetBuildTime(void) | 返回构建时间。 | +| const char\* GetBuildRootHash(void) | 返回当前版本hash。 | +| const char\* GetOsReleaseType(void) | 返回系统发布类型 | +| int GetDevUdid(char \*udid, int size) | 获取设备udid | + + +## 开发实例 系统属性使用实例 + ``` // set && get char key1[] = "rw.sys.version"; @@ -556,4 +283,3 @@ GetDevUdid(value26, 65); printf("device udid =%s\n", value26); free(value26); ``` - diff --git a/zh-cn/device-dev/subsystems/subsys-boot.md b/zh-cn/device-dev/subsystems/subsys-boot.md index a71c6ab86284f1d1dca602c5e7fffd2aae961f7f..b2302512738c6f1338f3455bf0a4d390eecb8667 100644 --- a/zh-cn/device-dev/subsystems/subsys-boot.md +++ b/zh-cn/device-dev/subsystems/subsys-boot.md @@ -1,17 +1,17 @@ -# 启动恢复 +# 启动恢复 -- **[启动恢复子系统概述](subsys-boot-overview.md)** -- **[init启动引导组件](subsys-boot-init.md)** -- **[appspawn应用孵化组件](subsys-boot-appspawn.md)** +- **[启动恢复子系统概述](subsys-boot-overview.md)** -- **[bootstrap服务启动组件](subsys-boot-bootstrap.md)** +- **[init启动引导组件](subsys-boot-init.md)** -- **[syspara系统属性组件](subsys-boot-syspara.md)** +- **[appspawn应用孵化组件](subsys-boot-appspawn.md)** -- **[常见问题](subsys-boot-faqs.md)** +- **[bootstrap服务启动组件](subsys-boot-bootstrap.md)** -- **[参考](subsys-boot-ref.md)** +- **[syspara系统属性组件](subsys-boot-syspara.md)** +- **[常见问题](subsys-boot-faqs.md)** +- **[参考](subsys-boot-ref.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guid.md b/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guid.md index c1d88f67c26811afaf4292b7fde1278eeea2b2ae..4c771af2b08831fd54c9bdc88c4456882d9b1622 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guid.md +++ b/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guid.md @@ -40,13 +40,13 @@ menuconfig kconfig ``` - ![界面示例](./figure/kconfig界面.PNG) + ![界面示例](figures/kconfig界面.PNG) 4. 参数填写 参数配置项可以参考:[productdefine/common/base/base_product.json](https://gitee.com/openharmony/productdefine_common/blob/master/base/base_product.json) - ![参数填写](./figure/kconfig参数输入.gif) + ![参数填写](figures/kconfig参数输入.gif) 5. 选择部件并配置 @@ -56,13 +56,13 @@ 3. 输入`feature`时,注意用英语逗号隔开多项输入。 - ![部件选择](./figure/kconfig部件选择.gif) + ![部件选择](figures/kconfig部件选择.gif) 6. 保存所选配置 按S键保存文件,可自定义输出文件名,默认为当前目录下`.config`文件。 - ![保存配置](./figure/kconfig保存.PNG) + ![保存配置](figures/kconfig保存.PNG) 7. 生成OpenHarmony Style配置文件 diff --git a/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md index a86c73bb21577c7c927d92baf37b5e5a2462cc66..b56624a23dba2bc4e208c88a80a2d07a4571722d 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md +++ b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md @@ -1,72 +1,43 @@ -# 轻量和小型系统编译构建指导 +# 轻量和小型系统编译构建指导 -- [概述](#section10958256161119) - - [基本概念](#section1732301411128) - - [目录结构](#section1588744014121) - - [构建流程](#section15761735134) -- [配置规则](#section2345183962710) - - [组件](#section142532518308) - - [芯片解决方案](#section121501451143710) - - [产品解决方案](#section134549283435) +## 概述 -- [使用指导](#section13754457192211) - - [前提条件](#section31651120233) - - [hb工具使用说明](#section1133304172313) - - [新增组件](#section167110415315) - - [新增芯片解决方案](#section1474718565412) - - [新增产品解决方案](#section1097623294220) + 一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: +- 支持按组件拼装产品并编译。 -- [常见问题](#section19909721104319) - - [编译构建过程中,提示“usr/sbin/ninja: invalid option -- w”](#section138233464318) - - [编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses”](#section151033911442) - - [编译构建过程中,提示“line 77: mcopy: command not found”](#section19811838104418) - - [编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”](#section03111118451) - - [编译构建过程中,提示“No module named 'Crypto'”](#section69981127125013) - - [编译构建过程中,提示“xx.sh : xx unexpected operator”](#section967617530505) +- 独立构建芯片解决方案厂商源码。 +- 独立构建单个组件。 -## 概述 -一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: - -- 支持按组件拼装产品并编译。 - -- 独立构建芯片解决方案厂商源码。 -- 独立构建单个组件。 - -### 基本概念 +### 基本概念 在使用编译构建子系统前,应了解如下基本概念: -- 子系统 - - 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 - - -- 组件 +- 子系统 + 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 - 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 +- 组件 + 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 -- gn +- gn + Generate ninja的缩写,用于产生ninja文件。 - Generate ninja的缩写,用于产生ninja文件。 +- ninja + ninja是一个专注于速度的小型构建系统。 -- ninja +- hb + OpenHarmony的命令行工具,用来执行编译命令。 - ninja是一个专注于速度的小型构建系统。 -- hb +### 目录结构 - OpenHarmony的命令行工具,用来执行编译命令。 - - -### 目录结构 ``` build/lite ├── components # 组件描述文件 -├── figure # readme中的图片 +├── figures # readme中的图片 ├── hb # hb pip安装包源码 ├── make_rootfs # 文件系统镜像制作脚本 ├── config # 编译配置项 @@ -78,31 +49,34 @@ build/lite └── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 ``` -### 构建流程 -编译构建流程如[图1 ](#fig9744112715161)所示,主要分设置和编译两步: +### 构建流程 + +编译构建流程如下图所示,主要分设置和编译两步: -**图 1** 编译构建流程 -![](figure/编译构建流程.jpg "编译构建流程") + **图1** 编译构建流程 + ![zh-cn_image_0000001171796557](figures/zh-cn_image_0000001171796557.jpg) -1. hb set: 设置OpenHarmony源码目录和要编译的产品。 -2. hb build: 编译产品、开发板或者组件。编译主要过程如下: - - 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 - - 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 - - 调用ninja:调用ninja -C out/board/product启动编译。 - - 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 +1. hb set: 设置OpenHarmony源码目录和要编译的产品。 +2. hb build: 编译产品、开发板或者组件。编译主要过程如下: + 1. 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 + 2. 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 + 3. 调用ninja:调用ninja -C out/board/product启动编译。 + 4. 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 -## 配置规则 + +## 配置规则 为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: -### 组件 -组件源码路径命名规则为:**\{领域\}/\{子系统\}/\{组件\}**,组件目录树规则如下: +### 组件 + + 组件源码路径命名规则为:**{领域}/{子系统}/{组件}**,组件目录树规则如下: +> ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** +> 组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 ->![](../public_sys-resources/icon-caution.gif) **注意:** ->组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 ``` component @@ -114,7 +88,7 @@ component └── BUILD.gn # 组件编译脚本 ``` -以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: + 以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: ``` { @@ -149,18 +123,17 @@ component } ``` -组件BUILD.gn的编写建议如下: + 组件BUILD.gn的编写建议如下: +- 编译目标名称与组件一致。 -- 编译目标名称与组件一致。 -- 组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos\_\{subsystem\}\_\{component\}\_\{feature\}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 -- 宏定义规则:OHOS\_\{SUBSYSTEM\}\_\{COMPONENT\}\_\{FEATURE\} +- 组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos_{subsystem}_{component}_{feature}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 - >![](../public_sys-resources/icon-note.gif) **说明:** - >组件的编译脚本语言为gn,gn的基本用法请见https://gn.googlesource.com/gn/+/master/docs/quick_start.md。 组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。 - - -以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: +- 宏定义规则:OHOS_{SUBSYSTEM}_{COMPONENT}_{FEATURE} + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 组件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。 + 以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: + ``` # 声明组件可配置的特性 declare_args() { @@ -206,13 +179,17 @@ component } ``` -### 芯片解决方案 -- 芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。 -- 芯片解决方案是一个特殊的组件,源码路径规则为:**device/\{芯片解决方案厂商\}/\{开发板\}**。 -- 芯片解决方案组件会随产品选择的开发板默认编译。 +### 芯片解决方案 + +- 芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。 + +- 芯片解决方案是一个特殊的组件,源码路径规则为:**device/{芯片解决方案厂商}/{开发板}**。 + +- 芯片解决方案组件会随产品选择的开发板默认编译。 -芯片解决方案目录树规则如下: + + 芯片解决方案目录树规则如下: ``` device @@ -226,10 +203,12 @@ device └── config.gni # liteos_a版本编译配置 ``` ->![](../public_sys-resources/icon-note.gif) **说明:** ->config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS组件,编译阶段系统全局可见。 -config.gni的关键字段介绍如下: +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS组件,编译阶段系统全局可见。 + + + config.gni的关键字段介绍如下: ``` kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 @@ -244,12 +223,14 @@ board_cxx_flags: 开发板配置的cpp文件编译选项。 board_ld_flags: 开发板配置的链接选项。 ``` -### 产品解决方案 -产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/\{产品解决方案厂商\}/\{产品名称\}**_。_产品解决方案也是一个特殊的组件。 +### 产品解决方案 + +产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/{产品解决方案厂商}/{产品名称}**_。_产品解决方案也是一个特殊的组件。 产品解决方案的目录树规则如下: + ``` vendor └── company # 产品解决方案厂商 @@ -264,169 +245,166 @@ vendor └── ...... ``` ->![](../public_sys-resources/icon-caution.gif) **注意:** ->**新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。** - -关键的目录和文件详细介绍如下: - -1. **vendor/company/product/init\_configs/etc** - - 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS-\>fstab-\>S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 - -2. **vendor/company/product/init\_configs/init.cfg** - - init进程启动服务的配置文件,当前支持解析的命令有: - - - start: 启动某个服务 - - mkdir: 创建文件夹 - - chmod: 修改指定路径/文件的权限 - - chown: 修改指定路径/文件的属组 - - mount: 挂载命令 - - 该文件中的各个字段的解释如下: - - ``` - { - "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 - "name" : "pre-init", - "cmds" : [ - "mkdir /storage/data", # 创建目录 - "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 - "mkdir /storage/data/log", - "chmod 0755 /storage/data/log", - "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid - ...... - "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] - # 其中flags仅支持:nodev、noexec、nosuid和rdonly - ] - }, { - "name" : "init", - "cmds" : [ # 按cmds数组顺序启动启动服务 - "start shell", # 注意:start与服务名称之间有且只有一个空格 - ...... - "start service1" - ] - }, { - "name" : "post-init", # 最后执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) - "cmds" : [] - } - ], - "services" : [{ # service数组,一个service对应一个进程 - "name" : "shell", # 服务名称 - "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 - "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 - "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 - "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 - "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 - "caps" : [4294967295] - }, - ...... - ] - } - ``` - -3. **vendor/company/product/init\_configs/hals** - - 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 - -4. **vendor/company/product/config.json** - - config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。 - - 以基于hispark\_taurus开发板的ipcamera产品为例,配置文件如下: - - ``` - { - "product_name": "ipcamera", # 产品名称 - "version": "3.0", # config.json的版本号, 固定"3.0" - "type": "small", # 系统类型, 可选[mini, small, standard] - "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 - "device_company": "hisilicon", # 芯片厂商 - "board": "hispark_taurus", # 开发板名称 - "kernel_type": "liteos_a", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "aafwk", # 选择的子系统 - "components": [ - { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 - ] - }, - { - ...... - } - ...... - 更多子系统和组件 - } - } - ``` - -5. **vendor/company/product/fs.yml** - - 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: - - ``` - fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs - fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 - source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 - target_dir: 必填,文件系统下对应文件目录 - ignore_files:选填,声明拷贝忽略文件 - dir_mode: 选填,文件目录权限,默认755 - file_mode: 选填,该文件目录下所有文件的权限,默认555 - fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 - file_dir: 必填,文件系统下具体文件路径 - file_mode: 必填,文件权限声明 - fs_symlink: 选填,配置文件系统软连接 - fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 - fs_attr: 选填,根据配置项动态调整文件系统 - ``` - - 其中fs\_symlink、fs\_make\_cmd字段支持以下变量: - - - $\{root\_path\} - - 代码根目录,对应gn的$\{ohos\_root\_path\} - - - $\{out\_path\} - - 产品out目录,对应gn的$\{root\_out\_dir\} - - - $\{fs\_dir\} - - 文件系统目录,由以下变量拼接而成 - - $\{root\_path\} - - $\{fs\_dir\_name\} +> ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** +> **新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。** - >![](../public_sys-resources/icon-note.gif) **说明:** - >fs.yml是可选的,对于没有文件系统的设备可不配置。 -6. **vendor/company/product/BUILD.gn** - - 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: - - ``` - group("product") { # target名称需与product名称即三级目录名称一致 - deps = [] - # 拷贝init配置 - deps += [ "init_configs" ] - # 其他 - ...... - } - ``` - - -## 使用指导 - -### 前提条件 +关键的目录和文件详细介绍如下: -开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建系统基础环境](../quick-start/quickstart-lite-env-setup.md)。 -### hb工具使用说明 +1. **vendor/company/product/init_configs/etc** + 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS->fstab->S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 + +2. **vendor/company/product/init_configs/init.cfg** + init进程启动服务的配置文件,当前支持解析的命令有: + + - start: 启动某个服务 + - mkdir: 创建文件夹 + - chmod: 修改指定路径/文件的权限 + - chown: 修改指定路径/文件的属组 + - mount: 挂载命令 + + 该文件中的各个字段的解释如下: + + ``` + { + "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 + "name" : "pre-init", + "cmds" : [ + "mkdir /storage/data", # 创建目录 + "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 + "mkdir /storage/data/log", + "chmod 0755 /storage/data/log", + "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid + ...... + "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] + # 其中flags仅支持:nodev、noexec、nosuid和rdonly + ] + }, { + "name" : "init", + "cmds" : [ # 按cmds数组顺序启动启动服务 + "start shell", # 注意:start与服务名称之间有且只有一个空格 + ...... + "start service1" + ] + }, { + "name" : "post-init", # 最后执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) + "cmds" : [] + } + ], + "services" : [{ # service数组,一个service对应一个进程 + "name" : "shell", # 服务名称 + "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 + "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 + "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 + "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 + "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 + "caps" : [4294967295] + }, + ...... + ] + } + ``` + +3. **vendor/company/product/init_configs/hals** + 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 + +4. **vendor/company/product/config.json** + config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。 + + 以基于hispark_taurus开发板的ipcamera产品为例,配置文件如下: + + + ``` + { + "product_name": "ipcamera", # 产品名称 + "version": "3.0", # config.json的版本号, 固定"3.0" + "type": "small", # 系统类型, 可选[mini, small, standard] + "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 + "device_company": "hisilicon", # 芯片厂商 + "board": "hispark_taurus", # 开发板名称 + "kernel_type": "liteos_a", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "aafwk", # 选择的子系统 + "components": [ + { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 + ] + }, + { + ...... + } + ...... + 更多子系统和组件 + } + } + ``` + +5. **vendor/company/product/fs.yml** + 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: + + + ``` + fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs + fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 + source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 + target_dir: 必填,文件系统下对应文件目录 + ignore_files:选填,声明拷贝忽略文件 + dir_mode: 选填,文件目录权限,默认755 + file_mode: 选填,该文件目录下所有文件的权限,默认555 + fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 + file_dir: 必填,文件系统下具体文件路径 + file_mode: 必填,文件权限声明 + fs_symlink: 选填,配置文件系统软连接 + fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 + fs_attr: 选填,根据配置项动态调整文件系统 + ``` + + 其中fs_symlink、fs_make_cmd字段支持以下变量: + - ${root_path} + 代码根目录,对应gn的${ohos_root_path} + + - ${out_path} + 产品out目录,对应gn的${root_out_dir} + + - ${fs_dir} + 文件系统目录,由以下变量拼接而成 + + - ${root_path} + - ${fs_dir_name} + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > fs.yml是可选的,对于没有文件系统的设备可不配置。 + +6. **vendor/company/product/BUILD.gn** + 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: + + + ``` + group("product") { # target名称需与product名称即三级目录名称一致 + deps = [] + # 拷贝init配置 + deps += [ "init_configs" ] + # 其他 + ...... + } + ``` + + +## 使用指导 + + +### 前提条件 + +开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建基础环境](../quick-start/quickstart-lite-env-setup.md)。 + +### hb工具使用说明 hb是OpenHarmony的命令行工具,用来执行编译命令。以下对hb的常用命令进行说明。 -**hb set** + **hb set** ``` hb set -h @@ -439,14 +417,17 @@ optional arguments: -p, --product Set OHOS board and kernel ``` -- hb set 后无参数,进入默认设置流程 -- hb set -root dir可直接设置代码根目录 -- hb set -p设置要编译的产品 +- hb set 后无参数,进入默认设置流程 + +- hb set -root dir可直接设置代码根目录 + +- hb set -p设置要编译的产品 **hb env** 查看当前设置信息 + ``` hb env [OHOS INFO] root path: xxx @@ -457,7 +438,7 @@ hb env [OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19 ``` -**hb build** + **hb build** ``` hb build -h @@ -481,7 +462,7 @@ optional arguments: --tee Enable tee -p PRODUCT, --product PRODUCT build a specified product with - {product_name}@{company}, eg: camera@huawei + {product_name}@{company}, eg: camera@example -f, --full full code compilation -n, --ndk compile ndk -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] @@ -500,15 +481,19 @@ optional arguments: Compile single target ``` -- hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. -- hb build \{component\_name\}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv\_store\)。 -- hb build -p ipcamera@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 -- 在device/device\_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 +- hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. + +- hb build {component_name}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv_store)。 + +- hb build -p ipcamera\@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 + +- 在device/device_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 **hb clean** 清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。 + ``` hb clean usage: hb clean [-h] [out_path] @@ -520,480 +505,456 @@ optional arguments: -h, --help show this help message and exit ``` -### 新增组件 + +### 新增组件 本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增: -1. 源码开发完成后,添加组件编译脚本。 +1. 源码开发完成后,添加组件编译脚本。 - 以编译组件hello\_world可执行文件为例,applications/sample/hello\_world/BUILD.gn可以写为: + 以编译组件hello_world可执行文件为例,applications/sample/hello_world/BUILD.gn可以写为: - ``` - executable("hello_world") { - include_dirs = [ - "include", - ] - sources = [ - "src/hello_world.c" + + ``` + executable("hello_world") { + include_dirs = [ + "include", ] - } - ``` - - 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello\_world的可执行文件。 - - 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: - - ``` - hb build -f -T //applications/sample/hello_world - ``` - - 组件在开发板上功能验证完成后,可按[步骤2\~4](#li11471037297)将组件配置到产品中。 - -2. 添加组件描述。 - - 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: - - - component:组件名称。 - - description:组件的一句话功能描述。 - - optional:组件是否为系统可选。 - - dirs:组件源码路径。 - - targets:组件编译入口。 - - 以将hello\_world组件加入应用子系统为例,在applications.json中添加hello\_world对象: - - ``` - { - "components": [ - { - "component": "hello_world", - "description": "Hello world.", - "optional": "true", - "dirs": [ - "applications/sample/hello_world" - ], - "targets": [ - "//applications/sample/hello_world" - ] - }, - ... + sources = [ + "src/hello_world.c" + ] + } + ``` + + 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello_world的可执行文件。 + + 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: + + + ``` + hb build -f -T //applications/sample/hello_world + ``` + + 组件在开发板上功能验证完成后,可按步骤2-4将组件配置到产品中。 + +2. 添加组件描述。 + + 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: + + - component:组件名称。 + - description:组件的一句话功能描述。 + - optional:组件是否为系统可选。 + - dirs:组件源码路径。 + - targets:组件编译入口。 + + 以将hello_world组件加入应用子系统为例,在applications.json中添加hello_world对象: + + + ``` + { + "components": [ + { + "component": "hello_world", + "description": "Hello world.", + "optional": "true", + "dirs": [ + "applications/sample/hello_world" + ], + "targets": [ + "//applications/sample/hello_world" + ] + }, + ... + ] + } + ``` + +3. 将组件配置到产品。 + + 产品的配置文件config.json位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello_world组件加入产品配置文件my_product.json中为例,加入hello_world对象: + + + ``` + { + "product_name": "hello_world_test", + "ohos_version": "OpenHarmony 1.0", + "device_company": "hisilicon", + "board": "hispark_taurus", + "kernel_type": "liteos_a", + "kernel_version": "1.0.0", + "subsystems": [ + { + "subsystem": "applications", + "components": [ + { "component": "hello_world", "features":[] } + ] + }, + ... ] - } - ``` + } + ``` -3. 将组件配置到产品。 +4. 编译产品。 + 1. 代码根目录输入hb set选择对应产品。 - 产品的配置文件config.json位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello\_world组件加入产品配置文件my\_product.json中为例,加入hello\_wolrd对象: + 2. 执行hb build。 - ``` - { - "product_name": "hello_world_test", - "ohos_version": "OpenHarmony 1.0", - "device_company": "hisilicon", - "board": "hispark_taurus", - "kernel_type": "liteos_a", - "kernel_version": "1.0.0", - "subsystems": [ - { - "subsystem": "applications", - "components": [ - { "component": "hello_world", "features":[] } - ] - }, - ... - ] - } - ``` - -4. 编译产品。 - - 1. 代码根目录输入hb set选择对应产品。 - - 2. 执行hb build。 - -### 新增芯片解决方案 +### 新增芯片解决方案 编译构建支持添加新的芯片解决方案厂商,具体步骤如下: -1. 创建芯片解决方案目录。 - - 按照[芯片解决方案配置规则](#section2345183962710)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: - - ``` - mkdir -p device/realtek/rtl8720 - ``` - -2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 - - 以realtek的“rtl8720“开发板的liteos\_a适配为例,device/realtek/rtl8720/liteos\_a/config.gni的内容如下: - - ``` - # Kernel type, e.g. "linux", "liteos_a", "liteos_m". - kernel_type = "liteos_a" - - # Kernel version. - kernel_version = "3.0.0" - - # Board CPU type, e.g. "cortex-a7", "riscv32". - board_cpu = "real-m300" - - # Board arch, e.g. "armv7-a", "rv32imac". - board_arch = "" - - # Toolchain name used for system compiling. - # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. - # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. - board_toolchain = "gcc-arm-none-eabi" - - # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. - board_toolchain_path = - rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", - root_build_dir) - - # Compiler prefix. - board_toolchain_prefix = "gcc-arm-none-eabi-" - - # Compiler type, "gcc" or "clang". - board_toolchain_type = "gcc" - - # Board related common compile flags. - board_cflags = [] - board_cxx_flags = [] - board_ld_flags = [] - ``` - -3. 编写编译脚本。 - - 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: - - ``` - group("rtl8720") { # target类型也可以shared_library, static_library, executable - # 具体内容 - ...... - } - ``` - -4. 编译芯片解决方案。 - - 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 - - -### 新增产品解决方案 +1. 创建芯片解决方案目录。 + 按照[芯片解决方案配置规则](#配置规则)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: + + + ``` + mkdir -p device/realtek/rtl8720 + ``` + +2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 + 以realtek的“rtl8720“开发板的liteos_a适配为例,device/realtek/rtl8720/liteo_a/config.gni的内容如下: + + ``` + # Kernel type, e.g. "linux", "liteos_a", "liteos_m". + kernel_type = "liteos_a" + + # Kernel version. + kernel_version = "3.0.0" + + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "real-m300" + + # Board arch, e.g. "armv7-a", "rv32imac". + board_arch = "" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "gcc-arm-none-eabi" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "gcc-arm-none-eabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [] + board_cxx_flags = [] + board_ld_flags = [] + ``` + +3. 编写编译脚本。 + 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: + + ``` + group("rtl8720") { # target类型也可以shared_library, static_library, executable + # 具体内容 + ...... + } + ``` + +4. 编译芯片解决方案。 + 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 + + +### 新增产品解决方案 编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: -1. 创建产品目录 - - 按照[产品解决方案配置规则](#section2345183962710)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: +1. 创建产品目录 + 按照[产品解决方案配置规则](#配置规则)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: + + + ``` + mkdir -p vendor/my_company/wifiiot + ``` + +2. 拼装产品 + 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my_company/wifiiot/config.json可以是: + + ``` + { + "product_name": "wifiiot", # 产品名称 + "version": "3.0", # config.json的版本号, 固定"3.0" + "type": "small", # 系统类型, 可选[mini, small, standard] + "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 + "device_company": "realtek", # 芯片解决方案厂商名称 + "board": "rtl8720", # 开发板名称 + "kernel_type": "liteos_m", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "kernel", # 选择的子系统 + "components": [ + { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 + ] + }, + ... + { + 更多子系统和组件 + } + ] + } + ``` + + 注意:编译构建系统编译前会对device_company,board,kernel_type,kernel_version、subsystem、component字段进行有效性检查,其中device_company,board,kernel_type,kernel_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 + +3. 适配OS接口 + 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 + +4. 配置系统服务 + 在产品目录下创建init_configs目录,并在init_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 + +5. 配置init进程(仅linux内核需要) + 在init_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 + +6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) + 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: + + ``` + - + fs_dir_name: rootfs # 镜像的名称 + fs_dirs: + - + # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin + source_dir: bin + target_dir: bin + ignore_files: + - Test.bin + - TestSuite.bin + - + # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 + source_dir: libs + target_dir: lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: usr/lib + target_dir: usr/lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: config + target_dir: etc + - + source_dir: system + target_dir: system + - + source_dir: sbin + target_dir: sbin + - + source_dir: usr/bin + target_dir: usr/bin + - + source_dir: usr/sbin + target_dir: usr/sbin + - + # 创建一个proc空目录 + target_dir: proc + - + target_dir: mnt + - + target_dir: opt + - + target_dir: tmp + - + target_dir: var + - + target_dir: sys + - + source_dir: etc + target_dir: etc + - + source_dir: vendor + target_dir: vendor + - + target_dir: storage + + fs_filemode: + - + file_dir: lib/ld-uClibc-0.9.33.2.so + file_mode: 555 + - + file_dir: lib/ld-2.24.so + file_mode: 555 + - + file_dir: etc/init.cfg + file_mode: 400 + fs_symlink: + - + # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so + source: libc.so + link_name: ${fs_dir}/lib/ld-musl-arm.so.1 + - + source: mksh + link_name: ${fs_dir}/bin/sh + - + source: mksh + link_name: ${fs_dir}/bin/shell + fs_make_cmd: + # 使用脚本将rootfs制作为ext4格式的image + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + - + fs_dir_name: userfs + fs_dirs: + - + source_dir: storage/etc + target_dir: etc + - + source_dir: data + target_dir: data + fs_make_cmd: + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + + ``` + +7. 配置产品Patch(可选,视产品涉及组件是否需要打补丁而定) + 在产品目录下创建patch.yml文件。patch.yml需按产品实际情况配置,一个典型的patch.yml文件如下: + + ``` + # 需要打patch的路径 + foundation/communication/dsoftbus: + # 该路径下需要打的patch存放路径 + - foundation/communication/dsoftbus/1.patch + - foundation/communication/dsoftbus/2.patch + third_party/wpa_supplicant: + - third_party/wpa_supplicant/1.patch + - third_party/wpa_supplicant/2.patch + - third_party/wpa_supplicant/3.patch + ... + ``` + + 配置完成后,编译时增加--patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译: + + ``` + hb build -f --patch + ``` + +8. 编写编译脚本 + 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: + + ``` + group("wifiiot") { # target名称与产品名一致 + deps = [] + # 拷贝init配置 + deps += [ "init_configs" ] + # 将hals加入编译 + deps += [ "hals" ] + # 其他 + ...... + } + ``` + +9. 编译产品。 + 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 + + +## 常见问题 + + +### 编译构建过程中,提示“usr/sbin/ninja: invalid option -- w” + +- **现象描述:** + 编译失败,提示“usr/sbin/ninja: invalid option -- w”。 + +- **可能原因:** + 编译环境中ninja版本太低,不支持--w选项。 + +- **解决办法:** + 卸载环境中ninja和gn,按照[获取工具](../get-code/gettools-ide.md)。 + + +### 编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses” + +- **现象描述:** + 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 + +- **可能原因:** + 编译环境ncurses库缺失。 + +- **解决办法:** + + ``` + sudo apt-get install lib32ncurses5-dev + ``` + + +### 编译构建过程中,提示“line 77: mcopy: command not found” + +- **现象描述:** + ​编译失败,提示“line 77: mcopy: command not found”。 + +- **可能原因:** + 编译环境未安装mcopy。 + +- **解决办法:** + + ``` + ​sudo apt-get install dosfstools mtools + ``` + - ``` - mkdir -p vendor/my_company/wifiiot - ``` +### 编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory” -2. 拼装产品 +- **现象描述:** + 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 - 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my\_company/wifiiot/config.json可以是: +- ​**可能原因:** + 当前用户对riscv编译器路径下的文件访问权限不够。 - ``` - { - "product_name": "wifiiot", # 产品名称 - "version": "3.0", # config.json的版本号, 固定"3.0" - "type": "small", # 系统类型, 可选[mini, small, standard] - "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 - "device_company": "realtek", # 芯片解决方案厂商名称 - "board": "rtl8720", # 开发板名称 - "kernel_type": "liteos_m", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "kernel", # 选择的子系统 - "components": [ - { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 - ] - }, - ... - { - 更多子系统和组件 - } - ] - } - ``` - - 注意:编译构建系统编译前会对device\_company,board,kernel\_type,kernel\_version、subsystem、component字段进行有效性检查,其中device\_company,board,kernel\_type,kernel\_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 - -3. 适配OS接口 - - 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 - -4. 配置系统服务 - - 在产品目录下创建init\_configs目录,并在init\_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 - -5. 配置init进程(仅linux内核需要) - - 在init\_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 - -6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) - - 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: - - ``` - - - fs_dir_name: rootfs # 镜像的名称 - fs_dirs: - - - # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin - source_dir: bin - target_dir: bin - ignore_files: - - Test.bin - - TestSuite.bin - - - # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 - source_dir: libs - target_dir: lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: usr/lib - target_dir: usr/lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: config - target_dir: etc - - - source_dir: system - target_dir: system - - - source_dir: sbin - target_dir: sbin - - - source_dir: usr/bin - target_dir: usr/bin - - - source_dir: usr/sbin - target_dir: usr/sbin - - - # 创建一个proc空目录 - target_dir: proc - - - target_dir: mnt - - - target_dir: opt - - - target_dir: tmp - - - target_dir: var - - - target_dir: sys - - - source_dir: etc - target_dir: etc - - - source_dir: vendor - target_dir: vendor - - - target_dir: storage - - fs_filemode: - - - file_dir: lib/ld-uClibc-0.9.33.2.so - file_mode: 555 - - - file_dir: lib/ld-2.24.so - file_mode: 555 - - - file_dir: etc/init.cfg - file_mode: 400 - fs_symlink: - - - # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so - source: libc.so - link_name: ${fs_dir}/lib/ld-musl-arm.so.1 - - - source: mksh - link_name: ${fs_dir}/bin/sh - - - source: mksh - link_name: ${fs_dir}/bin/shell - fs_make_cmd: - # 使用脚本将rootfs制作为ext4格式的image - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - - fs_dir_name: userfs - fs_dirs: - - - source_dir: storage/etc - target_dir: etc - - - source_dir: data - target_dir: data - fs_make_cmd: - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 +- ​**解决办法:** + 查询gcc_riscv32所在目录。 - ``` - -7. 配置产品Patch(可选,视产品涉及组件是否需要打补丁而定) - - 在产品目录下创建patch.yml文件。patch.yml需按产品实际情况配置,一个典型的patch.yml文件如下: - - ``` - # 需要打patch的路径 - foundation/communication/dsoftbus: - # 该路径下需要打的patch存放路径 - - foundation/communication/dsoftbus/1.patch - - foundation/communication/dsoftbus/2.patch - third_party/wpa_supplicant: - - third_party/wpa_supplicant/1.patch - - third_party/wpa_supplicant/2.patch - - third_party/wpa_supplicant/3.patch - ... - ``` - - 配置完成后,编译时增加--patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译: - - ``` - hb build -f --patch - ``` - -8. 编写编译脚本 - - 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: - - ``` - group("wifiiot") { # target名称与产品名一致 - deps = [] - # 拷贝init配置 - deps += [ "init_configs" ] - # 将hals加入编译 - deps += [ "hals" ] - # 其他 - ...... - } - ``` - -9. 编译产品。 - - 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 - - -## 常见问题 - -### 编译构建过程中,提示“usr/sbin/ninja: invalid option -- w” - -- **现象描述:** - - 编译失败,提示“usr/sbin/ninja: invalid option -- w”。 - -- **可能原因:** - - 编译环境中ninja版本太低,不支持--w选项。 - -- **解决办法:** - - 卸载环境中ninja和gn,按照[获取工具](../get-code/gettools-ide.md)。 - - -### 编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses” - -- **现象描述:** - - 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 - -- **可能原因:** - - 编译环境ncurses库缺失。 - -- **解决办法:** - - ``` - sudo apt-get install lib32ncurses5-dev - ``` - - -### 编译构建过程中,提示“line 77: mcopy: command not found” - -- **现象描述:** - - ​编译失败,提示“line 77: mcopy: command not found”。 - -- **可能原因:** - - 编译环境未安装mcopy。 - -- **解决办法:** - - ``` - ​sudo apt-get install dosfstools mtools - ``` - - -### 编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory” - -- **现象描述:** - - 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 - -- ​**可能原因:** - - 当前用户对riscv编译器路径下的文件访问权限不够。 - -- ​**解决办法:** - - 查询gcc\_riscv32所在目录。 - - ``` - which riscv32-unknown-elf-gcc - ``` - - 使用chmod命令修改目录权限为755。 - - -### 编译构建过程中,提示“No module named 'Crypto'” - -- **现象描述:** - - 编译失败,提示“No module named 'Crypto'”。 - -- **可能原因:** - - python3未安装Crypto。 - -- **解决办法:** - 1. 查询Python版本号。 - - ``` - python3 --version - ``` - - 2. 需使用python3.7以上版本,然后安装pycryptodome。 - - ``` - sudo pip3 install pycryptodome - ``` + ``` + which riscv32-unknown-elf-gcc + ``` + 使用chmod命令修改目录权限为755。 -### 编译构建过程中,提示“xx.sh : xx unexpected operator” +### 编译构建过程中,提示“No module named 'Crypto'” -- **现象描述:** +- **现象描述:** + 编译失败,提示“No module named 'Crypto'”。 - 编译失败:“xx.sh \[: xx unexpected operator”。 +- **可能原因:** + python3未安装Crypto。 -- **可能原因:** +- **解决办法:** + 1. 查询Python版本号。 + + ``` + python3 --version + ``` + 2. 需使用python3.7以上版本,然后安装pycryptodome。 + + ``` + sudo pip3 install pycryptodome + ``` - 编译环境shell不是bash。 -- **解决办法:** +### 编译构建过程中,提示“xx.sh : xx unexpected operator” - ``` - sudo rm -rf /bin/sh - sudo ln -s /bin/bash /bin/sh - ``` +- **现象描述:** + 编译失败:“xx.sh [: xx unexpected operator”。 +- **可能原因:** + 编译环境shell不是bash。 +- **解决办法:** + + ``` + sudo rm -rf /bin/sh + sudo ln -s /bin/bash /bin/sh + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md index cd1f3d3bf77492bc466b88f6b446edf0c9283444..9f55d1f71b9d3614cd20219130636880f742146f 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md +++ b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md @@ -1,74 +1,66 @@ -# 标准系统编译构建指导 +# 标准系统编译构建指导 -- [概述](#section17466112012244) - - [基本概念](#section445513507246) - - [运作机制](#section12541217142510) - - [约束与限制](#section886933762513) -- [编译构建使用指导](#section16901215262) - - [目录结构](#section109065332264) - - [编译命令](#section123265539266) - - [开发步骤](#section591084422719) - - -## 概述 +## 概述 编译构建子系统提供了一个基于gn和ninja的编译构建框架。主要提供以下功能: -- 构建不同芯片平台的产品。如:Hi3516DV300平台。 +- 构建不同芯片平台的产品。如:Hi3516DV300平台。 -- 根据产品配置,按照组件组装打包产品需要的能力。 +- 根据产品配置,按照组件组装并打包产品特性的能力。 -### 基本概念 -在了解编译构建子系统的能力前,应了解如下基本概念: +### 基本概念 -- 平台 +在了解编译构建子系统的能力前,应了解如下基本概念: - 开发板和内核的组合,不同平台支持的子系统和组件不同。 +- 平台 + 开发板和内核的组合,不同平台支持的子系统和组件不同。 -- 子系统 +- 子系统 + OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 - OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 +- 组件 + 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 -- 组件 +- gn + Generate ninja的缩写,用于产生ninja文件。 - 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 +- ninja + ninja是一个专注于速度的小型构建系统。 -- gn - Generate ninja的缩写,用于产生ninja文件。 +### 运作机制 -- ninja +OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: - ninja是一个专注于速度的小型构建系统。 +- 命令行解析:解析待编译的产品名称,加载相关配置。 +- 调用gn: 根据命令行解析的产品名称和编译类型,配置编译工具链和全局的编译选项。 -### 运作机制 +- 执行ninja:启动编译并生成对应的产品版本。 -OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: -- 命令行解析:解析待编译的产品名称,加载相关配置。 -- 调用gn: 根据命令行解析的产品名称和编译类型,配置编译工具链和全局的编译选项。 -- 执行ninja:启动编译并生成对应的产品版本。 +### 约束与限制 -### 约束与限制 +- 需按照[源码获取](../get-code/sourcecode-acquire.md)指导下载全量源码(采用方式三获取)。 -- 需按照[源码获取](../get-code/sourcecode-acquire.md)指导下载全量源码(采用方式三获取)。 -- 编译环境需要Ubuntu18.04及以上版本。 -- 安装编译所需的程序包。 +- 编译环境需要Ubuntu18.04及以上版本。 +- 安装编译所需的程序包。 安装命令: + + ``` + sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 + ``` - ``` - sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 - ``` +## 编译构建使用指导 -## 编译构建使用指导 -### 目录结构 +### 目录结构 + ``` /build # 编译构建主目录 ├── config # 编译相关的配置项 @@ -88,148 +80,547 @@ OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn └── toolchain # 编译工具链配置 ``` -### 编译命令 -- 代码根目录下执行全量版本的编译命令: +### 编译命令 - ``` - ./build.sh --product-name {product_name} - ``` +- 代码根目录下执行全量版本的编译命令: + + ``` + ./build.sh --product-name {product_name} + ``` - \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 + {product_name}为当前版本支持的平台。比如:Hi3516DV300等。 - 编译完成后,结果镜像保存在 out/{device_name}/packages/phone/images/ 目录下。 + 编译完成后,结果镜像保存在 out/{device_name}/packages/phone/images/ 目录下。 -- 编译命令支持选项: +- 编译命令支持选项: + + ``` + --product-name # 必须 编译的产品名称,如:Hi3516DV300 + --build-target # 可选 指定编译目标,可以指定多个 + --gn-args # 可选 gn参数,支持指定多个 + --ccache # 可选 编译使用ccache,需要本地安装ccache + ``` + + +### 开发步骤 + +1. 添加组件。 + 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 + + 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 + + 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem_examples子系统中(subsystem_examples子系统定义在test/examples/目录)。 + + 示例组件partA的完整目录结构如下: + + ``` + test/examples/partA + ├── feature1 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld1.h + │ └── src + │ └── helloworld1.cpp + ├── feature2 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld2.h + │ └── src + │ └── helloworld2.cpp + └── feature3 + ├── BUILD.gn + └── src + └── config.conf + ``` + + 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: + + ``` + config("helloworld_lib_config") { + include_dirs = [ "include" ] + } + + ohos_shared_library("helloworld_lib") { + sources = [ + "include/helloworld1.h", + "src/helloworld1.cpp", + ] + public_configs = [ ":helloworld_lib_config" ] + part_name = "partA" + } + ``` + + 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: + + + ``` + ohos_executable("helloworld_bin") { + sources = [ + "src/helloworld2.cpp" + ] + include_dirs = [ "include" ] + deps = [ # 依赖组件内模块 + "../feature1:helloworld_lib" + ] + external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” + install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 + part_name = "partA" + } + ``` - ``` - --product-name # 必须 编译的产品名称,如:Hi3516DV300 - --build-target # 可选 指定编译目标,可以指定多个 - --gn-args # 可选 gn参数,支持指定多个 - --ccache # 可选 编译使用ccache,需要本地安装ccache - ``` + 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: + + ``` + ohos_prebuilt_etc("feature3_etc") { + source = "src/config.conf" + relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 + part_name = "partA" + } + ``` + 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: -### 开发步骤 + + ``` + "partA": { + "module_list": [ + "//test/examples/partA/feature1:helloworld_lib", + "//test/examples/partA/feature2:helloworld_bin", + "//test/examples/partA/feature3:feature3_etc", + ], + "inner_kits": [ + + ], + "system_kits": [ + + ], + "test_list": [ + + ] + } + ``` -1. 添加组件。 + 一个组件包含module_list、inner_kits、system_kits、test_list四个部分的声明,其中: + - module_list:组件所包含的模块列表; + + - inner_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external_deps中添加依赖的模块; + + - system_kits:组件提供给开发者开发应用的接口; + + - test_list:组件中对应模块的测试用例; - 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 +2. 将组件添加到产品配置中。 + 在产品的配置中添加组件,产品对应的配置文件:productdefine/common/products/{product-name}.json。 - 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 + 在产品配置文件中添加 "subsystem_examples:partA",表示该产品中会编译并打包partA到版本中。 - 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem\_examples子系统中(subsystem\_examples子系统定义在test/examples/目录)。 +3. 编译。 + 以编译Hi3516DV300为例,编译命令如下: + + ``` + ./build.sh --product-name Hi3516DV300 --ccache + ``` - 示例组件partA的完整目录结构如下: +4. 编译输出。 + 编译所生成的文件都归档在out/hi3516dv300/目录下,结果镜像输出在 out/hi3516dv300/packages/phone/images/ 目录下。 - ``` - test/examples/partA - ├── feature1 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld1.h - │ └── src - │ └── helloworld1.cpp - ├── feature2 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld2.h - │ └── src - │ └── helloworld2.cpp - └── feature3 - ├── BUILD.gn - └── src - └── config.conf - ``` - 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: +## 常见问题 - ``` - config("helloworld_lib_config") { - include_dirs = [ "include" ] - } - - ohos_shared_library("helloworld_lib") { - sources = [ - "include/helloworld1.h", - "src/helloworld1.cpp", - ] - public_configs = [ ":helloworld_lib_config" ] - part_name = "partA" - } - ``` - - 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: - - ``` - ohos_executable("helloworld_bin") { - sources = [ - "src/helloworld2.cpp" - ] - include_dirs = [ "include" ] - deps = [ # 依赖组件内模块 - "../feature1:helloworld_lib" - ] - external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” - install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 - part_name = "partA" - } - ``` - 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: +### 如何将一个模块编译并打包到版本中? + +- 模块要指定part_name,指定它归属的部件,一个模块只能属于一个部件; + +- 部件的模块,要在部件配置的module_list中,或者可以被module_list中的模块依赖到; + +- 部件要加到对应产品的部件列表中。 + - ``` - ohos_prebuilt_etc("feature3_etc") { - source = "src/config.conf" - relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 - part_name = "partA" +### 关于deps、external_deps的使用 + +在添加一个模块的时候,需要在BUILD.gn中声明它的依赖,为了便于后续处理部件间依赖关系,我们将依赖分为两种——部件内依赖deps和部件间依赖external_deps。 + +**依赖分类:** + +部件内依赖: 现有模块module1属于部件part1,要添加一个属于部件part1的模块module2,module2依赖于module1,这种情况就属于部件内依赖。 + +部件间依赖: 现有模块module1属于部件part1,要添加一个模块module2,module2依赖于module1,module2属于部件part2。模块module2与模块module1分属于两个不同的部件,这种情况就属于部件间依赖。 + +部件内依赖使用deps,部件间依赖使用external_deps。 + +**示例:** + +部件内依赖示例: + + +``` +import("//build/ohos.gni") +ohos_shared_library("module1") { + …… + part_name = "part1" # 必选,所属部件名称 +} +``` + + +``` +import("//build/ohos.gni") +ohos_shared_library("module2") { + …… + deps = [ + "module1的gn target", + …… + ] # 部件内模块依赖 + part_name = "part1" # 必选,所属部件名称 +} +``` + +部件内依赖和一般的依赖一样 + +部件间依赖示例: + + +``` +import("//build/ohos.gni") +ohos_shared_library("module1") { + …… + part_name = "part1" # 必选,所属部件名称 +} +``` + +模块1所属部件的ohos.build文件 + + +``` +{ + "subsystem":"子系统名称", + "parts": { + "part1": { + "inner_kits": [ + { + "header": { + "header_base": "头文件所属目录", # 头文件所属目录 + "header_files": [ + "头文件名" + ] # 头文件名列表 + }, + "name": "module1的gn target" + }, + ], + …… } - ``` - - 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: - - ``` - "partA": { - "module_list": [ - "//test/examples/partA/feature1:helloworld_lib", - "//test/examples/partA/feature2:helloworld_bin", - "//test/examples/partA/feature3:feature3_etc", - ], - "inner_kits": [ - - ], - "system_kits": [ - - ], - "test_list": [ + } +} +``` + + +``` +import("//build/ohos.gni") +ohos_shared_library("module2") { + …… + external_deps = [ + "part1:module1", + …… + ] # 部件间模块依赖,这里依赖的模块必须是依赖的部件声明在inner_kits中的模块 + part_name = "part2" # 必选,所属部件名称 +} +``` + +> ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** +> 部件间依赖要写在external_deps里面,格式为”部件名:模块名"的形式,并且依赖的模块必须是依赖的部件声明在inner_kits中的模块。 + + +### 标准系统如何添加一个模块 + +要添加的模块可以分为以下三种情况,对原有的配置文件进行不同程度的修改。 + +- 在原有部件中添加一个模块 + +- 新建部件并在其中添加模块 + +- 新建子系统并在该子系统的部件下添加模块 + +**在原有部件中添加一个模块** + +1. 在模块目录下配置BUILD.gn,根据类型选择对应的模板。 + 这一步与在原有部件中添加一个模块的方法基本一致,只需注意该模块对应BUILD.gn文件中的part_name为新建部件的名称即可。 + +2. 修改或者新建ohos.build配置文件。 + + ``` + { + "subsystem": "子系统名", + "parts": { + "新建部件名": { + "module_list": [ + "部件包含模块的gn目标" + ], + "inner_kits": [ + ], + "test_list": [ + "测试用例", + ] + } + } + } + ``` + + 在原有子系统中添加一个新的部件,有两种方法,一种是在该子系统原有的ohos.build文件中添加该部件,另一种是新建一个ohos.build文件,注意无论哪种方式该ohos.build文件均在对应子系统所在文件夹下。 + + ohos.build文件包含两个部分,第一部分subsystem说明了子系统的名称,parts定义了该子系统包含的部件,要添加一个部件,需要把该部件对应的内容添加进parts中去。添加的时候需要指明该部件包含的模块module_list,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test_list中说明,inner_kits与test_list没有也可以不添加。 + +3. 在productdefine/common/products目录下的产品配置文件(json格式)中添加对应的部件,直接添加到原有部件后即可。 + + ``` + { + "parts":{ + "部件所属子系统名:部件名":{} + } + } + ``` + +**新建子系统并在该子系统的部件下添加模块** + +1. 在模块目录下配置BUILD.gn,根据类型选择对应的模板。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 + +2. 在新建的子系统目录下每个部件对应的文件夹下创建ohos.build文件,定义部件信息。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 + +3. 修改build目录下的subsystem_config.json文件。 + + ``` + { + "子系统名": { + "path": "子系统目录", + "name": "子系统名", + ... + } + } + ``` + + 该文件定义了有哪些子系统以及这些子系统所在文件夹路径,添加子系统时需要说明子系统path与name,分别表示子系统路径和子系统名。 + +4. 在productdefine/common/products目录下的产品配置如Hi3516DV300.json中添加对应的部件,直接添加到原有部件后即可。 + + ``` + { + ... + "parts":{ + "部件所属子系统名:部件名":{} + } + } + ``` + + 成功添加验证: + + - 在输出文件夹的对应子系统文件夹下的部件文件夹下的BUILD.gn文件中module_list包含了新建模块的BUILD.gn中定义的目标。 + - 编译完成后打包到image中去,生成对应的so文件或者二进制文件。 + +**配置文件说明** + +鸿蒙操作系统的配置文件主要有四个。 + +1. productdefine/common/products目录下的产品名.json文件。 + + ``` + { + "product_name": "Hi3516DV300", + "product_company": "hisilicon", + "product_device": "hi3516dv300", + "version": "2.0", + "type": "standard", + "parts":{ + "ace:ace_engine_standard":{}, + "ace:napi":{}, + "account:os_account_standard":{}, + "distributeddatamgr:native_appdatamgr":{}, + "distributeddatamgr:distributeddatamgr":{}, + "distributeddatamgr:appdatamgr_jskits":{}, + } + } + ``` + + 指明了产品名,产品厂商,产品设备,版本,要编译的系统类型,以及产品包含的部件。 + +2. build目录下的subsystem_config.json文件。 + + ``` + { + "ace": { + "project": "hmf/ace", + "path": "foundation/ace", + "name": "ace", + "dir": "foundation" + } + } + ``` + + 该文件对子系统进行了说明,我们需要该子系统定义中的name与path,分别表示子系统的名称和所在文件夹路径。 + +3. 子系统中ohos.build文件。 + + ``` + { + "subsystem": "ace", + "parts": { + "napi": { + "module_list": [ + "//foundation/ace/napi:napi_packages" + ], + "inner_kits": [ + ], + "test_list": [ + "//foundation/ace/napi:napi_packages_test", + "//foundation/ace/napi/test/unittest:unittest" + ] + } + } + } + ``` + + ohos.build文件定义了子系统包含的部件。 + + 每个部件定义它所包含的模块目标module_list,以及部件间交互的接口inner_kits,测试用例test_list。部件包含的模块目标module_list是必须要说明的。 + +4. 每个模块对应的BUILD.gn文件。 + 可以使用提供的模板,也可以使用gn语法规则自定义编写。 + + +### hap的编译 + +**hap包的构成** + +OpenHarmony上的hap包由资源,raw assets,js assets,native库,config.json等部分构成。 + +**编译系统提供的模板** + +编译系统提供了4个模板,用来编译hap包。 + +模板集成在ohos.gni中,使用之前需要引用build/ohos.gni + +ohos_resources + +- 声明一个资源目标。资源目标被restool编译之后会生成index文件,hap中会打包资源源文件和index文件。 + +- 该目标会同时生成资源编译后的ResourceTable.h,直接依赖该目标就可以引用该头文件 + +- 资源目标的目标名必须以"resources"或"resource"或"res"结尾,否则编译检查时会报错 + +- 支持的变量: + 1. sources: 资源的路径,变量类型是list,可以写多个路径 + 2. hap_profile: 编译资源时需要提供对应hap包的config.json + 3. deps: 当前目标的依赖,可选 + +ohos_assets + +- 声明一个资产目标 + +- 注意拼写:assets不是assert + +- assets目标的目标名必须以"assets"或"asset"结尾 + +- 支持的变量: + 1. sources:raw assets所在路径,变量类型是list,可以写多个路径 + 2. deps: 当前目标的依赖,可选 + +ohos_js_assets + +- 声明一个JS 资源目标,JS资源是L2 hap包的可执行部分 + +- JS assets目标的目标名必须以"assets"或"asset"结尾 + +- 支持的变量: + 1. source_dir: JS 资源的路径,变量类型是string,只能写一个 + 2. deps: 当前目标的依赖,可选 + +ohos_hap + +- 声明一个hap目标,该目标会生成一个hap包,最终将会打包到system镜像中 + +- 支持的变量: + 1. hap_profile: hap包的config.json + 2. deps: 当前目标的依赖 + 3. shared_libraries: 当前目标依赖的native库 + 4. hap_name: hap包的名字,可选,默认为目标名 + 5. final_hap_path: 用户可以制定生成的hap的位置,可选,final_hap_path中会覆盖hap_name + 6. subsystem_name: hap包从属的子系统名,需要和ohos.build中的名字对应,否则将导致无法安装到system镜像中 + 7. part_name: hap包从属的部件名,同subsystem_name + 8. js2abc: 是否需要将该hap包转换为ARK的字节码 + 签名篇见:[配置应用签名]( https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768) + 9. certificate_profile: hap对应的授权文件,用于签名 + 10. certificate_file: 证书文件,证书文件和授权文件,应用开发者需要去openharmony官网申请 + 11. keystore_path: keystore文件,用于签名 + 12. keystore_password: keystore的密码,用于签名 + 13. key_alias: key的别名 + 14. module_install_name:安装时的hap包名称 + 15. module_install_dir: 安装到system中的位置,默认安装在system/app目录下 + + **开发示例** + - ] - } - ``` + ``` + import("//build/ohos.gni") # 引用ohos.gni + ohos_hap("clock") { + hap_profile = "./src/main/config.json" # config.json + deps = [ + ":clock_js_assets", # JS assets + ":clock_resources", # 资源 + ] + shared_libraries = [ + "//third_party/libpng:libpng", # native库 + ] + certificate_profile = "../signature/systemui.p7b" # Cer文件 + hap_name = "SystemUI-NavigationBar" # 名字 + part_name = "prebuilt_hap" + subsystem_name = "applications" + } + ohos_js_assets("clock_js_assets") { + source_dir = "./src/main/js/default" + } + ohos_resources("clock_resources") { + sources = [ "./src/main/resources" ] + hap_profile = "./src/main/config.json" + } + ``` + + +### 开源软件Notice收集策略说明 + +**收集目标** + +只收集打包到镜像里面的模块对应的License;不打包的都不收集,比如构建过程使用的工具(如clang/python/ninja等)。 + +静态库本身是不会被打包的,一般是作为动态库或者可执行程序的一部分被打包到系统中的,为了确保完备,静态库的都会收集。 - 一个组件包含module\_list、inner\_kits、system\_kits、test\_list四个部分的声明,其中: +最终合并的Notice.txt要体现出镜像中每个文件都是用了哪些License,模块和License要有对应关系。 - - module\_list:组件所包含的模块列表; - - inner\_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external\_deps中添加依赖的模块; - - system\_kits:组件提供给开发者开发应用的接口; - - test\_list:组件中对应模块的测试用例; +最终合并的Notice.txt文件在/system/etc/ 目录下。 -2. 将组件添加到产品配置中。 +**收集规则** - 在产品的配置中添加组件,产品对应的配置文件:productdefine/common/products/\{product-name\}.json。 +按照优先级收集License - 在产品配置文件中添加 "subsystem\_examples:partA",表示该产品中会编译并打包partA到版本中。 +1. 模块在BUILD.gn中直接声明自己使用的License文件,优先级最高。如下图示例: + + ``` + ohos_shared_library("example") { + ... + license_file = "path-to-license-file" + ... + } + ``` -3. 编译。 +2. 如果模块没有显式声明,那么编译脚本会在BUILD.gn所在的当前目录中查找Readme.OpenSource文件,解析该文件,找出该文件中声明的license,将其作为模块的License。 + 如果Readme.OpenSource文件中配置的license文件不存在,直接报错。 - 以编译Hi3516DV300为例,编译命令如下: +3. 如果Readme.OpenSource文件不存在,编译脚本会从当前目录开始,向上层目录寻找(一直找到源码的根目录),默认查找License/Copyright/Notice三个文件,如果找到,则将其作为模块的License。 - ``` - ./build.sh --product-name Hi3516DV300 --ccache - ``` +4. 如果上面三种方式都未找到license,则使用默认的license作为该模块的license;默认license是Apache2.0 License。 -4. 编译输出。 +需要注意及检查的问题 - 编译所生成的文件都归档在out/hi3516dv300/目录下,结果镜像输出在 out/hi3516dv300/packages/phone/images/ 目录下。 +1. 三方的开源软件,比如openssl,icu等,这部分软件基本上在源码目录下都是要求配置Readme.OpenSource,要检查Readme.OpenSource文件是否和BUILD.gn文件在同一个目录,以及Reame.OpenSource文件中配置的License文件是否存在以及真是有效。 +2. 代码目录下,如果代码使用的不是Apache2.0 License,需要在目录下提供对应的License文件,或者直接在模块中指定license_file。 +3. 如果BUILD.gn中添加的源码文件不是当前目录的,需要检查下源码文件所在仓下的license是否和BUILD.gn文件所在仓的一致,不一致的需要处理。 diff --git a/zh-cn/device-dev/subsystems/subsys-build.md b/zh-cn/device-dev/subsystems/subsys-build.md index a202b701bd55e15d517638810a2a02cf12d39479..bf8667d708b2574196adf43deed137d685890312 100644 --- a/zh-cn/device-dev/subsystems/subsys-build.md +++ b/zh-cn/device-dev/subsystems/subsys-build.md @@ -1,9 +1,9 @@ -# 编译构建 +# 编译构建 -- **[轻量和小型系统编译构建指导](subsys-build-mini-lite.md)** -- **[标准系统编译构建指导](subsys-build-standard-large.md)** -- **[构建系统编码规范和最佳实践指导](subsys-build-gn-coding-style-and-best-practice.md)** -- **[编译构建Kconfig可视化配置指导](subsys-build-gn-kconfig-visual-config-guid.md)** +- **[轻量和小型系统编译构建指导](subsys-build-mini-lite.md)** +- **[标准系统编译构建指导](subsys-build-standard-large.md)** + +- **[构建系统编码规范与最佳实践](subsys-build-gn-coding-style-and-best-practice.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-data-relational-database-overview.md b/zh-cn/device-dev/subsystems/subsys-data-relational-database-overview.md index 7129f484a38e66078384c58878619e50c1587efc..90ef4efc82a04fd03a0083f9ecc92c54f3fec8f6 100644 --- a/zh-cn/device-dev/subsystems/subsys-data-relational-database-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-data-relational-database-overview.md @@ -25,7 +25,7 @@ OpenHarmony关系型数据库对外提供通用的操作接口(即Rdb Store接 **图1** 关系型数据库运作机制 -![](figure/zh-cn_image_0000001115980740.png) +![](figures/zh-cn_image_0000001115980740.png) ## 默认配置 - 如果不指定数据库的日志模式,那么系统默认日志方式是WAL(Write Ahead Log)模式。 diff --git a/zh-cn/device-dev/subsystems/subsys-data-storage-overview.md b/zh-cn/device-dev/subsystems/subsys-data-storage-overview.md index a4830a9c807017d7f106c9fcb61e546e52417bd1..67dfa96b86233202ae94f46c0492377fcd87ccb3 100755 --- a/zh-cn/device-dev/subsystems/subsys-data-storage-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-data-storage-overview.md @@ -21,7 +21,7 @@ **图 1** 轻量级数据存储运作机制 -![](figure/zh-cn_image_0000001192123772.png) +![](figures/zh-cn_image_0000001192123772.png) ## 约束与限制 diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-faultlogger.md b/zh-cn/device-dev/subsystems/subsys-dfx-faultlogger.md new file mode 100644 index 0000000000000000000000000000000000000000..444c3f35869ea204e409bf25d5ce1c148e8be1c3 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx-faultlogger.md @@ -0,0 +1,268 @@ +# Faultlogger开发指导 + + +## 概述 + + +### 功能简介 + +Faultlogger是OpenHarmony为开发者提供的一个维测日志框架,能够为应用、元能力、系统服务进程崩溃故障提供统一检测、日志采集、日志存储、日志上报功能,为应用崩溃故障提供详细的维测日志用以辅助故障定位。 + +FaultLogger承载OpenHarmony系统上的故障记录功能,按照服务对象不同分别运行在两个部件中: + +- Hiview部件中的服务:服务于应用层和native层的功能模块,功能是分类管理系统中发生的各类故障信息,并为模块提供查询故障的API。 + +- Faultloggerd部件中的服务:服务于崩溃进程,功能是收集C/C++运行时异常的守护进程和获取进程调用栈。 + +基于Faultlogger服务,进程崩溃的处理流程如下图所示: + + **图1** 进程崩溃处理流程图 + +![zh-cn_image_0000001261812333](figures/zh-cn_image_0000001261812333.png) + +1. 进程安装信号处理器后,通过DFX_SignalHandler函数检测并响应进程崩溃异常信号; + +2. SignalHandler检测到异常信号后Fork出子进程,并运行ProcessDump程序开始dump崩溃进程和线程的堆栈信息; + +3. ProcessDump程序在读取异常堆栈信息后将日志写入到Faultloggerd中的临时存储目录,进而生成完整的崩溃日志; + +4. Faultloggerd根据需要将故障通过Hiview提供的AddFaultLog()接口进行上报,hiview将处理生成简化的崩溃日志,并上报Hisysevent事件。 + +基于这样的设计,在资源有限的小型系统上可只部署Faultloggerd,也依然可以获取用于定位崩溃问题的日志。 + + +### 使用场景 + +Faultloggerd意在为开发者在开发测试过程中遇到的崩溃或卡死问题提供一种简单轻量的定位手段。 + +主要包含以下应用场景: + + **表1** Faultloggerd模块应用场景 + +| 场景描述 | 使用工具 | 使用方式 | +| -------- | -------- | -------- | +| 了解函数的调用顺序 | DumpCatcher API | 参见:[使用DumpCatcher获取调用栈](#使用dumpcatcher获取调用栈) | +| 应用卡死/CPU占用高 | ProcessDump | 参见:[使用ProcessDump获取调用栈](#使用processdump获取调用栈) | +| 进程未处理信号崩溃 | 崩溃日志和addr2line工具 | 参见:[基于崩溃日志对问题进行定位](#基于崩溃日志对问题进行定位) | + + +## 使用DumpCatcher获取调用栈 + + +### 接口说明 + +DumpCatcher可以抓取OpenHarmony指定进程(线程)的调用栈。 + + **表2** DumpCatcher接口说明 + +| 类 | 方法 | 描述 | +| -------- | -------- | -------- | +| DfxDumpCatcher | bool DumpCatch(const int pid, const int tid, std::string& msg) |   接口返回值:
- true:回栈成功,回栈信息存储在msg字符串对象中;
- false:回栈失败。
  输入参数:
- pid:目标进程号;
- tid:目标线程号,如果需要回栈进程中的所有线程,则tid设定为0;
  输出参数:
- msg:如果回栈成功,则通过msg返回调用栈信息。 | + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 当调用此接口的进程id与目标pid不一致时需要调用者是管理员(system,root)用户。当抓取非本用户组进程调用栈时还需具备读取对方/proc/pid/maps及ptrace到对方进程的权限。 + + +### 开发实例 + + +系统应用开发者可以用DumpCatcher在自己的应用中获取指定进程(线程)的调用栈。下文以dumpcatcherdemo模块使用DumpCatcher接口获取调用栈作为实例进行讲解。 + + +1. 编译构建文件添加dumpcatcher依赖:以/base/hiviewdfx/faultloggerd/example/BUILD.gn为例,在include_dirs中添加DfxDumpCatcher头文件路径,并在deps中添加“//base/hiviewdfx/faultloggerd/interfaces/innerkits/dump_catcher:lib_dfx_dump_catcher”模块依赖。 + + ``` + import("//base/hiviewdfx/faultloggerd/faultloggerd.gni") + import("//build/ohos.gni") + + config("dumpcatcherdemo_config") { + visibility = [ ":*" ] + + include_dirs = [ + ".", + "//utils/native/base/include", + "//base/hiviewdfx/faultloggerd/interfaces/innerkits/dump_catcher/include/", # 添加dumpcatcher头文件路径 + ] + } + + ohos_executable("dumpcatcherdemo") { sources = [ "dump_catcher_demo.cpp" ] configs = [ ":dumpcatcherdemo_config" ] deps = [ "//base/hiviewdfx/faultloggerd/interfaces/innerkits/dump_catcher:lib_dfx_dump_catcher", # 添加dumpcathcer模块依赖 "//utils/native/base:utils", ] external_deps = [ "hilog_native:libhilog" ] install_enable = true part_name = "faultloggerd" subsystem_name = "hiviewdfx" + } + ``` + +2. 头文件定义用到的函数:以/base/hiviewdfx/faultloggerd/example/dump_catcher_demo.h为例,本样例代码中,通过调用栈深度测试的测试函数来构造一个指定深度的调用栈。 + + ``` + #ifndef DUMP_CATCHER_DEMO_H + #define DUMP_CATCHER_DEMO_H + + #include + + #define NOINLINE __attribute__((noinline)) + + // 定义该宏函数用于自动生成函数调用链 + #define GEN_TEST_FUNCTION(FuncNumA, FuncNumB) \ + __attribute__((noinline)) int TestFunc##FuncNumA() \ + { \ + return TestFunc##FuncNumB(); \ + } + + // 调用栈深度测试的测试函数 + int TestFunc0(void); + int TestFunc1(void); + int TestFunc2(void); + int TestFunc3(void); + int TestFunc4(void); + int TestFunc5(void); + int TestFunc6(void); + int TestFunc7(void); + int TestFunc8(void); + int TestFunc9(void); + int TestFunc10(void); + + #endif // DUMP_CATCHER_DEMO_H + ``` + +3. 在源文件中调用DumpCatch接口:以/base/hiviewdfx/faultloggerd/example/dump_catcher_demo.cpp为例,引用dfx_dump_catcher.h头文件,声明DfxDumpCatcher对象,通过宏函数构造函数调用链,并最后调用DumpCatch接口方法,传入需要抓取调用栈的进程号、线程号。 + + ``` + #include "dump_catcher_demo.h" + + #include + #include + #include + // dfx_dump_catcher.h头文件引入 + #include "dfx_dump_catcher.h" + using namespace std; + + NOINLINE int TestFunc10(void) + { + OHOS::HiviewDFX::DfxDumpCatcher dumplog; + string msg = ""; + bool ret = dumplog.DumpCatch(getpid(), gettid(), msg); // 调用DumpCatch接口获取调用栈 + if (ret) { + cout << msg << endl; + } + return 0; + } + + // 通过宏函数自动生成函数调用链 + GEN_TEST_FUNCTION(0, 1) + GEN_TEST_FUNCTION(1, 2) + GEN_TEST_FUNCTION(2, 3) + GEN_TEST_FUNCTION(3, 4) + GEN_TEST_FUNCTION(4, 5) + GEN_TEST_FUNCTION(5, 6) + GEN_TEST_FUNCTION(6, 7) + GEN_TEST_FUNCTION(7, 8) + GEN_TEST_FUNCTION(8, 9) + GEN_TEST_FUNCTION(9, 10) + + int main(int argc, char *argv[]) + { + TestFunc0(); + return 0; + } + ``` + + +## 使用ProcessDump获取调用栈 + + +### 工具说明 + +ProcessDump是一个抓取调用栈的命令行工具,在OpenHarmony系统中可直接使用,该工具通过-p、-t参数指定进程和线程,命令执行后在命令行窗口打印指定进程的线程栈信息。 + + **表3** ProcessDump命令行工具使用说明 + +| 工具名称 | 命令行工具路径 | 执行命令 | 描述 | +| -------- | -------- | -------- | -------- | +| processdump | /system/bin | - processdump -p [pid]
- processdump -p [pid] -t [tid] | **参数说明:**
- -p [pid]:打印指定进程下面的所有线程栈信息。
- -p [pid] -t [tid]:打印指定进程下面的指定线程信息。
**返回值说明:**
如果栈信息解析成功,则将信息显示到标准输出;失败则打印错误信息。 | + + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 此工具需要在root下使用,或调用者有权限ptrace到目标进程,并读取目标进程的smaps。 + + +### 使用实例 + +通过processdump命令行工具打印hiview进程的调用栈。 + + +``` +# ps -A | grep hiview + 114 ? 00:00:00 hiview +# processdump -p 114 -t 114 +Tid:114, Name:hiview +#00 pc 0000000000089824(00000000b6f44824) /system/lib/ld-musl-arm.so.1(ioctl+68) +#01 pc 000000000002a709(00000000b6c56709) /system/lib/libipc_core.z.so(_ZN4OHOS15BinderConnector11WriteBinderEmPv+16) +#02 pc 000000000002ba75(00000000b6c57a75) /system/lib/libipc_core.z.so(_ZN4OHOS13BinderInvoker18TransactWithDriverEb+224) +#03 pc 000000000002bb37(00000000b6c57b37) /system/lib/libipc_core.z.so(_ZN4OHOS13BinderInvoker13StartWorkLoopEv+22) +#04 pc 000000000002c211(00000000b6c58211) /system/lib/libipc_core.z.so(_ZN4OHOS13BinderInvoker10JoinThreadEb+36) +#05 pc 0000000000038d07(00000000004bcd07) /system/bin/hiview(_ZNSt3__h6vectorINS_9sub_matchINS_11__wrap_iterIPKcEEEENS_9allocatorIS6_EEE8__appendEj+596) +#06 pc 0000000000028655(00000000004ac655) /system/bin/hiview +#07 pc 00000000000c2b08(00000000b6f7db08) /system/lib/ld-musl-arm.so.1(__libc_start_main+116) +#08 pc 00000000000285f4(00000000004ac5f4) /system/bin/hiview +#09 pc 0000000000028580(00000000004ac580) /system/bin/hiview +``` + + +## 基于崩溃日志对问题进行定位 + +开发者可以通过faultloggerd生成的崩溃堆栈日志进行问题定位。本章节将主要介绍如何利用addr2line工具进行崩溃问题定位。 + +1. 程序自崩溃或构造崩溃。 + 例如将如下代码植入自己的代码中,调用触发一个无效内存访问故障(SIGSEGV)。 + + + ``` + NOINLINE int TriggerSegmentFaultException() + { + printf("test TriggerSegmentFaultException \n"); + // 为构造崩溃,强制进行类型转换 + int *a = (int *)(&RaiseAbort); + *a = SIGSEGV; + return 0; + } + ``` + +2. 获取崩溃函数调用栈日志。 + 因为存在未处理的异常,进程会在 /data/log/faultlog/temp路径下生成临时的日志文件,其命名规则为: + + + ``` + cppcrash-pid-time + ``` + + 获取其生成的调用栈如下: + + + ``` + Pid:816 + Uid:0 + Process name:./crasher + Reason:Signal:SIGSEGV(SEGV_ACCERR)@0x0042d33d + Fault thread Info: + Tid:816, Name:crasher + r0:0042d33d r1:0000000b r2:1725d4c4 r3:b6f9fa84 + r4:bec97e69 r5:b6fc0268 r6:0042d661 r7:bec97d60 + r8:00000000 r9:00000000 r10:00000000 + fp:bec97d20 ip:00000020 sp:bec97cd0 lr:b6f9fae4 pc:0042d32c + + #00 pc 000000000000332c(000000000042d32c) /data/crasher(TriggerSegmentFaultException+15) + #01 pc 00000000000035c7(000000000042d5c7) /data/crasher(ParseAndDoCrash+277) + #02 pc 0000000000003689(000000000042d689) /data/crasher(main+39) + #03 pc 00000000000c3b08(00000000b6fbbb08) /system/lib/ld-musl-arm.so.1(__libc_start_main+116) + #04 pc 00000000000032f8(000000000042d2f8) /data/crasher(_start_c+112) + #05 pc 0000000000003284(000000000042d284) /data/crasher(_start+32) + ``` + +3. 利用addr2line工具进行调用栈分析。 + 使用addr2line工具根据偏移地址解析行号: + + + ``` + root:~/OpenHarmony/out/hi3516dv300/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -e crasher 000332c + base/hiviewdfx/faultloggerd/tools/crasher/dfx_crasher.c:57 + ``` + + 这个崩溃是由赋值给一块不可写的区域导致的,代码行为dfx_crasher.c文件的57行,修改后可以避免发生此崩溃。 diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hichecker.md b/zh-cn/device-dev/subsystems/subsys-dfx-hichecker.md new file mode 100644 index 0000000000000000000000000000000000000000..6c76bc9a0644905ddabe6635665062e4c978e868 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hichecker.md @@ -0,0 +1,112 @@ +# HiChecker开发指导 + + +## 概述 + +HiChecker是OpenHarmony提供的用于检测代码错误使用方式和运行结果的一种检测框架,可在应用和系统开发阶段用于运行时的缺陷扫描。 + +本章节内容对大型系统类设备(参考内存≥1GiB)、标准系统类设备(参考内存≥128MiB)适用。 + + +## 开发指导 + + +### 场景介绍 + +HiChecker的主要作用是给基于OpenHarmony的应用(包含系统和三方应用)开发者提供一套检测工具,用来检测应用程序开发过程中容易被人忽略的部分问题,包括应用关键线程调用耗时函数、应用进程中事件出现分发、执行超时以及应用进程中元能力资源泄露等,检测到的问题以日志记录或进程崩溃等形式展现出来以便开发者发现并修改相关问题。 + + +### 接口说明 + +HiChecker提供的主要接口及功能如下: + + **表1** HiChecker函数接口 + +| **类** | **方法(包括返回值、方法名、参数列表)** | **描述** | +| -------- | -------- | -------- | +| HiChecker | uint_64_t RULE_CAUTION_PRINT_LOG
= 1<<63; | 告警规则,当有告警时记录日志。 | +| uint_64_t RULE_CAUTION_TRIGGER_CRASH = 1<<62; | 告警规则,当有告警时让应用退出。 | +| uint_64_t RULE_THREAD_CHECK_SLOW_PROCESS = 1; | 检测规则,检测是否有耗时函数被调用。 | +| uint_64_t RULE_CHECK_SLOW_EVENT = 1<<32; | 检测规则,检测有事件分发或处理超过规定的时间阈值。 | +| uint_64_t RULE_CHECK_ABILITY_CONNECTION_LEAK = 1<<33; | 检测规则,检测ability泄露。 | +| AddRule(uint_64_t rule) : void | 添加一条或者多条规则到系统,系统根据添加的规则进行检测或反馈。 | +| RemoveRule(uint_64_t rule) : void | 删除一组规则,删除的规则后续将不再生效。 | +| GetRule() : uint_64_t | 获取当前线程规则、进程规则、告警规则的合集。 | +| Contains(uint_64_t rule) : bool | 当前已添加的规则集中是否包含了某一个特定的规则, 如果传入的rule是线程级别的rule,仅查询当前线程中是否包含。 | +| NotifySlowProcess(std::string tag) : void | 通知有慢处理,通知系统当前代码调用了耗时较长的慢处理流程,以告知应用重要线程中尽量避开直接调用。 | +| NotifySlowEvent(std::string tag) : void | 通知发生事件分发超时或执行超时。 | +| NotifyAbilityConnectionLeak(Caution caution) : void | 通知发生AbilityConnection泄露。 | +| Caution | GetTriggerRule() : uint_64_t | 获取触发当前告警的检测规则。 | +| GetCautionMsg() : std::string | 获取更多辅助信息。 | +| GetStackTrace() : std::string | 获取告警触发时的堆栈信息。 | + + +### 开发实例 + +C++使用示例 + +1. 在使用hichecker功能相关的代码文件中,包含hichecker头文件: + + ``` + #include "hichecker.h" + ``` + + 如果非DFX子系统,需要加上HiviewDFX域。 + + + ``` + using namespace OHOS::HiviewDFX; + ``` + + 通过静态调用使用相关接口。 + + + ``` + HiChecker::AddRule(Rule::RULE_THREAD_CHECK_SLOW_PROCESS); //添加一条规则 + HiChecker::AddRule(Rule::RULE_CHECK_SLOW_EVENT | Rule::RULE_CAUTION_PRINT_LOG); //添加多条规则 + HiChecker::Contains(Rule::RULE_CAUTION_PRINT_LOG); // true + HiChecker::GetRule(); //RULE_THREAD_CHECK_SLOW_PROCESS | RULE_CHECK_SLOW_EVENT | RULE_CAUTION_PRINT_LOG + ``` + + 当规则被触发时,根据添加的告警规则执行告警(默认为写日志)。 + + - RULE_CAUTION_PRINT_LOG + 日志输出触发告警的规则、线程ID、线程名、堆栈等信息。 + + - RULE_CAUTION_TRIGGER_CRASH + 进程直接退出,日志输出退出提示以及辅助信息。 + + 通知接口的使用: + + - NotifySlowProcess(std::string tag) + 通知系统当前代码调用了耗时较长的慢处理流程,入参示例: + + + ``` + “threadId:xx,threadName:xx,actualTime:xx,delayTime:xx“ + ``` + + - NotifySlowEvent(std::string tag) + 通知发生事件分发超时或执行超时,入参示例: + + + ``` + “threadId:xx,threadName:xx,eventName:xx,actualTime:xx,delayTime:xx“ + ``` + + - NotifyAbilityConnectionLeak(Caution caution) + 通知发生AbilityConnection泄露,入参示例:传入一个Caution实例。 + + + ``` + Caution caution(Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK , cautionMessage, stackTrace) + // cautionMessage与其它通知接口类似 + // stackTrace为发生泄露时的堆栈信息 + ``` + +2. 编译设置,在引入hichecker相关模块的BUILD.gn里增加子系统依赖: + + ``` + include_dirs = [ "//base/hiviewdfx/interfaces/innerkits/libhichecker/include" ] + external_deps = [ "hichecker_native:libhichecker" ] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hicollie.md b/zh-cn/device-dev/subsystems/subsys-dfx-hicollie.md index c81289a859e496debb4d69e4a2a7fe8a01ae2186..fa0a13a42b766da47c2071970e7613576099be21 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hicollie.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hicollie.md @@ -1,105 +1,30 @@ -# HiCollie开发指导 +# HiCollie开发指导 -- [概述](#section3432134085116) -- [接口说明](#section139261151145116) -- [效果](#section1589120102458) -- [开发实例](#section13905646534) - - [C++接口开发实例](#section9797199145316) - - [线程卡死监控](#section1734221332) - - [超时监控](#section2186947140) - -## 概述 +## 概述 HiCollie提供了软件看门狗功能。针对系统服务死锁、应用主线程阻塞,用户业务流程超时等故障,HiCollie提供了一套统一的用于故障检测和故障日志生成的框架,提供软件超时故障日志,辅助定位软件超时问题。 -## 接口说明 - -**表 1** C++接口功能描述表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

所属类

-

接口定义

-

描述

-

XCollieChecker类接口

-

virtual void CheckBlock()

-

接口功能:卡死检测回调函数。

-

输入参数:无。

-

输出参数:无。

-

返回值:无。

-

XCollieChecker类接口

-

virtual void CheckThreadBlock()

-

接口功能:线程卡死检测回调函数。

-

输入参数:无。

-

输出参数:无。

-

返回值:无。

-

XCollie类接口

-

void RegisterXCollieChecker(const sptr<XCollieChecker> &checker, unsigned int type)

-

接口功能:线程卡死检测回调函数注册。

-

输入参数:

-
  • checker:XCollieChecker实例指针。
  • type:卡死检测类型,取值设置为XCOLLIE_THREAD。
-

输出参数:无。

-

返回值:无。

-

XCollie类接口

-

int SetTimer(const std::string &name, unsigned int timeout, std::function<void (void *)> func, void *arg, unsigned int flag)

-

接口功能:添加定时器。

-

输入参数:

-
  • name:定时器名称。
  • timeout:超时时间,单位为秒。
  • func:超时回调函数。
  • arg:超时回调函数参数指针。
  • flag:定时器操作类型。

    XCOLLIE_FLAG_DEFAULT // 其他三个选项功能之和

    -

    XCOLLIE_FLAG_NOOP // 仅调用超时回调函数

    -

    XCOLLIE_FLAG_LOG // 生成超时故障日志

    -

    XCOLLIE_FLAG_RECOVERY // 进程退出

    -
-

输出参数:无。

-

返回值:成功返回定时器标识,失败返回-1。

-

XCollie类接口

-

bool UpdateTimer(int id, unsigned int timeout)

-

接口功能:更新定时器。

-

输入参数:

-
  • id:定时器标识。
  • timeout:超时时间,单位为秒。
-

输出参数:无。

-

返回值:成功返回true,失败返回false。

-

XCollie类接口

-

void CancelTimer(int id)

-

接口功能:取消定时器。

-

输入参数:定时器标识。

-

输出参数:无。

-

返回值:无。

-
- -## 效果 + +## 接口说明 + + **表1** C++接口功能描述表 + +| 所属类 | 接口定义 | 描述 | +| -------- | -------- | -------- | +| XCollieChecker类接口 | virtual void CheckBlock() | 接口功能:卡死检测回调函数。
输入参数:无。
输出参数:无。
返回值:无。 | +| XCollieChecker类接口 | virtual void CheckThreadBlock() | 接口功能:线程卡死检测回调函数。
输入参数:无。
输出参数:无。
返回值:无。 | +| XCollie类接口 | void RegisterXCollieChecker(const sptr&lt;XCollieChecker&gt; &checker, unsigned int type) | 接口功能:线程卡死检测回调函数注册。
输入参数:
- checker:XCollieChecker实例指针。
- type:卡死检测类型,取值设置为XCOLLIE_THREAD。
输出参数:无。
返回值:无。 | +| XCollie类接口 | int SetTimer(const std::string &name, unsigned int timeout, std::function&lt;void (void _)&gt; func, void _arg, unsigned int flag) | 接口功能:添加定时器。
输入参数:
- name:定时器名称。
- timeout:超时时间,单位为秒。
- func:超时回调函数。
- arg:超时回调函数参数指针。
- flag:定时器操作类型。
  XCOLLIE_FLAG_DEFAULT  // 其他三个选项功能之和
  XCOLLIE_FLAG_NOOP // 仅调用超时回调函数
  XCOLLIE_FLAG_LOG //  生成超时故障日志
  XCOLLIE_FLAG_RECOVERY //  进程退出
输出参数:无。
返回值:成功返回定时器标识,失败返回-1。 | +| XCollie类接口 | bool UpdateTimer(int id, unsigned int timeout) | 接口功能:更新定时器。
输入参数:
- id:定时器标识。
- timeout:超时时间,单位为秒。
输出参数:无。
返回值:成功返回true,失败返回false。 | +| XCollie类接口 | void CancelTimer(int id) | 接口功能:取消定时器。
输入参数:定时器标识。
输出参数:无。
返回值:无。 | + + +## 效果 日志打印: + ``` timeout: TimeoutTimer start at 1611040305 to check 1s ago @@ -114,80 +39,80 @@ ABI: 'arm64' #01 pc 00000000000174cc /data/test/XCollieTimeoutModuleTest ``` -## 开发实例 - -### C++接口开发实例 - -### 线程卡死监控 - -线程卡死监控功能需要开发者实现两个卡死检测回调函数,XCollieChecker类的CheckBlock和CheckThreadBlock接口函数。实现了该回调函数之后,开发者还需要通过XCollie类的RegisterXCollieChecker函数,将该回调函数的类实例成功注册。卡死监控线程会定时执行全部已成功注册的回调函数,检查线程逻辑完成标志位,判定已经成功注册的线程逻辑是否被卡死。 - -1. 源代码开发 - 包含头文件: +## 开发实例 - ``` - #include "xcollie.h" - ``` - 在业务代码中使用: +### C++接口开发实例 - ``` - void MyXCollieChecker::CheckLock() - { - /* time consuming job */ - } - - void MyXCollieChecker::CheckThreadBlock() - { - /* time consuming job */ - } - - sptr checker = new MyXCollieChecker("MyXCollieChecker"); - XCollie::GetInstance().RegisterXCollieChecker(checker, - (XCOLLIE_LOCK | XCOLLIE_THREAD)); - ...... - ``` -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: - - ``` - external_deps = [ "hiviewdfx:libxcollie" ] - ``` +### 线程卡死监控 +线程卡死监控功能需要开发者实现两个卡死检测回调函数,XCollieChecker类的CheckBlock和CheckThreadBlock接口函数。实现了该回调函数之后,开发者还需要通过XCollie类的RegisterXCollieChecker函数,将该回调函数的类实例成功注册。卡死监控线程会定时执行全部已成功注册的回调函数,检查线程逻辑完成标志位,判定已经成功注册的线程逻辑是否被卡死。 -### 超时监控 +1. 源代码开发 + 包含头文件: + + ``` + #include "xcollie.h" + ``` + + 在业务代码中使用: + + + ``` + void MyXCollieChecker::CheckLock() + { + /* time consuming job */ + } + + void MyXCollieChecker::CheckThreadBlock() + { + /* time consuming job */ + } + + sptr checker = new MyXCollieChecker("MyXCollieChecker"); + XCollie::GetInstance().RegisterXCollieChecker(checker, + (XCOLLIE_LOCK | XCOLLIE_THREAD)); + ...... + ``` + +2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + external_deps = [ "hiviewdfx:libxcollie" ] + ``` + + +### 超时监控 单个进程通过SetTimer接口函数添加定时器最多可以设置128个,超过上限则添加定时器操作会失败。 -1. 源代码开发 - - 包含头文件: - - ``` - #include "xcollie.h" - ``` - - 在业务代码中使用(添加/更新/取消): - - ``` - std::function callback = [](void *args) - { - /* dump helpful information */ - }; - - int id = XCollie::GetInstance().SetTimer("MyXCollieTimer", 10, callback ,nullptr, XCOLLIE_FLAG_LOG); - /* time consuming job */ - XCollie::GetInstance().UpdateTimer(id, 5); - /* time consuming job */ - XCollie::GetInstance().CancelTimer(id); - ...... - ``` - -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: - - ``` - external_deps = [ "hiviewdfx:libxcollie" ] - ``` - - +1. 源代码开发 + 包含头文件: + + ``` + #include "xcollie.h" + ``` + + 在业务代码中使用(添加/更新/取消): + + ``` + std::function callback = [](void *args) + { + /* dump helpful information */ + }; + + int id = XCollie::GetInstance().SetTimer("MyXCollieTimer", 10, callback ,nullptr, XCOLLIE_FLAG_LOG); + /* time consuming job */ + XCollie::GetInstance().UpdateTimer(id, 5); + /* time consuming job */ + XCollie::GetInstance().CancelTimer(id); + ...... + ``` + +2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + external_deps = [ "hiviewdfx:libxcollie" ] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hidumper.md b/zh-cn/device-dev/subsystems/subsys-dfx-hidumper.md new file mode 100644 index 0000000000000000000000000000000000000000..9e4a91ff9294a4dfd58117a1e976a0c7c39074ea --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hidumper.md @@ -0,0 +1,183 @@ +# HiDumper开发指导 + + +## 概述 + + +### 功能简介 + +HiDumper是OpenHarmony为开发、测试人员、IDE工具提供的系统信息获取工具,帮助开发者分析、定位问题。 + +本章节内容对大型系统类设备(参考内存≥1GiB)、标准系统类设备(参考内存≥128MiB)适用。 + + +### 源码目录说明 + + +``` +/base/hiviewdfx/hidumper +├── frameworks # 框架代码 +│ ├── native # 导出功能核心代码 +│ │ │── inlude # 头文件目录 +│ │ │── src # 源文件目录 +│ │ │── common # 通用功能代码 +│ │ │── executor # 导出过程执行器代码 +│ │ │── factory # 跟进导出项生成导出执行器 +│ │ │── manager # 导出管理核心代码 +│ │ │── util # 工具类源代码 +│── sa_profile # Hidumper sa属性文件 +│── services # Hidumper服务源码 +│ │── native # 服务C++源码 +│ │── zidl # 通讯功能源码目录 +│ │ │── include # 通讯功能头文件 +│ │ │── src # 通讯功能源代码 +├── test # 测试用例目录 +│ ├── unittest # 单元测试代码 +│ ├── moduletest # 模块级别测试代码 +``` + + +## 使用指导 + + +### 命令参数说明 + + **表1** HiDumper命令参数说明 + +| 选项 | **描述** | +| -------- | -------- | +| -h | 帮助信息 | +| -t [timeout] | 超时时间,单位:秒。默认值是30s。如果设置为0表示无超时限定。 | +| -lc | 系统信息簇列表 | +| -ls | 系统元能力列表 | +| -c | 导出系统簇信息 | +| -c [base system] | 以base或system标签区分的系统簇信息导出 | +| -s | 导出全部系统元能力信息 | +| -s [SA0 SA1] | 导出SA0、SA1等元能力id对应的元能力信息 | +| -s [SA] -a ['-h'] | 以-h为参数导出SA指定的系统元能力信息 | +| -e | 导出Faultlog模块生成的崩溃日志 | +| --net | 导出网络信息 | +| --storage | 导出存储信息 | +| -p | 导出进程列表及全部进程信息 | +| -p [pid] | 导出指定进程号的进程全部信息 | +| --cpuusage [pid] | 导出CPU使用信息;如果指定pid则导出该进程的CPU使用信息 | +| --cpufreq | 导出实际的CPU频率 | +| --mem [pid] | 导出内存使用信息;如果指定pid则导出该进程的内存使用信息 | +| --zip | 将导出信息压缩到固定文件夹下 | + + +### 使用实例 + +HiDumper可以为开发者导出系统当前基本信息,通过这些基本信息可以定位分析问题。给子服务和元能力传递复杂参数时,参数需要在双引号中。 + +具体步骤如下: + +1. 进入设备命令行,输入hidumper -h获取基本信息介绍,功能语法介绍。 + + ``` + hidumper -h + ``` + +2. 输入hidumper -lc获取系统信息分类列表。 + + ``` + hidumper -lc + ``` + +3. 输入hidumper -c获取系统base、system等所有分类信息。 + + ``` + hidumper -c + ``` + +4. 输入 hidumper -c [base | system] 按 base 或 system 分类获取系统簇信息 + + ``` + hidumper -c base + hidumper -c system + ``` + +5. 输入 hidumper -ls 命令获取系统中元能力列表 + + ``` + hidumper -ls + ``` + +6. 输入 hidumper -s 命令获取系统全部元能力信息 + + ``` + hidumper -s + ``` + +7. 运行 hidumper -s 3301 -a "-h" 命令获取id为3301的元能力的帮助 + + ``` + hidumper -s 3301 -a "-h" + ``` + +8. 运行 hidumper -s 3008命令获取id为3008的元能力的全部信息 + + ``` + hidumper -s 3008 + ``` + +9. 运行 hidumper -e 命令获取Faultlog模块生成的崩溃历史信息 + + ``` + hidumper -e + ``` + +10. 运行 hidumper --net 命令获取网络信息 + + ``` + hidumper --net + ``` + +11. 运行 hidumper --storage 命令获取存储相关信息 + + ``` + hidumper --storage + ``` + +12. 运行 hidumper -p 命令获取进程信息,包括进程、线程的列表和信息 + + ``` + hidumper -p + ``` + +13. 运行 hidumper -p 1024 命令获取pid为1024的进程信息 + + ``` + hidumper -p 1024 + ``` + +14. 运行 hidumper --cpuusage [pid] 命令获取CPU的使用信息;如果指定了进程的pid,则只获取该进程的CPU使用信息 + + ``` + hidumper --cpuusage + hidumper --cpuusage 1024 + ``` + +15. 运行 hidumper --cpufreq 命令获取每一个CPU核实际运行的频率 + + ``` + hidumper --cpufreq + ``` + +16. 运行 hidumper --mem [pid] 命令获取全部的内存使用信息;如果指定进程的pid,只获取该进程的内存使用情况 + + ``` + hidumper --mem [pid] + ``` + +17. 运行 hidumper --zip 命令压缩信息数据到/data/dumper目录下 + + ``` + hidumper --zip + ``` + +18. 运行 hidumper -t timeout 命令设置超时时间,单位:秒。默认值是30s。如果设置为0表示无超时限定。 + + ``` + hidumper -t [timeout] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md index ad09ffb51a01da5d07f78af250c187d671e06f0a..cefdcee926126e79d498e549114c36c5ef6a1a32 100755 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md @@ -1,108 +1,70 @@ -# HiLog\_Lite开发指导 +# HiLog_Lite开发指导 -- [概述](#section775017517390) -- [接口说明](#section114412157402) -- [开发实例](#section1482812550419) -## 概述 +## 概述 -HiLog\_Lite是针对轻量系统类设备(参考内存≥128KB)、小型系统类设备(参考内存≥1MB)的hilog框架,实现了日志的打印、输出和流控功能。 +HiLog_Lite是针对轻量系统类设备(参考内存≥128KiB)、小型系统类设备(参考内存≥1MiB)的hilog框架,实现了日志的打印、输出和流控功能。 -## 接口说明 + +## 接口说明 C语言接口: + ``` HILOG_DEBUG(mod, fmt, ...) HILOG_INFO/HILOG_WARN/HILOG_ERROR/HILOG_FATAL ``` -**表 1** 接口参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数名

-

是否必填

-

参数类型

-

参数说明

-

mod

-

-

uint8

-

模块/服务的ID。

-

统一规划分配,最大支持64个,其中第三方APP统一使用HILOG_MODULE_APP作为模块ID。

-

fmt

-

-

char *

-

格式化输出字符串。

-
  1. 最大支持6个可变参数,不支持%s。
  2. 格式化后的单条日志最大长度128字节,超过将无法打印。
-

可变参

-

-

int32

-

仅支持数字类型,最大支持6个变参。

-
- -## 开发实例 - -以下引用samgr\_lite模块使用hilog\_lite框架作为实例。 - -1. 添加模块ID,在“base/hiviewdfx/hilog\_lite/interfaces/native/kits/hilog\_lite/hiview\_log.h“的类型定义结构体中添加HILOG\_MODULE\_SAMGR定义。 - - ``` - typedef enum { - ... - HILOG_MODULE_SAMGR, - ... - } HiLogModuleType; - ``` - -2. 注册模块,在“base/hiviewdfx/hilog\_lite/frameworks/mini/hiview\_log.c“的HiLogInit函数中添加注册代码。 - - ``` - HiLogRegisterModule(HILOG_MODULE_SAMGR, "SAMGR"); - ``` - -3. 在GN文件中添加头文件依赖,文件路径为:“foundation/distributedschedule/samgr\_lite/samgr/BUILD.gn“ - - ``` - include_dirs = [ - "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite", - ] - ``` - -4. 源文件“foundation/distributedschedule/samgr\_lite/samgr/source/message.c“中引用头文件并调用接口。 - - ``` - #include - uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler) - { - ... - if (err != EC_SUCCESS) { - HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend [%p] failed(%d)!", identity->queueId, err); - (void)FreeReference(&exchange); - } - ... - } - ``` - - + + **表1** 接口参数说明 + +| 参数名 | 是否必填 | 参数类型 | 参数说明 | +| -------- | -------- | -------- | -------- | +| mod | 是 | uint8 | 模块/服务的ID。
统一规划分配,最大支持64个,其中第三方APP统一使用HILOG_MODULE_APP作为模块ID。 | +| fmt | 是 | char \* | 格式化输出字符串。
1. 最大支持6个可变参数,不支持%s。
2. 格式化后的单条日志最大长度128字节,超过将无法打印。 | +| 可变参 | 否 | int32 | 仅支持数字类型,最大支持6个变参。 | + + +## 开发实例 + +以下引用samgr_lite模块使用hilog_lite框架作为实例。 + +1. 添加模块ID,在“base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite/hiview_log.h“的类型定义结构体中添加HILOG_MODULE_SAMGR定义。 + + ``` + typedef enum { + ... + HILOG_MODULE_SAMGR, + ... + } HiLogModuleType; + ``` + +2. 注册模块,在“base/hiviewdfx/hilog_lite/frameworks/mini/hiview_log.c“的HiLogInit函数中添加注册代码。 + + ``` + HiLogRegisterModule(HILOG_MODULE_SAMGR, "SAMGR"); + ``` + +3. 在GN文件中添加头文件依赖,文件路径为:“foundation/distributedschedule/samgr_lite/samgr/BUILD.gn“ + + ``` + include_dirs = [ + "//base/hiviewdfx/hilog_lite/interfaces/native/kits/hilog_lite", + ] + ``` + +4. 源文件“foundation/distributedschedule/samgr_lite/samgr/source/message.c“中引用头文件并调用接口。 + + ``` + #include + uint32 *SAMGR_SendSharedRequest(const Identity *identity, const Request *request, uint32 *token, Handler handler) + { + ... + if (err != EC_SUCCESS) { + HILOG_ERROR(HILOG_MODULE_SAMGR, "SharedSend [%p] failed(%d)!", identity->queueId, err); + (void)FreeReference(&exchange); + } + ... + } + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md index 46cd76d4eb6f88abb64d4aae05ee46e8d5e35352..bf35fc643592c369128e5a20109ef0f8dae8d5fa 100755 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md @@ -1,19 +1,20 @@ # HiLog开发指导 + ## 概述 HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用打印日志,记录用户操作、系统运行状态等。 -本章节内容对标准系统类设备(参考内存≥128MB)适用。 +本章节内容对标准系统类设备(参考内存≥128MiB)适用。 ## 接口说明 -**表1** C++、C的函数接口 + **表1** C++、C的函数接口 -| **C++** | | **C** | +| C++ | | C | | -------- | -------- | -------- | -| **类** | **方法** | **方法/宏** | +| 类 | 方法 | 方法/宏 | | HiLog | int Debug(const HiLogLabel &label, const char \*fmt, ...) | HILOG_DEBUG(type, ...) | | | int Info(const HiLogLabel &label, const char \*fmt, ...) | HILOG_INFO(type, ...) | | | int Warn(const HiLogLabel &label, const char \*fmt, ...) | HILOG_WARN(type, ...) | @@ -21,11 +22,11 @@ HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用 | | int Fatal(const HiLogLabel &label, const char \*fmt, ...) | HILOG_FATAL(type, ...) | | | NA | int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char \*tag, const char \*fmt, ...) | | | boolean IsLoggable(unsigned int domain, const char \*tag, LogLevel level) | bool HiLogIsLoggable(unsigned int domain, const char \*tag, LogLevel level) | -| HiLogLabel | struct HiLogLabel | LOG_DOMAIN
LOG_TAG | +| HiLogLabel | struct HiLogLabel | LOG_DOMAIN
LOG_TAG | -**表3** C++接口说明函数参数和功能 + **表2** C++接口说明函数参数和功能 -| **类** | **方法** | **描述** | +| 类 | 方法 | 描述 | | -------- | -------- | -------- | | HiLog | int Debug(const HiLogLabel &label, const char \*fmt, ...) | 功能:输出 debug 级别日志。
输入参数:
- label:用于标识输出日志的类型、业务领域、TAG。
- format:常量格式字符串,包含参数类型、隐私标识。未加隐私标识的缺省为隐私参数。
- fmt:格式化变参描述字符串。
输出参数:无
返回值:大于等于0,成功;小于0,失败。 | | | int Info(const HiLogLabel &label, const char \*fmt, ...) | 功能:输出 info 级别日志。
参数说明同 Debug 接口。 | @@ -42,12 +43,13 @@ HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用 ### C使用示例 1. 在.c源文件中,包含hilog头文件: + ``` #include "hilog/log.h" ``` - 定义domain、tag: - + 定义domain、tag: + ``` #undef LOG_DOMAIN #undef LOG_TAG @@ -55,13 +57,14 @@ HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用 #define LOG_TAG "MY_TAG" ``` - 打印日志: - + 打印日志: + ``` HILOG_INFO(LOG_CORE, "Failed to visit %{private}s, reason:%{public}d.", url, errno); ``` 2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + ``` external_deps = [ "hilog_native:libhilog" ] ``` @@ -70,12 +73,13 @@ HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用 ### C++使用示例 1. 在.h类定义头文件中,包含hilog头文件: + ``` #include "hilog/log.h" ``` - 如果类头文件中需要日志打印,在头文件中类定义起始处 定义 LABEL: - + 如果类头文件中需要日志打印,在头文件中类定义起始处 定义 LABEL: + ``` class MyClass { static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "MY_TAG"}; @@ -83,20 +87,21 @@ HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用 } ``` - 如果类头文件中没有日志打印,在类实现文件中 定义 LABEL: - + 如果类头文件中没有日志打印,在类实现文件中 定义 LABEL: + ``` using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "MY_TAG"}; ``` - 打印日志: - + 打印日志: + ``` HiLog::Info(LABEL, "Failed to visit %{private}s, reason:%{public}d.", url, errno); ``` 2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + ``` external_deps = [ "hiviewdfx:libhilog" ] ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hilog-standard.md b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-standard.md deleted file mode 100644 index 85ab173619c45beccf89bf41b24fac8e4b0a8cfc..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hilog-standard.md +++ /dev/null @@ -1,229 +0,0 @@ -# HiLog开发指导 - -- [概述](#section8154107175019) -- [接口说明](#section6748124155012) -- [开发实例](#section102728581536) - - [C使用示例](#section12916224185417) - - [C++使用示例](#section19399185610547) - - -## 概述 - -HiLog是OpenHarmony日志系统,提供给系统框架、服务、以及应用打印日志,记录用户操作、系统运行状态等。 - -本章节内容对标准系统类设备(参考内存≥128MB)适用。 - -## 接口说明 - -**表 1** C++、C的函数接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

C++

-
  

C

-

-

方法

-

方法/宏

-

HiLog

-

int Debug(const HiLogLabel &label, const char *fmt, ...)

-

HILOG_DEBUG(type, ...)

-
  

int Info(const HiLogLabel &label, const char *fmt, ...)

-

HILOG_INFO(type, ...)

-
  

int Warn(const HiLogLabel &label, const char *fmt, ...)

-

HILOG_WARN(type, ...)

-
  

int Error(const HiLogLabel &label, const char *fmt, ...)

-

HILOG_ERROR(type, ...)

-
  

int Fatal(const HiLogLabel &label, const char *fmt, ...)

-

HILOG_FATAL(type, ...)

-
  

NA

-

int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...)

-
  

boolean IsLoggable(unsigned int domain, const char *tag, LogLevel level)

-

bool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level)

-

HiLogLabel

-

struct HiLogLabel

-

LOG_DOMAIN

-

LOG_TAG

-
- -**表 2** C++接口说明函数参数和功能 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-

方法

-

描述

-

HiLog

-

int Debug(const HiLogLabel &label, const char *fmt, ...)

-

功能:输出 debug 级别日志。

-

输入参数:

-
  • label:用于标识输出日志的类型、业务领域、TAG。
  • format:常量格式字符串,包含参数类型、隐私标识。未加隐私标识的缺省为隐私参数。
  • fmt:格式化变参描述字符串。
-

输出参数:无

-

返回值:大于等于0,成功;小于0,失败。

-
  

int Info(const HiLogLabel &label, const char *fmt, ...)

-

功能:输出 info 级别日志。

-

参数说明同 Debug 接口。

-
  

int Warn(const HiLogLabel &label, const char *fmt, ...)

-

功能:输出 warn 级别日志。

-

参数说明同 Debug 接口。

-
  

int Error(const HiLogLabel &label, const char *fmt, ...)

-

功能:输出 error 级别日志。

-

参数说明同 Debug 接口。

-
  

int Fatal(const HiLogLabel &label, const char *fmt, ...)

-

功能:输出 fatal 级别日志。

-

参数说明同 Debug 接口。

-
  

boolean IsLoggable(unsigned int domain, const char *tag, LogLevel level)

-

功能:检查指定业务领域、TAG、级别的日志是否可以打印。

-

输入参数:

-
  • domain:指定日志业务领域。
  • tag: 指定日志TAG。
  • level: 指定日志level。
-

输出参数:无

-

返回值:如果指定domain、tag、level日志可以打印则返回true;否则返回false。

-

HiLogLabel

-

struct HiLogLabel

-

功能:初始化日志标签参数。

-

成员参数:

-
  • domain:指定日志业务领域。
  • tag: 指定日志TAG。
  • level: 指定日志level。
-
- -## 开发实例 - -### C使用示例 - -1. 在.c源文件中,包含hilog头文件: - - ``` - #include "hilog/log.h" - ``` - - 定义domain、tag: - - ``` - #undef LOG_DOMAIN - #undef LOG_TAG - #define LOG_DOMAIN 0 // 标识业务领域,范围0x0~0xFFFFF - #define LOG_TAG "MY_TAG" - ``` - - 打印日志: - - ``` - HILOG_INFO(LOG_CORE, "Failed to visit %{private}s, reason:%{public}d.", url, errno); - ``` - -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: - - ``` - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - ``` - - -### C++使用示例 - -1. 在.h类定义头文件中,包含hilog头文件: - - ``` - #include "hilog/log.h" - ``` - - 如果类头文件中需要日志打印,在头文件中类定义起始处 定义 LABEL: - - ``` - class MyClass { - static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, "MY_TAG"}; - ...... - } - ``` - - 如果类头文件中没有日志打印,在类实现文件中 定义 LABEL: - - ``` - using namespace OHOS::HiviewDFX; - static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "MY_TAG"}; - ``` - - 打印日志: - - ``` - HiLog::Info(LABEL, "Failed to visit %{private}s, reason:%{public}d.", url, errno); - ``` - -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: - - ``` - external_deps = [ "hiviewdfx:libhilog" ] - ``` - - diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md index 81785b1a3c6568cb93307ad1aa99081eea395f59..9157101af654977c4645be895616333320b18f50 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md @@ -1,133 +1,128 @@ -# HiSysEvent订阅指导 +# HiSysEvent订阅 -- [概述](#section315316685112) - - [功能简介](#section123181433335224) - - [约束与限制](#section123181433375224) -- [开发指导](#section315316685113) - - [接口说明](#section0342191810519) - - [开发实例](#section123181432175110) -## 概述 +## 概述 -### 功能简介 -HiSysEvent提供了跨进程订阅机制,开发者可以通过注册订阅接口实时获取关注的事件,例如电池模块侦听功耗相关的事件,用于分析耗电情况。 - -### 约束与限制 - -**HiSysEvent事件订阅条件约束:** - -- 在订阅HiSysEvent事件之前,需要先完成HiSysEvent打点配置,具体配置方法请参考[《HiSysEvent打点配置指导》](subsys-dfx-hisysevent-logging-config.md)。 - -## 开发指导 - -### 接口说明 - -**表 1** HiSysEvent订阅接口 - -| 接口名称 | 描述 | -| -------- | --------- | -|bool HiSysEventManager::AddEventListener(std::shared_ptr<HiSysEventSubscribeCallBack> listener, std::vector<ListenerRule>& rules)|接口功能:注册订阅HiSysEvent系统事件侦听对象,可设置规则订阅某些事件。

输入参数:
  • listener:订阅回调对象。
  • rules:事件订阅规则。
返回值:
  • 0:订阅成功,重复订阅。
  • 1:订阅成功,初次订阅。
  • 其他值:订阅失败。
| -|bool HiSysEventManager::RemoveListener(std::shared_ptr<HiSysEventSubscribeCallBack> listener)|接口功能:移除订阅hisysevent系统事件侦听对象。

输入参数:
  • listener:订阅回调对象。
返回值:
  无。| - -**表 2** ListenerRule订阅规则对象 - -| 接口名称 | 描述 | -| -------- | --------- | -|ListenerRule(const std::string& tag, RuleType ruleType = RuleType::WHOLE_WORD)|接口功能:订阅规则构造函数,创建事件标签订阅规则对象。

输入参数:
  • tag:订阅规则的HisysEvent事件标签,字符串类型,最大长度16个字符(含),有效字符包含大小写字母及数字。
  • ruleType:订阅规则的规则类型,RuleType枚举类型(参考表3)。
| -|ListenerRule(const std::string& domain, const std::string& eventName, RuleType ruleType = RuleType::WHOLE_WORD)|接口功能:订阅规则构造函数,创建事件领域与事件名称订阅规则对象。

输入参数:
  • domain:订阅规则的HisysEvent事件领域,字符串类型,最大长度16个字符(含),有效字符包含大写字母、数字及下划线。
  • eventName:订阅规则的HisysEvent事件名称,字符串类型,最大长度32个字符(含),有效字符包含大写字母、数字及下划线。
  • ruleType:订阅规则的规则类型,RuleType枚举类型(参考表3)。
| -|ListenerRule(const std::string& domain, const std::string& eventName, const std::string& tag, RuleType ruleType = RuleType::WHOLE_WORD)|接口功能:订阅规则构造函数,创建事件领域、事件名称,事件标签订阅规则对象。

输入参数:
  • tag:订阅规则的HisysEvent事件标签,字符串类型,最大长度16个字符(含),有效字符包含大小写字母及数字。
  • domain:订阅规则的HisysEvent事件领域,字符串类型,最大长度16个字符(含),有效字符包含大写字母、数字及下划线。
  • eventName:订阅规则的HisysEvent事件名称,字符串类型,最大长度32个字符(含),有效字符包含大写字母、数字及下划线。
  • ruleType:订阅规则的规则类型,RuleType枚举类型(参考表3)。
| - -**表 3** RuleType类型 - -| 枚举值 | 描述 | -| ------------ | ------------- | -| WHOLE_WORD | 全词匹配类型 | -| PREFIX | 前缀匹配类型 | -| REGULAR | 正则匹配类型 | - -**表 4** HiSysEventSubscribeCallBack订阅对象 +### 功能简介 -| 接口名称 | 描述 | -| -------- | --------- | -|void HiSysEventSubscribeCallBack::OnHandle(const std::string& domain, const std::string& eventName, const int eventType, const std::string& eventDetail)|接口功能:订阅事件的回调接口。

输入参数:
  • domain:事件所属领域。
  • eventName:事件的名称。
  • eventType:事件类型。
  • eventDetail:包含事件相关信息的字符串,以json的形式体现。
返回值:
  无。| - -### 开发实例 - -订阅HiSysEvent事件C++接口实例 - -1. 源代码开发 - - 自定义订阅回调实现类头文件DemoListener.h: - - ``` - #ifndef DEMO_LISTENER_H - #define DEMO_LISTENER_H - - #include "hisysevent_subscribe_callback.h" - - #include - - class DemoListener : public OHOS::HiviewDFX::HiSysEventSubscribeCallBack { - public: - explicit DemoListener() : HiSysEventSubscribeCallBack() {} - void OnHandle(const std::string& domain, const std::string& eventName, const int eventType, - const std::string& eventDetail); - virtual ~DemoListener() {} - void OnServiceDied(); - }; - - #endif // DEMO_LISTENER_H - ``` - - 增加DemoListener.cpp文件,在DemoListener类中根据实际需求自定义订阅回调接口的实现逻辑: - - ``` - #include "demo_listener.h" +HiSysEvent提供了跨进程订阅机制,开发者可以通过注册订阅接口实时获取关注的事件,例如电池模块侦听功耗相关的事件,用于分析耗电情况。 - #include - void DemoListener::OnHandle(const std::string& domain, const std::string& eventName, - const int eventType, const std::string& eventDetail) - { - std::cout << eventDetail << std::endl; - } +### 约束与限制 - void DemoListener::OnServiceDied() - { - std::cout << std::string("service disconnect, exit") << std::endl; - exit(0); - } - ``` +在订阅HiSysEvent事件之前,需要先完成HiSysEvent打点配置,具体配置方法请参考[《HiSysEvent打点配置指导》](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md)。 - 通过HiSysEventManager类提供的AddEventListener接口注册回调对象,完成对HiSysEvent的订阅: - ``` - std::shared_ptr demoListener = nullptr; - try { - demoListener = std::make_shared(); - } catch(...) { - // 智能指针获取失败异常处理 - } - if (demoListener != nullptr) { - // 事件标签规则订阅,规则类型为默认的全词匹配类型 - ListenerRule tagRule("dfx"); - // 事件标签规则订阅,规则类型为正则匹配类型 - ListenerRule regRule("dfx.*", RuleType::REGULAR); - // 事件领域及事件名称规则订阅,规则类型为前缀匹配类型 - ListenerRule domainNameRule("HIVIEWDFX", "APP_USAGE", RuleType::PREFIX); - std::vector sysRules; - sysRules.push_back(tagRule); - sysRules.push_back(regRule); - sysRules.push_back(domainNameRule); - HiSysEventManager::AddEventListener(demoListener, sysRules); - } - ``` - -2. 编译配置 - - 在BUILD.gn编译文件中,需要添加依赖hisysevent\_native组件的libhisyseventmanager库: - - ``` - external_deps = [ "hisysevent_native:libhisyseventmanager", ] - ``` +## 开发指导 + + +### 接口说明 + + **表1** HiSysEvent订阅接口 + +| 接口名称 | 描述 | +| -------- | -------- | +| bool HiSysEventManager::AddEventListener(std::shared_ptr<HiSysEventSubscribeCallBack> listener, std::vector<ListenerRule>& rules) | 接口功能:注册订阅HiSysEvent系统事件侦听对象,可设置规则订阅某些事件。
输入参数:
- listener:订阅回调对象。
- rules:事件订阅规则。
返回值:
- 0:订阅成功,重复订阅。
- 1:订阅成功,初次订阅。
- 其他值:订阅失败。 | +| bool HiSysEventManager::RemoveListener(std::shared_ptr<HiSysEventSubscribeCallBack> listener) | 接口功能:移除订阅hisysevent系统事件侦听对象。
输入参数:
- listener:订阅回调对象。
返回值:
无。 | + + **表2** ListenerRule订阅规则对象 + +| 接口名称 | 描述 | +| -------- | -------- | +| ListenerRule(const std::string& tag, RuleType ruleType = RuleType::WHOLE_WORD) | 接口功能:订阅规则构造函数,创建事件标签订阅规则对象。
输入参数:
- tag:订阅规则的HisysEvent事件标签,字符串类型,最大长度16个字符(含),有效字符包含大小写字母及数字。
- ruleType:订阅规则的规则类型,RuleType枚举类型(参考表3)。 | +| ListenerRule(const std::string& domain, const std::string& eventName, RuleType ruleType = RuleType::WHOLE_WORD) | 接口功能:订阅规则构造函数,创建事件领域与事件名称订阅规则对象。
输入参数:
- domain:订阅规则的HisysEvent事件领域,字符串类型,最大长度16个字符(含),有效字符包含大写字母、数字及下划线。
- eventName:订阅规则的HisysEvent事件名称,字符串类型,最大长度32个字符(含),有效字符包含大写字母、数字及下划线。
- ruleType:订阅规则的规则类型,RuleType枚举类型(参考表3)。 | +| ListenerRule(const std::string& domain, const std::string& eventName, const std::string& tag, RuleType ruleType = RuleType::WHOLE_WORD) | 接口功能:订阅规则构造函数,创建事件领域、事件名称,事件标签订阅规则对象。
输入参数:
- tag:订阅规则的HisysEvent事件标签,字符串类型,最大长度16个字符(含),有效字符包含大小写字母及数字。
- domain:订阅规则的HisysEvent事件领域,字符串类型,最大长度16个字符(含),有效字符包含大写字母、数字及下划线。
- eventName:订阅规则的HisysEvent事件名称,字符串类型,最大长度32个字符(含),有效字符包含大写字母、数字及下划线。
- ruleType:订阅规则的规则类型,RuleType枚举类型(参考表3)。 | + + **表3** RuleType类型 + +| 枚举值 | 描述 | +| -------- | -------- | +| WHOLE_WORD | 全词匹配类型 | +| PREFIX | 前缀匹配类型 | +| REGULAR | 正则匹配类型 | + + **表4** HiSysEventSubscribeCallBackBase订阅对象 + +| 接口名称 | 描述 | +| -------- | -------- | +| void HiSysEventSubscribeCallBack::OnHandle(const std::string& domain, const std::string& eventName, const int eventType, const std::string& eventDetail) | 接口功能:订阅事件的回调接口。
输入参数:
- domain:事件所属领域。
- eventName:事件的名称。
- eventType:事件类型。
- eventDetail:包含事件相关信息的字符串,以json的形式体现。
返回值:
无。 | + + +## 开发实例 + + +### C++接口实例 + +订阅HiSysEvent事件C++接口实例。 + +1. 源代码开发 + 自定义订阅回调实现类头文件DemoListener.h: + + + ``` + #ifndef DEMO_LISTENER_H + #define DEMO_LISTENER_H + + #include "hisysevent_subscribe_callback.h" + + #include + + class DemoListener : public OHOS::HiviewDFX::HiSysEventSubscribeCallBack { + public: + explicit DemoListener() : HiSysEventSubscribeCallBack() {} + void OnHandle(const std::string& domain, const std::string& eventName, const int eventType, + const std::string& eventDetail); + virtual ~DemoListener() {} + void OnServiceDied(); + }; + + #endif // DEMO_LISTENER_H + ``` + + 增加DemoListener.cpp文件,在DemoListener类中根据实际需求自定义订阅回调接口的实现逻辑: + + + ``` + #include "demo_listener.h" + + #include + + void DemoListener::OnHandle(const std::string& domain, const std::string& eventName, + const int eventType, const std::string& eventDetail) + { + std::cout << eventDetail << std::endl; + } + + void DemoListener::OnServiceDied() + { + std::cout << std::string("service disconnect, exit") << std::endl; + exit(0); + } + ``` + + 通过HiSysEventManager类提供的AddEventListener接口注册回调对象,完成对HiSysEvent的订阅: + + + ``` + auto demoListener = std::make_shared(); + // 事件标签规则订阅,规则类型为默认的全词匹配类型 + ListenerRule tagRule("dfx"); + // 事件标签规则订阅,规则类型为正则匹配类型 + ListenerRule regRule("dfx.*", RuleType::REGULAR); + // 事件领域及事件名称规则订阅,规则类型为前缀匹配类型 + ListenerRule domainNameRule("HIVIEWDFX", "APP_USAGE", RuleType::PREFIX); + std::vector sysRules; + sysRules.push_back(tagRule); + sysRules.push_back(regRule); + sysRules.push_back(domainNameRule); + HiSysEventManager::AddEventListener(demoListener, sysRules); + ``` + +2. 编译配置 + 在BUILD.gn编译文件中,需要添加依赖hisysevent_native组件的libhisyseventmanager库: + + + ``` + external_deps = [ "hisysevent_native:libhisyseventmanager", ] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md index 8c332e335ae8c839d6fc9bed45a23a9f4d9ffc54..4b7b2ecc30a30d697f4d57e001d9850a3d7841e5 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md @@ -1,97 +1,108 @@ -# HiSysEvent打点配置指导 +# HiSysEvent打点配置 -## 概述 -组件若有HiSysEvent事件的打点需求,则需要先定义yaml文件并在bundle.js文件中[配置yaml文件的路径](#section123181432175135)。OpenHarmony编译框架在编译过程中则会通过python编译脚本解析校验bundle.js文件指定的所有yaml文件。在解析校验之后,编译框架会将这些yaml文件中配置的信息汇总转换成名为hisysevent.def的json文件。最后,将此json文件打包到系统指定路径下,用作HiSysEvent事件落盘的判断依据。 +## 概述 -### 基本概念 + +### 功能简介 + +组件若有HiSysEvent事件的打点需求,则需要先定义yaml文件并在bundle.js文件中[配置yaml文件的路径](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md#section123181432175135)。OpenHarmony编译框架在编译过程中则会通过python编译脚本解析校验bundle.js文件指定的所有yaml文件。在解析校验之后,编译框架会将这些yaml文件中配置的信息汇总转换成名为hisysevent.def的json文件。最后,将此json文件打包到系统指定路径下,用作HiSysEvent事件落盘的判断依据。 + + +### 基本概念 在配置HiSysEvent打点之前,开发者应了解以下基本概念: -- 事件领域 - 用于标识事件所属的领域,在yaml文件中以domain为键值指定,可参考yaml文件样例中的[domain](#section123181432175123)。 +- 事件领域 用于标识事件所属的领域,在yaml文件中以domain为键值指定,可参考yaml文件样例中的[domain](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md#section123181432175123)。 -- 事件名称 - 用于指定事件领域包含的所有事件,可参考yaml文件样例中的[EVENT_NAMEA/EVENT_NAMEB](#section123181432175123)。 +- 事件名称 用于指定事件领域包含的所有事件,可参考yaml文件样例中的[EVENT_NAMEA/EVENT_NAMEB](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md#section123181432175123)。 -- 参数 - 用于定义某个事件名称包含的所有键值,可参考yaml文件样例中的[__BASE/NAME1/NAME2](#section123181432175123)。 +- 参数 用于定义某个事件名称包含的所有键值,可参考yaml文件样例中的[__BASE/NAME1/NAME2](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md#section123181432175123)。 -### 约束与限制 +### 约束与限制 -**定义事件领域、事件名称及参数的约束与限制:** +定义事件领域、事件名称及参数的约束与限制: - 每个yaml文件只能有一个事件领域,且不能与其他yaml文件中定义的事件领域重名。 - 每个事件领域可定义零个或多个事件名称,同一个事件领域内部的事件名称不能重名。 -- 每个事件名称可定义多个参数,同一个事件名称内部的参数不能重名,每个事件名称**有且只有**一个名称为__BASE的参数,此参数字段组成如表1,其它自定义参数,具体字段组成如表2。 +- 每个事件名称可定义多个参数,同一个事件名称内部的参数不能重名,每个事件名称有且只有一个名称为__BASE的参数,此参数字段组成如表1,其它自定义参数,具体字段组成如表2。 + **表1** __BASE参数字段说明 + + | 字段名称 | 描述 | + | -------- | -------- | + | type | 字段说明:必选字段,用来标识该事件名称的类型。
取值范围:
- FAULT:错误类型。
- STATISTIC:统计类型。
- SECURITY:安全性。
- BEHAVIOR:用户行为。 | + | level | 字段说明:必选字段,用来标识该事件名称的级别。
取值范围:
- CRITICAL:严重。
- MINOR:一般。 | + | tag | 字段说明:可选字段,用来标识该事件名称的标签。
定义规则:
- 最多可同时定义5个标签,标签之间使用空格来分隔。
- 单个标签最多包含16个字符,字符范围[a-zA-Z0-9] | + | desc | 字段说明:必选字段,用来对该事件名称进行描述。
定义规则:
- 至少包含3个字符,最多包含128个字符,字符范围[a-zA-Z0-9 _] | - **表 1** __BASE参数字段说明 + **表2** 自定义参数字段说明 + + | 字段名称 | 描述 | + | -------- | -------- | + | type | 字段说明:必选字段,用来标识该参数的类型。
取值范围:
- BOOL
- UINT8
- UINT16
- INT32
- UINT32
- UINT64
- FLOAT
- DOUBLE
- STRING | + | arrsize | 字段作用:可选字段,用来标识数组类型参数的长度。
取值范围:
- 1~100 | + | desc | 字段作用:必选字段,用来对该参数进行描述。
定义规则:
- 至少包含3个字符,最多包含128个字符,字符范围[a-zA-Z0-9 _] | - | 字段名称 | 描述 | - | ----- | ----- | - | type | 字段说明:必选字段,用来标识该事件名称的类型。

取值范围:
  • FAULT:错误类型。
  • STATISTIC:统计类型。
  • SECURITY:安全性。
  • BEHAVIOR:用户行为。
| - | level | 字段说明:必选字段,用来标识该事件名称的级别。

取值范围:
  • CRITICAL:严重。
  • MINOR:一般。
| - | tag | 字段说明:可选字段,用来标识该事件名称的标签。

定义规则:
  • 最多可同时定义5个标签,标签之间使用空格来分隔。
  • 单个标签最多包含16个字符,字符范围[a-zA-Z0-9]
| - | desc | 字段说明:必选字段,用来对该事件名称进行描述。

定义规则:
  • 至少包含3个字符,最多包含128个字符,字符范围[a-zA-Z0-9 _]
| - **表 2** 自定义参数字段说明 +## 编写yaml文件 - | 字段名称 | 描述 | - | ----- | ----- | - | type | 字段说明:必选字段,用来标识该参数的类型。

取值范围:
  • BOOL
  • UINT8
  • UINT16
  • INT32
  • UINT32
  • UINT64
  • FLOAT
  • DOUBLE
  • STRING
| - | arrsize | 字段作用:可选字段,用来标识数组类型参数的长度。

取值范围:
  • 1~100
| - | desc | 字段作用:必选字段,用来对该参数进行描述。

定义规则:
  • 至少包含3个字符,最多包含128个字符,字符范围[a-zA-Z0-9 _]
| -## 编写yaml文件 +### 编写规则 -### yaml文件编写规则 +- 事件领域命名规则: + - 字母开头,且只能由大写字母/数字/下划线组成; + - 字符串长度取值范围为1~16。 -- 事件领域命名规则: - - 字母开头,且只能由大写字母/数字/下划线组成; - - 字符串长度取值范围为1~16。 -- 事件名称命名规则: - - 字母开头,且只能由大写字母/数字/下划线组成; - - 字符串长度取值范围1~32; - - 单个事件领域内部事件名称的不能超过4096个。 -- 参数命名规则: - - 字母开头,且只能由大写字母/数字/下划线组成; - - 字符串长度取值范围1~32; - - 单个事件名称内包含的参数的个数不能超过128个。 +- 事件名称命名规则: + - 字母开头,且只能由大写字母/数字/下划线组成; + - 字符串长度取值范围1~32; + - 单个事件领域内部事件名称的不能超过4096个。 -### yaml文件编写样例 +- 参数命名规则: + - 字母开头,且只能由大写字母/数字/下划线组成; + - 字符串长度取值范围1~32; + - 单个事件名称内包含的参数的个数不能超过128个。 -- yaml文件样例指定的事件领域名称为MODULEA,该事件领域包含两个事件,名称分别是EVENT_NAMEA和EVENT_NAMEB。 -- EVENT_NAMEA被定义成错误类型的严重事件,该事件包含类型为字符串类型的NAME1参数、字符串类型的NAME2参数及无符号短整型类型的NAME3参数,可以通过事件领域MODULEA和事件名称EVENT_NAMEA对其进行[实时订阅](subsys-dfx-hisysevent-listening.md)。 -- EVENT_NAMEB被定义成统计类型的一般事件,EVENT_NAMEB包含类型为无符号短整型类型的NAME1参数及整型类型的NAME2参数。因为EVENT_NAMEB在__BASE参数中定义了名称为tag1和tag2的两个事件标签,所以不仅可以通过事件领域MODULEA和事件名称EVENT_NAMEB对其进行[实时订阅](subsys-dfx-hisysevent-listening.md),,所以还可以通过事件标签对该事件进行[实时订阅](subsys-dfx-hisysevent-listening.md)。 - ``` - ########################################## - # the hisysevent definition for module a # - ########################################## +### 编写样例 - domain: MODULEA +- yaml文件样例指定的事件领域名称为MODULEA,该事件领域包含两个事件,名称分别是EVENT_NAMEA和EVENT_NAMEB。 - EVENT_NAMEA: - __BASE: {type: FAULT, level: CRITICAL, desc: event name a} - NAME1: {type: STRING, desc: name1} - NAME2: {type: STRING, desc: name2} - NAME3: {type: UINT16, desc: name3} +- EVENT_NAMEA被定义成错误类型的严重事件,该事件包含类型为字符串类型的NAME1参数、字符串类型的NAME2参数及无符号短整型类型的NAME3参数,可以通过事件领域MODULEA和事件名称EVENT_NAMEA对其进行[实时订阅](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md)。 - EVENT_NAMEB: - __BASE: {type: STATISTIC, level: MINOR, tag: tag1 tag2, desc: event name b} - NAME1: {type: UINT16, desc: name1} - NAME2: {type: INT32, desc: name2} - ``` +- EVENT_NAMEB被定义成统计类型的一般事件,EVENT_NAMEB包含类型为无符号短整型类型的NAME1参数及整型类型的NAME2参数。因为EVENT_NAMEB在__BASE参数中定义了名称为tag1和tag2的两个事件标签,所以不仅可以通过事件领域MODULEA和事件名称EVENT_NAMEB对其进行[实时订阅](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md),,所以还可以通过事件标签对该事件进行[实时订阅](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-listening.md)。 + + ``` + ########################################## + # the hisysevent definition for module a # + ########################################## + + domain: MODULEA + + EVENT_NAMEA: + __BASE: {type: FAULT, level: CRITICAL, desc: event name a} + NAME1: {type: STRING, desc: name1} + NAME2: {type: STRING, desc: name2} + NAME3: {type: UINT16, desc: name3} + + EVENT_NAMEB: + __BASE: {type: STATISTIC, level: MINOR, tag: tag1 tag2, desc: event name b} + NAME1: {type: UINT16, desc: name1} + NAME2: {type: INT32, desc: name2} + ``` -## 验证yaml文件 -### 配置yaml文件路径 +## 验证yaml文件 -在bundle.js文件中通过```hisysevent_config```属性完成yaml文件的路径指定: +### 配置yaml文件路径 + +在bundle.js文件中通过hisysevent_config属性完成yaml文件的路径指定: + + ``` { "name": "@ohos/moduel_a", @@ -133,45 +144,47 @@ } ``` ->![](../public_sys-resources/icon-note.gif) **说明:** ->yaml文件可根据实际需求置于组件工程的任意目录下,只要在bundle.js文件指定即可。 - -### 编译yaml文件 - -- 全量编译: - - 全量编译整个系统,会将所有组件配置的yaml文件中的配置进行汇总,正常完成系统编译后,指定目录下就会生成hisysevent.def文件。 +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> yaml文件可根据实际需求置于组件工程的任意目录下,只要在bundle.js文件指定即可。 - ``` - cd 工程根目录的绝对路径 - ./build --product-name - ``` - - 全量编译生成的hisysevent.def文件可以通过以下命令获取: +### 编译yaml文件 - ``` - cd 工程根目录的绝对路径 - find out -name hisysevent.def -type f - ``` +- 全量编译: + - 全量编译整个系统,会将所有组件配置的yaml文件中的配置进行汇总,正常完成系统编译后,指定目录下就会生成hisysevent.def文件。 + + ``` + cd 工程根目录的绝对路径 + ./build --product-name + ``` -- 单文件编译: + - 全量编译生成的hisysevent.def文件可以通过以下命令获取: + + ``` + cd 工程根目录的绝对路径 + find out -name hisysevent.def -type f + ``` - 也可以只编译单个组件的yaml文件,命令如下: +- 单文件编译: + 也可以只编译单个组件的yaml文件,命令如下: - ``` - cd 工程根目录的绝对路径 - ./build/ohos/hisysevent/gen_def_from_all_yaml.py --yaml-list --def-path - ``` + + ``` + cd 工程根目录的绝对路径 + ./build/ohos/hisysevent/gen_def_from_all_yaml.py --yaml-list --def-path + ``` - **表 3** 单文件编译参数说明 + **表3** 单文件编译参数说明 + + | 选项名称 | 描述 | + | -------- | -------- | + | --yaml-list | 指定需要编译的yaml文件路径列表,多个yaml文件路径之间用空格分隔。 | + | --def-path | 指定编译生成的hisysevent.def文件的生成路径。 | - | 选项名称 | 描述 | - | ------ | ------ | - | --yaml-list | 指定需要编译的yaml文件路径列表,多个yaml文件路径之间用空格分隔。 | - | --def-path | 指定编译生成的hisysevent.def文件的生成路径。 | -### 打点及查询定义的事件 +### 打点及查询定义的事件 -1. 通过[hdc_std工具](subsys-toolchain-hdc-guide.md)将hisysevent.def文件推送到至设备的//system/etc/hiview/目录下; +1. 通过[hdc_std工具](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md)将hisysevent.def文件推送到至设备的//system/etc/hiview/目录下。 -2. 触发yaml文件自定义的HiSysEvent事件完成打点,通过[hisysevent -l](subsys-dfx-hisysevent-tool.md)命令查询历史HiSysEvent事件,确认触发的自定义HiSysEvent事件是否打点成功。 +2. 触发yaml文件自定义的HiSysEvent事件完成打点,通过[hisysevent -l](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-tool.md)命令查询历史HiSysEvent事件,确认触发的自定义HiSysEvent事件是否打点成功。 diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging.md index f653c1062f9d3762960d3587ffe6d645593104f7..a5e7d6a8f5ab5afe986194b0986652c354cbba51 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging.md @@ -1,108 +1,189 @@ -# HiSysEvent打点指导 +# HiSysEvent打点 -- [概述](#section77571101789) - - [功能简介](#section123133332175224) - - [约束与限制](#section123181432175224) -- [开发指导](#section314416685113) - - [接口说明](#section13480315886) - - [开发实例](#section112771171317) -## 概述 +## 概述 -### 功能简介 + +### 功能简介 HiSysEvent提供OpenHarmony打点接口,通过在关键路径打点记录系统在运行过程中的重要信息,辅助开发者定位问题,此外还支持开发者将数据上传到云进行大数据质量度量。 -### 约束与限制 -**HiSysEvent事件打点条件约束:** +### 约束与限制 -- 在进行HiSysEvent事件打点之前,需要先完成HiSysEvent打点配置,具体配置方法请参考[《HiSysEvent打点配置指导》](subsys-dfx-hisysevent-logging-config.md)。 +在进行HiSysEvent事件打点之前,需要先完成HiSysEvent打点配置,具体配置方法请参考[《HiSysEvent打点配置指导》](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-logging-config.md)。 -## 开发指导 -### 接口说明 +## 开发指导 -C++打点接口如下: + +### 接口说明 + +JAVA打点接口如下: HiSysEvent类,具体的API详见接口文档 。 -**表 1** HiSysEvent接口介绍 - -| 接口名称 | 描述 | -| -------- | --------- | -| template<typename... Types> static int Write(const std::string &domain, const std::string &eventName, EventType type, Types... keyValues) | 接口功能:记录系统事件。

输入参数:
  • domain:事件的相关领域,需要使用预置领域请参考Domain,可自定义领域。自定义领域长度在16个字符以内,有效的字符是0-9、A-Z,以字母开头。
  • eventName:事件名,长度在32个字符以内,有效的字符是0-9、A-Z、下划线,以字母开头,不能以下划线结尾。
  • type:事件类型,参考EventType。
  • keyValues:事件参数键值对,支持基本的数据类型、std::string,以及std::vector<基本类型>、std:vector<std::string>。参数名长度在48个字符以内,有效的字符是0-9、A-Z、下划线,以字母开头,不能以下划线结尾。参数名的个数在32个以内。
返回值:
  • 0:系统事件记录成功。
  • 负值:系统事件记录失败。
| - -**表 2** HiSysEvent::Domain接口介绍 - -| 成员名称 | 描述 | -| -------- | --------- | -| static const std::string AAFWK | 元能力子系统 | -| static const std::string APPEXECFWK | 用户程序框架子系统 | -| static const std::string ACCOUNT | 账号子系统 | -| static const std::string ACE | ACE子系统 | -| static const std::string AI | AI业务子系统 | -| static const std::string BARRIER_FREE | 无障碍软件服务子系统 | -| static const std::string BIOMETRICS | 生物特征识别服务子系统 | -| static const std::string CCRUNTIME |C/C++运行环境子系统 | -| static const std::string COMMUNICATION | 公共通信子系统 | -| static const std::string DEVELOPTOOLS | 研发工具链子系统 | -| static const std::string DISTRIBUTED_DATAMGR | 分布式数据管理子系统 | -| static const std::string DISTRIBUTED_SCHEDULE | 分布式任务调度子系统 | -| static const std::string GLOBAL | 全球化子系统 | -| static const std::string GRAPHIC | 图形子系统 | -| static const std::string HIVIEWDFX | DFX子系统 | -| static const std::string IAWARE | 本地资源调度管控子系统 | -| static const std::string INTELLI_ACCESSORIES | 智能配件业务子系统 | -| static const std::string INTELLI_TV | 智能电视业务子系统 | -| static const std::string IVI_HARDWARE | 车机专有硬件服务子系统 | -| static const std::string LOCATION | 位置服务子系统 | -| static const std::string MSDP | 综合传感处理平台子系统 | -| static const std::string MULTI_MEDIA | 媒体子系统 | -| static const std::string MULTI_MODAL_INPUT | 多模输入子系统 | -| static const std::string NOTIFICATION | 事件通知子系统 | -| static const std::string POWERMGR | 电源服务子系统 | -| static const std::string ROUTER | 路由器业务子系统 | -| static const std::string SECURITY | 安全子系统 | -| static const std::string SENSORS | 泛Sensor服务子系统 | -| static const std::string SOURCE_CODE_TRANSFORMER | 应用移植子系统 | -| static const std::string STARTUP | 启动恢复子系统 | -| static const std::string TELEPHONY | 电话服务子系统 | -| static const std::string UPDATE | 升级服务子系统 | -| static const std::string USB | USB服务子系统 | -| static const std::string WEARABLE_HARDWARE | 穿戴专有硬件服务子系统 | -| static const std::string WEARABLE_HARDWARE | 穿戴业务子系统 | -| static const std::string OTHERS | 其它 | - -**表 3** HiSysEvent::EventType接口介绍 - -| 接口名称 | 描述 | -| -------- | --------- | -| FAULT | 故障类型事件 | -| STATISTIC | 统计类型事件 | -| SECURITY | 安全类型事件 | -| BEHAVIOR | 系统行为事件 | - -### 开发实例 + **表1** HiSysEvent接口介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| public static int write(String domain, String eventName, EventType type, Object... keyValues) | 接口功能:记录系统事件。
输入参数:
- domain:事件的相关领域,需要使用预置领域请参考Domain,可自定义领域。自定义领域长度在16个字符以内,有效的字符是0-9、A-Z,以字母开头。
- eventName:事件名,长度在32个字符以内,有效的字符是0-9、a-z、A-Z、_,以字母开头,不能以_结尾。
- type:事件类型,参考EventType。
- keyValues:事件参数键值对,支持基本的数据类型、std::string,以及std::vector<基本类型>、std:vector<std::string>。参数名长度在48个字符以内,有效的字符是0-9、a-z、A-Z、_,以字母开头,不能以_结尾。参数名的个数在32个以内。
返回值:成功返回0,错误返回小于0的值。 | +| public static int write(String domain, String eventName, EventType type, Map<String, Object> keyValues) | 接口功能:记录系统事件。
输入参数:
- domain:事件的相关领域,需要使用预置领域请参考Domain,可自定义领域。自定义领域长度在16个字符以内,有效的字符是0-9、A-Z,以字母开头。
- eventName:事件名,长度在32个字符以内,有效的字符是0-9、a-z、A-Z、_,以字母开头,不能以_结尾。
- type:事件类型,参考EventType。
- keyValues:事件参数键值对,支持基本的数据类型、std::string,以及std::vector<基本类型>、std:vector<std::string>。参数名长度在48个字符以内,有效的字符是0-9、a-z、A-Z、_,以字母开头,不能以_结尾。参数名的个数在32个以内。
返回值:成功返回0,错误返回小于0的值。 | + + **表2** HiSysEvent.Domain接口介绍 + +| 成员 | 描述 | +| -------- | -------- | +| public static final String AAFWK = "AAFWK" | 元能力子系统 | +| public static final String APPEXECFWK = "APPEXECFWK" | 用户程序框架子系统 | +| public static final String ACCOUNT = "ACCOUNT" | 账号子系统 | +| public static final String AI = "AI" | AI子系统 | +| public static final String BARRIER_FREE = "BARRIERFREE" | 无障碍软件服务子系统 | +| public static final String BIOMETRICS = "BIOMETRICS" | 生物特征识别服务子系统 | +| public static final String CCRUNTIME = "CCRUNTIME" | C/C++运行环境子系统 | +| public static final String COMMUNICATION = "COMMUNICATION" | 公共通信子系统 | +| public static final String DEVELOPTOOLS = "DEVELOPTOOLS" | 研发工具链子系统 | +| public static final String DISTRIBUTED_DATAMGR = "DISTDATAMGR" | 分布式数据管理子系统 | +| public static final String DISTRIBUTED_SCHEDULE = "DISTSCHEDULE" | 分布式任务调度子系统 | +| public static final String GLOBAL = "GLOBAL" | 全球化子系统 | +| public static final String GRAPHIC = "GRAPHIC" | 图形子系统 | +| public static final String HIVIEWDFX = "HIVIEWDFX" | DFX子系统 | +| public static final String IAWARE = "IAWARE" | 本地资源调度管控子系统 | +| public static final String INTELLI_ACCESSORIES = "INTELLIACC" | 智能配件业务子系统 | +| public static final String INTELLI_TV = "INTELLITV" | 智能电视业务子系统 | +| public static final String IVI_HARDWARE = "IVIHARDWARE" | 车机专有硬件服务子系统 | +| public static final String LOCATION = "LOCATION" | 位置服务子系统 | +| public static final String MSDP = "MSDP" | 综合传感处理平台子系统 | +| public static final String MULTI_MEDIA = "MULTIMEDIA" | 媒体子系统 | +| public static final String MULTI_MODAL_INPUT = "MULTIMODALINPUT" | 多模输入子系统 | +| public static final String NOTIFICATION = "NOTIFICATION" | 事件通知子系统 | +| public static final String POWERMGR = "POWERMGR" | 电源服务子系统 | +| public static final String ROUTER = "ROUTER" | 路由器业务子系统 | +| public static final String SECURITY = "SECURITY" | 安全子系统 | +| public static final String SENSORS = "SENSORS" | 泛Sensor服务子系统 | +| public static final String SOURCE_CODE_TRANSFORMER = "SRCTRANSFORMER" | 应用移植子系统 | +| public static final String STARTUP = "STARTUP" | 启动恢复子系统 | +| public static final String TELEPHONY = "TELEPHONY" | 电话服务子系统 | +| public static final String UPDATE = "UPDATE" | 升级服务子系统 | +| public static final String USB = "USB" | USB服务子系统 | +| public static final String WEARABLE_HARDWARE = "WEARABLEHW" | 穿戴专有硬件服务子系统 | +| public static final String WEARABLE = "WEARABLE" | 穿戴业务子系统 | +| public static final String OTHERS = "OTHERS" | 其它 | + + **表3** HiSysEvent.EventType接口介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| FAULT | 故障类型事件 | +| STATISTIC | 统计类型事件 | +| SECURITY | 安全类型事件 | +| BEHAVIOR | 系统行为事件 | -C++接口实例 +C++打点接口如下: + +HiSysEvent类,具体的API详见接口文档 。 -1. 源代码开发 + **表4** HiSysEvent接口介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| template<typename... Types> static int Write(const std::string &domain, const std::string &eventName, EventType type, Types... keyValues) | 接口功能:记录系统事件。
输入参数:
- domain:事件的相关领域,需要使用预置领域请参考Domain,可自定义领域。自定义领域长度在16个字符以内,有效的字符是0-9、A-Z,以字母开头。
- eventName:事件名,长度在32个字符以内,有效的字符是0-9、A-Z、下划线,以字母开头,不能以下划线结尾。
- type:事件类型,参考EventType。
- keyValues:事件参数键值对,支持基本的数据类型、std::string,以及std::vector<基本类型>、std:vector<std::string>。参数名长度在48个字符以内,有效的字符是0-9、A-Z、下划线,以字母开头,不能以下划线结尾。参数名的个数在32个以内。
返回值:
- 0:系统事件记录成功。
- 负值:系统事件记录失败。 | + + **表5** HiSysEvent::Domain接口介绍 + +| 成员名称 | 描述 | +| -------- | -------- | +| static const std::string AAFWK | 元能力子系统 | +| static const std::string APPEXECFWK | 用户程序框架子系统 | +| static const std::string ACCOUNT | 账号子系统 | +| static const std::string ACE | ACE子系统 | +| static const std::string AI | AI业务子系统 | +| static const std::string BARRIER_FREE | 无障碍软件服务子系统 | +| static const std::string BIOMETRICS | 生物特征识别服务子系统 | +| static const std::string CCRUNTIME | C/C++运行环境子系统 | +| static const std::string COMMUNICATION | 公共通信子系统 | +| static const std::string DEVELOPTOOLS | 研发工具链子系统 | +| static const std::string DISTRIBUTED_DATAMGR | 分布式数据管理子系统 | +| static const std::string DISTRIBUTED_SCHEDULE | 分布式任务调度子系统 | +| static const std::string GLOBAL | 全球化子系统 | +| static const std::string GRAPHIC | 图形子系统 | +| static const std::string HIVIEWDFX | DFX子系统 | +| static const std::string IAWARE | 本地资源调度管控子系统 | +| static const std::string INTELLI_ACCESSORIES | 智能配件业务子系统 | +| static const std::string INTELLI_TV | 智能电视业务子系统 | +| static const std::string IVI_HARDWARE | 车机专有硬件服务子系统 | +| static const std::string LOCATION | 位置服务子系统 | +| static const std::string MSDP | 综合传感处理平台子系统 | +| static const std::string MULTI_MEDIA | 媒体子系统 | +| static const std::string MULTI_MODAL_INPUT | 多模输入子系统 | +| static const std::string NOTIFICATION | 事件通知子系统 | +| static const std::string POWERMGR | 电源服务子系统 | +| static const std::string ROUTER | 路由器业务子系统 | +| static const std::string SECURITY | 安全子系统 | +| static const std::string SENSORS | 泛Sensor服务子系统 | +| static const std::string SOURCE_CODE_TRANSFORMER | 应用移植子系统 | +| static const std::string STARTUP | 启动恢复子系统 | +| static const std::string TELEPHONY | 电话服务子系统 | +| static const std::string UPDATE | 升级服务子系统 | +| static const std::string USB | USB服务子系统 | +| static const std::string WEARABLE_HARDWARE | 穿戴专有硬件服务子系统 | +| static const std::string WEARABLE_HARDWARE | 穿戴业务子系统 | +| static const std::string OTHERS | 其它 | + + **表6** HiSysEvent::EventType接口介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| FAULT | 故障类型事件 | +| STATISTIC | 统计类型事件 | +| SECURITY | 安全类型事件 | +| BEHAVIOR | 系统行为事件 | + + +### 开发实例 + +Java接口实例 + +1. 源代码开发 + 引入类名: + + + ``` + import ohos.hiviewdfx.HiSysEvent; + ``` + + 假设业务关注应用启动时间start_app,在相关代码中使用(调用接口打点): + + + ``` + HiSysEvent.write(HiSysEvent.Domain.AAFWK, "start_app", HiSysEvent.EventType.FAULT, "app_name", "com.demo"); + ``` + +2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + external_deps = [ "hisysevent:hisysevent_java" ] + ``` - 在类定义头文件或者类实现源文件中,包含HiSysEvent头文件: +C++接口实例 - ``` - #include "hisysevent.h" - ``` +1. 源代码开发 + 在类定义头文件或者类实现源文件中,包含HiSysEvent头文件: - 假设在业务关注应用启动时间start\_app,在业务类实现相关源文件中使用(调用接口打点): + + ``` + #include "hisysevent.h" + ``` - ``` - HiSysEvent::Write(HiSysEvent::Domain::AAFWK, "start_app", HiSysEvent::EventType::FAULT, "app_name", "com.demo"); - ``` + 假设在业务关注应用启动时间start_app,在业务类实现相关源文件中使用(调用接口打点): -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + HiSysEvent::Write(HiSysEvent::Domain::AAFWK, "start_app", HiSysEvent::EventType::FAULT, "app_name", "com.demo"); + ``` - ``` - external_deps = [ "hisysevent_native:libhisysevent" ] - ``` +2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + external_deps = [ "hisysevent_native:libhisysevent" ] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-query.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-query.md index d467ec4e62033d8ee421e69fda5ec4bee634c78a..07c67f71f5b933d995e71e6b59bbfcfb039e0261 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-query.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-query.md @@ -1,110 +1,104 @@ -# HiSysEvent查询指导 +# HiSysEvent查询 -- [概述](#section279684125212) -- [开发指导](#section315316761113) - - [接口说明](#section03869128521) - - [开发实例](#section14286111855212) -## 概述 +## 概述 HiSysEvent提供了查询接口,支持开发者设置条件查询HiSysEvent事件,例如功耗部件可以通过该接口获取所需的系统事件进行业务分析。 -## 开发指导 -### 接口说明 +## 开发指导 -**表 1** HiSysEvent查询接口 -| 接口名称 | 描述 | -| -------- | --------- | -| bool HiSysEventManager::QueryHiSysEvent(struct QueryArg& queryArg, std::vector<QueryRule>& queryRules, std::shared_ptr<HiSysEventQueryCallBack> queryCallBack) | 接口功能:
  支持设置查询时间段,事件领域,事件名称等,查询满足条件的HiSysEvent事件。

输入参数:
  • queryArg:查询参数。
  • queryRules:事件过滤规则。
  • queryCallBack:查询接口回调对象。
返回值:
  • true:查询成功。
  • false:查询失败。
| +### 接口说明 + **表1** HiSysEvent查询接口 -**表 2** QueryArg查询参数对象 +| 接口名 | 描述 | +| -------- | -------- | +| bool HiSysEventManager::QueryHiSysEvent(struct QueryArg& queryArg, std::vector<QueryRule>& queryRules, std::shared_ptr<HiSysEventQueryCallBack> queryCallBack) | 接口功能:支持设置查询时间段,事件领域,事件名称等,查询满足条件的HiSysEvent事件。
输入参数:
- queryArg:查询参数。
- queryRules:事件过滤规则。
- queryCallBack:查询接口回调对象。
返回值:
- true:查询成功。
- false:查询失败。 | -| 属性名称 | 描述 | -| -------- | --------- | -| beginTime | long long int类型,用于指定查询事件的开始时间。 | -| endTime | long long int类型,用于指定查询事件的结束时间。 | -| maxEvents | int类型,用于指定查询返回事件查询的最多条数。 | + **表2** QueryArg查询参数对象 -**表 3** QueryRule查询规则对象 +| 属性名称 | 描述 | +| -------- | -------- | +| beginTime | long long int类型,用于指定查询事件的开始时间。 | +| endTime | long long int类型,用于指定查询事件的结束时间。 | +| maxEvents | int类型,用于指定查询返回事件查询的最多条数。 | -| 接口名称 | 描述 | -| -------- | --------- | -| QueryRule(const std::string& domain, const std::vector<std::string>& eventList) | 接口功能:查询规则构造函数,创建查询规则对象。

输入参数:
  • domain:string类型,用来标识查询规则对象的事件所属领域,如果传入的是空字符串,则默认事件领域字段匹配成功。
  • eventList:std::vector<std::string>类型,事件名称的列表,如果传入的是空字符串,则默认事件名称字段匹配成功。
| + **表3** QueryRule查询规则对象 -**表 4** HiSysEventQueryCallBack查询回调对象 +| 接口名称 | 描述 | +| -------- | -------- | +| QueryRule(const std::string& domain, const std::vector<std::string>& eventList) | 接口功能:查询规则构造函数,创建查询规则对象。
输入参数:
- domain:string类型,用来标识查询规则对象的事件所属领域,如果传入的是空字符串,则默认事件领域字段匹配成功。
- eventList:std::vector<std::string>类型,事件名称的列表,如果传入的是空字符串,则默认事件名称字段匹配成功。 | -| 接口名称 | 描述 | -| -------- | --------- | -| void HiSysEventQueryCallBack::OnQuery(const ::std::vector<std::string>& sysEvent, const ::std::vector<int64_t>& seq) | 接口功能:订阅事件查询中的回调。

输入参数:
  • sysEvent:返回事件集合。
  • seq:事件序列集合。
返回值:
  无。 | -| void HiSysEventQueryCallBack::OnComplete(int32_t reason, int32_t total) | 接口功能:订阅事件查询完成的回调。

输入参数:
  • reason:查询结束返回原因,目前默认是0。
  • total:本次查询总共返回的事件总数量。
返回值:
  无。 | + **表4** HiSysEventQueryCallBack查询回调对象 -### 开发实例 +| 接口名称 | 描述 | +| -------- | -------- | +| void HiSysEventQueryCallBack::OnQuery(const ::std::vector<std::string>& sysEvent, const ::std::vector<int64_t>& seq) | 接口功能:订阅事件查询中的回调。
输入参数:
- sysEvent:返回事件集合。
- seq:事件序列集合。
返回值:
无。 | +| void HiSysEventQueryCallBack::OnComplete(int32_t reason, int32_t total) | 接口功能:订阅事件查询完成的回调。
输入参数:
- reason:查询结束返回原因,目前默认是0。
- total:本次查询总共返回的事件总数量。
返回值:
无。 | -C++接口实例。 -1. 源代码开发: - - - 引入对应的头文件: - - hisysevent\_manager.h - - - 实现对应的查询回调接口: - - void HiSysEventQueryCallBack::OnQuery\(const ::std::vector<std::string>& sysEvent, const ::std::vector& seq\) - - void HiSysEventQueryCallBack::OnComplete\(int32\_t reason, int32\_t total\) - - - 在相应的业务逻辑里面调用查询接口: - - HiSysEventManager::QueryHiSysEvent\(struct QueryArg& queryArg, std::vector& queryRules, std::shared\_ptr queryCallBack\) - - - ``` - // 以下是查询所有系统事件的应用例子 - #include "hisysevent_manager.h" - #include - - namespace OHOS { - namespace HiviewDFX { - // 实现查询回调的接口 - void HiSysEventToolQuery::OnQuery(const ::std::vector& sysEvent, - const ::std::vector& seq) - { - for_each(sysEvent.cbegin(), sysEvent.cend(), [](const std::string &tmp) { - std::cout << tmp << std::endl; - }); - } - - void HiSysEventToolQuery::OnComplete(int32_t reason, int32_t total) - { - return; - } - } // namespace HiviewDFX - } // namespace OHOS - - // 调用查询接口获取HiSysEvent事件 - std::shared_ptr queryCallBack = nullptr; - try { - queryCallBack = std::make_shared(); - } catch (...) { - // 智能指针获取失败处理 - } - if (queryCallBack != nullptr) { - struct QueryArg args(clientCmdArg.beginTime, clientCmdArg.endTime, clientCmdArg.maxEvents); - std::vector rules; - HiSysEventManager::QueryHiSysEvent(args, rules, queryCallBack); - } - ``` - -2. 编译设置: - - 在BUILD.gn编译文件中,需要添加依赖hisysevent\_native部件的libhisyseventmanager库。 - - ``` - external_deps = [ "hisysevent_native:libhisyseventmanager", ] - ``` +### 开发实例 + +C++接口实例。 +1. 源代码开发: + 引入对应的头文件: + + ``` + #include "hisysevent_manager.h" + ``` + + 实现对应的查询回调接口: + + ``` + void HiSysEventQueryCallBack::OnQuery(const ::std::vector& sysEvent, const ::std::vector& seq) + void HiSysEventQueryCallBack::OnComplete(int32_t reason, int32_t total) + ``` + + 在相应的业务逻辑里面调用查询接口: + + ``` + HiSysEventManager::QueryHiSysEvent(struct QueryArg& queryArg, + std::vector& queryRules, std::shared_ptr queryCallBack) + ``` + + 以下是查询所有系统事件的应用例子: + + ``` + #include "hisysevent_manager.h" + #include + + namespace OHOS { + namespace HiviewDFX { + // 实现查询回调的接口 + void HiSysEventToolQuery::OnQuery(const ::std::vector& sysEvent, + const ::std::vector& seq) + { + for_each(sysEvent.cbegin(), sysEvent.cend(), [](const std::string &tmp) { + std::cout << tmp << std::endl; + }); + } + + void HiSysEventToolQuery::OnComplete(int32_t reason, int32_t total) + { + return; + } + } // namespace HiviewDFX + } // namespace OHOS + + // 调用查询接口获取HiSysEvent事件 + auto queryCallBack = std::make_shared(); + struct QueryArg args(clientCmdArg.beginTime, clientCmdArg.endTime, clientCmdArg.maxEvents); + std::vector mRules; + HiSysEventManager::QueryHiSysEvent(args, mRules, queryCallBack); + ``` + +2. 编译设置: + 在BUILD.gn编译文件中,需要添加依赖hisysevent_native部件的libhisyseventmanager库。 + + ``` + external_deps = [ "hisysevent_native:libhisyseventmanager", ] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-tool.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-tool.md index a71dcc312d7027c21495891c3096c381201d5d8d..c48bd5528a40130e607f90b33922f393a24858c2 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-tool.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent-tool.md @@ -1,153 +1,156 @@ -# HiSysEvent工具使用指导 +# HiSysEvent工具 -- [概述](#section1886702718521) -- [实时订阅HiSysEvent事件相关命令](#section1210623418527) -- [查询历史HiSysEvent事件相关命令](#section1210623418539) -## 概述 +## 概述 目前在系统的/system/bin目录下预置了hisysevent工具,开发者可以通过此工具实时订阅HiSysEvent事件及查询历史HiSysEvent事件。 -## 实时订阅HiSysEvent事件相关命令 -- 实时订阅HiSysEvent事件的基础命令: +## 实时订阅HiSysEvent事件相关命令 - ``` - hisysevent -r - ``` +- 实时订阅HiSysEvent事件的基础命令: - 选项说明: + +``` +hisysevent -r +``` - | 选项名称 | 功能说明 | - | -------- | --------- | - | -r  | 以缺省设置实时订阅HiSysEvent事件,在此种订阅方式下有任何实时HiSysEvent事件产生,都会在控制台上打印此HiSysEvent事件 | +选项说明: -- 打开调试模式: + | 选项名称 | 功能说明 | +| -------- | -------- | +| -r | 以缺省设置实时订阅HiSysEvent事件,在此种订阅方式下有任何实时HiSysEvent事件产生,都会在控制台上打印此HiSysEvent事件 | - ``` - hisysevent -r -d - ``` +- 打开调试模式: - 选项说明: + +``` +hisysevent -r -d +``` - | 选项名称 | 功能说明 | - | -------- | --------- | - | -d | 在调试模式下实时订阅HiSysEvent事件 | +选项说明: -- 通过事件标签方式实时订阅HiSysEvent事件: + | 选项名称 | 功能说明 | +| -------- | -------- | +| -d | 在调试模式下实时订阅HiSysEvent事件 | - ``` - hisysevent -r -t [-c [WHOLE_WORD|PREFIX|REGULAR]] - ``` +- 通过事件标签方式实时订阅HiSysEvent事件: - 选项说明: + +``` +hisysevent -r -t [-c [WHOLE_WORD|PREFIX|REGULAR]] +``` - | 选项名称 | 功能说明 | - | -------- | --------- | - | -t  | 设置实时订阅的HiSysEvent事件标签,用来过滤订阅的HiSysEvent事件。 | - | -c  | 设置实时订阅的HiSysEvent事件标签匹配规则,有“WHOLE_WORD”、“PREFIX”、“REGULAR”三种匹配规则。 | +选项说明: - 命令实例: + | 选项名称 | 功能说明 | +| -------- | -------- | +| -t | 设置实时订阅的HiSysEvent事件标签,用来过滤订阅的HiSysEvent事件。 | +| -c | 设置实时订阅的HiSysEvent事件标签匹配规则,有“WHOLE_WORD”、“PREFIX”、“REGULAR”三种匹配规则。 | - ``` - # hisysevent -r -t "TAG" -c PREFIX - {"domain_":"ACE","name_":"UI_BLOCK_6S","type_":1,"time_":1501940269812,"tz_":"+0000","tag_":"TAG1","pid_":1428,"tid_":1452,"uid_":10001,"level_":"CRITICAL","info_":""} - # hisysevent -r -t "TA\w{0,1}" -c REGULAR - {"domain_":"WINDOWMANAGER","name_":"NO_FOCUS_WINDOW","type_":1,"time_":1501940269802,"tz_":"+0000","tag_":"TAG","pid_":1428,"tid_":1433,"uid_":10001,"level_":"CRITICAL","info_":""} - {"domain_":"ACE","name_":"UI_BLOCK_6S","type_":1,"time_":1501940269812,"tz_":"+0000","tag_":"TAG1","pid_":1428,"tid_":1452,"uid_":10001,"level_":"CRITICAL","info_":""} - # hisysevent -r -t "TA\w+" -c REGULAR - {"domain_":"WINDOWMANAGER","name_":"NO_FOCUS_WINDOW","type_":1,"time_":1501940269802,"tz_":"+0000","tag_":"TAG","pid_":1428,"tid_":1433,"uid_":10001,"level_":"CRITICAL","info_":""} - {"domain_":"ACE","name_":"UI_BLOCK_6S","type_":1,"time_":1501940269812,"tz_":"+0000","tag_":"TAG1","pid_":1428,"tid_":1452,"uid_":10001,"level_":"CRITICAL","info_":""} - ``` +命令实例: -- 通过事件领域及事件名称的方式实时订阅HiSysEvent事件: + +``` +# hisysevent -r -t "TAG" -c PREFIX {"domain_":"ACE","name_":"UI_BLOCK_6S","type_":1,"time_":1501940269812,"tz_":"+0000","tag_":"TAG1","pid_":1428,"tid_":1452,"uid_":10001,"level_":"CRITICAL","info_":""} +# hisysevent -r -t "TAw{0,1}" -c REGULAR {"domain_":"WINDOWMANAGER","name_":"NO_FOCUS_WINDOW","type_":1,"time_":1501940269802,"tz_":"+0000","tag_":"TAG","pid_":1428,"tid_":1433,"uid_":10001,"level_":"CRITICAL","info_":""} {"domain_":"ACE","name_":"UI_BLOCK_6S","type_":1,"time_":1501940269812,"tz_":"+0000","tag_":"TAG1","pid_":1428,"tid_":1452,"uid_":10001,"level_":"CRITICAL","info_":""} +# hisysevent -r -t "TAw+" -c REGULAR {"domain_":"WINDOWMANAGER","name_":"NO_FOCUS_WINDOW","type_":1,"time_":1501940269802,"tz_":"+0000","tag_":"TAG","pid_":1428,"tid_":1433,"uid_":10001,"level_":"CRITICAL","info_":""} {"domain_":"ACE","name_":"UI_BLOCK_6S","type_":1,"time_":1501940269812,"tz_":"+0000","tag_":"TAG1","pid_":1428,"tid_":1452,"uid_":10001,"level_":"CRITICAL","info_":""} +``` - ``` - hisysevent -r -o -n [-c [WHOLE_WORD|PREFIX|REGULAR]] - ``` +- 通过事件领域及事件名称的方式实时订阅HiSysEvent事件: - 选项说明: + +``` +hisysevent -r -o -n [-c [WHOLE_WORD|PREFIX|REGULAR]] +``` - | 选项名称 | 功能说明 | - | -------- | --------- | - | -o | 设置实时订阅的HiSysEvent事件领域,用来过滤订阅的HiSysEvent事件。 | - | -n | 设置实时订阅的HiSysEvent事件名称,用来过滤订阅的HiSysEvent事件。 | - | -c | 设置实时订阅的HiSysEvent事件领域及事件名称的匹配规则,有“WHOLE_WORD”、“PREFIX”、“REGULAR”三种匹配规则。 | +选项说明: - 命令实例: + | 选项名称 | 功能说明 | +| -------- | -------- | +| -o | 设置实时订阅的HiSysEvent事件领域,用来过滤订阅的HiSysEvent事件。 | +| -n | 设置实时订阅的HiSysEvent事件名称,用来过滤订阅的HiSysEvent事件。 | +| -c | 设置实时订阅的HiSysEvent事件领域及事件名称的匹配规则,有“WHOLE_WORD”、“PREFIX”、“REGULAR”三种匹配规则。 | - ``` - # hisysevent -r -o "DOMAINA" -n "EVENTNAMEA" - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":1501940269802,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - # hisysevent -r -o "DOMA\w{0,10}" -n "EVENT\w+" -c REULAR - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":1501940269802,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINABC","name_":"EVENTNAMEABC","type_":1,"time_":1501940269938,"tz_":"+0000","pid_":1428,"tid_":1336,"uid_":10002,"level_":"CRITICAL","info_":""} - # hisysevent -r -o "DOMA\w{0,10}" -c REGULAR - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":1501940269802,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINABC","name_":"EVENTNAMEABC","type_":1,"time_":1501940269938,"tz_":"+0000","pid_":1428,"tid_":1336,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINABC","name_":"EVENTNAMEB","type_":1,"time_":1501940279938,"tz_":"+0000","pid_":1428,"tid_":1344,"uid_":10002,"level_":"CRITICAL","info_":""} - ``` +命令实例: - >![](../public_sys-resources/icon-note.gif) **说明:** - >当同时通过-t、-o及-n指定了相关订阅规则参数设置,则判断设置的事件标签是否为空,若不为空,则使用事件标签规则进行订阅,否则使用事件领域及事件名称订阅规则进行订阅。 + +``` +# hisysevent -r -o "DOMAINA" -n "EVENTNAMEA" +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":1501940269802,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +# hisysevent -r -o "DOMAw{0,10}" -n "EVENTw+" -c REULAR +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":1501940269802,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} {"domain_":"DOMAINABC","name_":"EVENTNAMEABC","type_":1,"time_":1501940269938,"tz_":"+0000","pid_":1428,"tid_":1336,"uid_":10002,"level_":"CRITICAL","info_":""} +# hisysevent -r -o "DOMAw{0,10}" -c REGULAR +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":1501940269802,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} {"domain_":"DOMAINABC","name_":"EVENTNAMEABC","type_":1,"time_":1501940269938,"tz_":"+0000","pid_":1428,"tid_":1336,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINABC","name_":"EVENTNAMEB","type_":1,"time_":1501940279938,"tz_":"+0000","pid_":1428,"tid_":1344,"uid_":10002,"level_":"CRITICAL","info_":""} +``` -## 查询历史HiSysEvent事件相关命令 +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 当同时通过-t、-o及-n指定了相关订阅规则参数设置,则判断设置的事件标签是否为空,若不为空,则使用事件标签规则进行订阅,否则使用事件领域及事件名称订阅规则进行订阅。 -- 查询历史HiSysEvent事件的基础命令: - ``` - hisysevent -l - ``` +## 查询历史HiSysEvent事件相关命令 - 选项说明: +- 查询历史HiSysEvent事件的基础命令: - | 选项名称 | 功能说明 | - | -------- | --------- | - | -l | 以缺省设置查询历史HiSysEvent事件,此次查询会返回最近不多于1000条的HiSysEvent事件。 | + +``` +hisysevent -l +``` -- 通过设置开始/结束时间,过滤查询历史HiSysEvent事件的结果的命令: +选项说明: - ``` - hisysevent -l -s -e - ``` + | 选项名称 | 功能说明 | +| -------- | -------- | +| -l | 以缺省设置查询历史HiSysEvent事件,此次查询会返回最近不多于1000条的HiSysEvent事件。 | - 选项说明: +- 通过设置开始/结束时间,过滤查询历史HiSysEvent事件的结果的命令: - | 选项名称 | 功能说明 | - | -------- | --------- | - | -s | 设置查询历史HiSysEvent事件的开始时间,此次查询只会返回不早于该时间点的HiSysEvent事件。 | - | -e | 设置查询历史HiSysEvent事件的结束时间,此次查询只会返回不晚于该时间点的HiSysEvent事件。 | + +``` +hisysevent -l -s -e +``` - 命令实例: +选项说明: - ``` - # hisysevent -l -s 20207388633 -e 20207389000 - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388633,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388634,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388900,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207389000,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - ``` + | 选项名称 | 功能说明 | +| -------- | -------- | +| -s | 设置查询历史HiSysEvent事件的开始时间,此次查询只会返回不早于该时间点的HiSysEvent事件。 | +| -e | 设置查询历史HiSysEvent事件的结束时间,此次查询只会返回不晚于该时间点的HiSysEvent事件。 | -- 通过设置最大数量值,限制查询历史HiSysEvent事件的数量: +命令实例: - ``` - hisysevent -l -m - ``` + +``` +# hisysevent -l -s 20207388633 -e 20207389000 +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388633,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388634,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388900,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207389000,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +``` - 选项说明: +- 通过设置最大数量值,限制查询历史HiSysEvent事件的数量: - | 选项名称 | 功能说明 | - | -------- | --------- | - | -m | 设置查询历史HiSysEvent事件的数量,有效值范围[0,1000],此次查询返回的HiSysEvent事件数目不会多于此值。 | + +``` +hisysevent -l -m +``` - 命令实例: +选项说明: - ``` - # hisysevent -l -s 20207388633 -e 20207389000 -m 3 - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388634,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388900,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207389000,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - # hisysevent -l -m 2 - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388633,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - {"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388634,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} - ``` + | 选项名称 | 功能说明 | +| -------- | -------- | +| -m | 设置查询历史HiSysEvent事件的数量,有效值范围[0,1000],此次查询返回的HiSysEvent事件数目不会多于此值。 | + +命令实例: + + +``` +# hisysevent -l -s 20207388633 -e 20207389000 -m 3 +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388634,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388900,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207389000,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +# hisysevent -l -m 2 +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388633,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +{"domain_":"DOMAINA","name_":"EVENTNAMEA","type_":1,"time_":20207388634,"tz_":"+0000","pid_":1428,"tid_":1333,"uid_":10002,"level_":"CRITICAL","info_":""} +``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md index 26043db5cafd11df0b0166eb8c5acbbc0a77e5a3..189134220d756e0355c9f049d79834fd8d033197 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md @@ -1,11 +1,13 @@ -# HiSysEvent开发指导 +# HiSysEvent开发指导 -- **[HiSysEvent打点配置指导](subsys-dfx-hisysevent-logging-config.md)** -- **[HiSysEvent打点指导](subsys-dfx-hisysevent-logging.md)** -- **[HiSysEvent订阅指导](subsys-dfx-hisysevent-listening.md)** +- **[HiSysEvent打点配置](subsys-dfx-hisysevent-logging-config.md)** -- **[HiSysEvent查询指导](subsys-dfx-hisysevent-query.md)** +- **[HiSysEvent打点](subsys-dfx-hisysevent-logging.md)** -- **[HiSysEvent工具使用指导](subsys-dfx-hisysevent-tool.md)** \ No newline at end of file +- **[HiSysEvent订阅](subsys-dfx-hisysevent-listening.md)** + +- **[HiSysEvent查询](subsys-dfx-hisysevent-query.md)** + +- **[HiSysEvent工具](subsys-dfx-hisysevent-tool.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hitrace.md b/zh-cn/device-dev/subsystems/subsys-dfx-hitrace.md index 1b2af97a7833183344a189cd9e3c1d1f95b7f34c..498881fd5cad8a390f6a0bf5100959d2610f29b6 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx-hitrace.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hitrace.md @@ -1,446 +1,111 @@ -# HiTrace开发指导 +# HiTrace开发指导 -- [概述](#section3986195420436) -- [应用场景](#section134561822574) - - [业务使用示例](#section63861653124417) +## 概述 -- [接口说明](#section1517945334617) - - [接口形式对比](#section932504474) - - [接口功能参数](#section2514638125) +HiTrace主要是对于跨设备/跨进程/跨线程的业务流程,通过相同的traceid在整个业务流程中传递,将流程处理过程中的调用关系、各种输出信息关联和展现出来,帮助使用者分析、定位问题和系统调优。 -- [通信调用处理](#section11257133933) -- [开发实例](#section14310412491) - - [C++接口实例](#section114916381509) - - [C接口实例](#section108292107514) +## 应用场景 -## 概述 +HiTrace在产品中应用场景如下,包括: -HiTrace主要是对于跨设备/跨进程/跨线程的业务流程,通过相同的traceid在整个业务流程中传递,将流程处理过程中的调用关系、各种输出信息关联和展现出来,帮助使用者分析、定位问题和系统调优。 +- 端侧业务流程信息(日志、事件等)关联、上报 -## 应用场景 +- 云侧对上报信息的关联展示和分析,辅助问题定位 -HiTrace在产品中应用场景如下,包括: +- IDE对业务流程详细信息、耗时分布进行调试,辅助系统调优 -- 端侧业务流程信息(日志、事件等)关联、上报 -- 云侧对上报信息的关联展示和分析,辅助问题定位 -- IDE对业务流程详细信息、耗时分布进行调试,辅助系统调优 + **图1** HiTrace应用场景 + ![zh-cn_image_0000001216312860](figures/zh-cn_image_0000001216312860.png) - **图 1** HiTrace应用场景 - ![](figure/HiTrace应用场景.png "HiTrace应用场景") +### 业务使用示例 -### 业务使用示例 + **图2** 业务调用流程图(跨设备、跨进程同步调用) + + ![zh-cn_image_0000001216632830](figures/zh-cn_image_0000001216632830.png) -**图 2** 业务调用流程图(跨设备、跨进程同步调用) -![](figure/业务调用流程图(跨设备-跨进程同步调用).png "业务调用流程图(跨设备-跨进程同步调用)") +1. 调试时展示业务流程中的调用关系,进行关键路径分析、功能依赖分析,确定各调用点耗时、调用频率,提前发现性能瓶颈点。 -1. 调试时展示业务流程中的调用关系,进行关键路径分析、功能依赖分析,确定各调用点耗时、调用频率,提前发现性能瓶颈点。 + **图3** 业务调用流程序列图 + ![zh-cn_image_0000001216792790](figures/zh-cn_image_0000001216792790.png) - **图 3** 业务调用流程序列图 - ![](figure/业务调用流程序列图.png "业务调用流程序列图") + + **图4** 业务调用流程性能耗时分布 + ![zh-cn_image_0000001261272659](figures/zh-cn_image_0000001261272659.png) - **图 4** 业务调用流程性能耗时分布 - ![](figure/业务调用流程性能耗时分布.png "业务调用流程性能耗时分布") +2. 在日志和事件等信息中自动附加traceid信息,便于开发人员综合分析和快速实现问题定界定位。 -2. 在日志和事件等信息中自动附加traceid信息,便于开发人员综合分析和快速实现问题定界定位。 -## 接口说明 +## 接口说明 HiTrace提供C++、C接口。上层业务主要使用HiTrace跟踪启动、结束接口。 -HiTrace实现在C层,主要原理是在一次业务调用流程中,利用通信传递traceid,在业务处理前将traceid设置到当前线程的TLS\(Thread Local Storage\)中,业务处理结束清除当前线程的TLS;这样的话,在业务处理中可以从当前线程的上下文TLS取到traceid,自动附加到日志、事件信息中。 - -### 接口形式对比 - -**表 1** C++、C的函数接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  

C++

-

C

-

-

函数

-

函数

-

HiTrace

-

HiTraceId Begin(const std::string& name, int flags)

-

HiTraceIdStruct HiTraceBegin(const char* name, int flags)

-
  

void End(const HiTraceId& id)

-

void HiTraceEnd(const HiTraceIdStruct* pId)

-
  

HiTraceId GetId();

-

HiTraceIdStruct HiTraceGetId()

-
  

void SetId(const HiTraceId& id)

-

void HiTraceSetId(const HiTraceIdStruct* pId)

-
  

void ClearId()

-

void HiTraceClearId()

-
  

HiTraceId CreateSpan()

-

HiTraceIdStruct HiTraceCreateSpan()

-
  

void Tracepoint(HiTraceTracepointType type, const HiTraceId& id, const char* fmt, ...)

-

void HiTraceTracepoint(HiTraceTracepointType type, const HiTraceIdStruct* pId, const char* fmt, ...)

-
  

void Tracepoint(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceId& id, const char* fmt, ...)

-

void HiTraceTracepointEx(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceIdStruct* pId, const char* fmt, ...)

-

HiTraceId

-

HiTraceId();

-

void HiTraceInitId(HiTraceIdStruct* pId)

-
  

HiTraceId(const uint8_t* pIdArray, int len)

-

HiTraceIdStruct HiTraceBytesToId(const uint8_t* pIdArray, int len)

-
  

bool IsValid()

-

int HiTraceIsValid(const HiTraceIdStruct* pId)

-
  

bool IsFlagEnabled(HiTraceFlag flag)

-

int HiTraceIsFlagEnabled(const HiTraceIdStruct* pId, HiTraceFlag flag)

-
  

void EnableFlag(HiTraceFlag flag)

-

void HiTraceEnableFlag(HiTraceIdStruct* pId, HiTraceFlag flag)

-
  

int GetFlags()

-

int HiTraceGetFlags(const HiTraceIdStruct* pId)

-
  

void SetFlags(int flags)

-

void HiTraceSetFlags(HiTraceIdStruct* pId, int flags)

-
  

uint64_t GetChainId()

-

uint64_t HiTraceGetChainId(const HiTraceIdStruct* pId)

-
  

void SetChainId(uint64_t chainId)

-

void HiTraceSetChainId(HiTraceIdStruct* pId, uint64_t chainId)

-
  

uint64_t GetSpanId()

-

uint64_t HiTraceGetSpanId(const HiTraceIdStruct* pId)

-
  

void SetSpanId(uint64_t spanId)

-

void HiTraceSetSpanId(HiTraceIdStruct* pId, uint64_t spanId)

-
  

uint64_t GetParentSpanId()

-

uint64_t HiTraceGetParentSpanId(const HiTraceIdStruct* pId)

-
  

void SetParentSpanId(uint64_t parentSpanId)

-

void HiTraceSetParentSpanId(HiTraceIdStruct* pId, uint64_t parentSpanId)

-
  

int ToBytes(uint8_t* pIdArray, int len)

-

int HiTraceIdToBytes(const HiTraceIdStruct* pId, uint8_t* pIdArray, int len)

-
- -### 接口功能参数 - -**表 2** C++接口说明函数参数和功能 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-

方法

-

描述

-

HiTrace

-

HiTraceId Begin(const std::string& name, int flags)

-

功能:启动HiTrace跟踪、生成HiTraceId对象并设置到当前线程TLS中。

-

输入参数:

-
  • name:业务流程名称。
  • flags:跟踪指示位,可以组合使用,具体含义为:
    • HITRACE_FLAG_INCLUDE_ASYNC:同时跟踪同步调用和异步调用,缺省只跟踪同步调用。
    • HITRACE_FLAG_DONOT_CREATE_SPAN:不创建子分支,缺省创建子分支。
    • HITRACE_FLAG_TP_INFO:输出tracepoint信息,缺省不输出。
    • HITRACE_FLAG_NO_BE_INFO:不输出起始、结束信息,缺省输出。
    • HITRACE_FLAG_DONOT_ENABLE_LOG:不与日志关联输出,缺省关联。
    • HITRACE_FLAG_FAULT_TRIGGER:故障触发的跟踪,缺省为正常启动的。
    • HITRACE_FLAG_D2D_TP_INFO:输出设备间tracepoint信息,缺省不输出。
    • HITRCE_FLAG_DEFAULT: 缺省标志。
    -
  • 输出参数:无
  • 返回值:启动跟踪超过返回有效HiTraceId对象,否则返回无效对象。
-

注意:嵌套启动跟踪时,内层启动调用返回无效对象。

-
  

void End(const HiTraceId& id)

-

功能:根据Begin返回的HiTraceId停止HiTrace跟踪;清除当前线程TLS中HiTraceId内容。

-

输入参数:

-
  • id:HiTraceId对象。
-

输出参数:无。

-

返回值:无。

-
  

HiTraceId GetId();

-

功能:从当前线程TLS中获取HiTraceId对象。

-

输入参数:无。

-

输出参数:无。

-

返回值:当前线程上下文的HiTraceId对象。

-
  

void SetId(const HiTraceId& id)

-

功能:设置HiTraceId对象内容到当前线程TLS中。

-

输入参数:

-
  • id:HiTraceId对象。
-

输出参数:无。

-

返回值:无。

-
  

void ClearId()

-

功能:清除当前线程TLS中的HiTraceId对象。

-

输入参数:无。

-

输出参数:无。

-

返回值:无。

-
  

HiTraceId CreateSpan()

-

接口功能:获取当前HiTraceId对象中的分支ID。

-

输入参数:无。

-

输出参数:无。

-

返回值:当前分支ID。

-
  

void Tracepoint(HiTraceTracepointType type, const HiTraceId& id, const char* fmt, ...)

-

功能:根据埋点信息类型输出HiTrace埋点信息,包括时间戳、子分支HiTraceId对象信息。

-

输入参数:

-
  • type:埋点信息类型,具体为
    • HITRACE_TP_CS:Client Send,同步/异步通信客户端发送信息。
    • HITRACE_TP_SR:Server Receive, 同步/异步通信服务端接收信息。
    • HITRACE_TP_SS:Server Send,同步通信服务端发送响应信息。
    • HITRACE_TP_CR:Client Receive,同步通信客户端接收响应信息。
    • HITRACE_TP_GENERAL:普通输出信息。
    -
  • id:当前子分支id。
  • fmt:格式化变参描述字符串。
  • args:变参。
-

输出参数:无。

-

返回值:无。

-
  

void Tracepoint(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceId& id, const char* fmt, ...)

-

功能:根据通信模式、埋点信息类型输出HiTrace埋点信息,包括时间戳、子分支HiTraceId对象信息。

-

输入参数:

-
  • mode:通信模式,具体为
    • HITRACE_CM_DEFAULT:未指定通信模式。
    • HITRACE_CM_THREAD:线程间通信。
    • HITRACE_CM_PROCESS:进程间通信。
    • HITRACE_CM_DEVICE:设备间通信。
    -
  • type:埋点信息类型,具体为
    • HITRACE_TP_CS:Client Send,同步/异步通信客户端发送信息。
    • HITRACE_TP_SR:Server Receive, 同步/异步通信服务端接收信息。
    • HITRACE_TP_SS:Server Send,同步通信服务端发送响应信息。
    • HITRACE_TP_CR:Client Receive,同步通信客户端接收响应信息。
    • HITRACE_TP_GENERAL:普通输出信息。
    -
  • id:当前子分支id。
  • fmt:格式化变参描述字符串。
  • args:变参。
-

输出参数:无。

-

返回值:无。

-

HiTraceId

-

HiTraceId();

-

功能:缺省构造函数,生成无效HiTraceId对象。

-

输入参数:无。

-

输出参数:无。

-

返回值:无。

-
  

HiTraceId(const uint8_t* pIdArray, int len)

-

功能:构造函数,根据字节数组创建跟踪HiTraceId对象。

-
输入参数:
  • pIdArray:字节数组指针。
  • len:字节数组长度。
-
-

输出参数:无。

-

返回值:无。

-
  

bool IsValid()

-

功能:HiTraceId对象是否有效。

-

输入参数:无。

-

输出参数:无。

-

返回值:true 有效;false 无效。

-
  

bool IsFlagEnabled(HiTraceFlag flag)

-

功能:HiTraceId对象的某标志是否置位。

-

输入参数:

-
  • flag:跟踪指示位,具体含义见Begin函数中的定义。
-

输出参数:无。

-

返回值:true 该标志置位;false 该标志未置位。

-
  

void EnableFlag(HiTraceFlag flag)短短

-

功能:设置某跟踪标志位到HiTraceId对象中。

-

输入参数:

-
  • flag:跟踪指示位,具体含义见Begin函数中的定义。
-

输出参数:无。

-

返回值:无。

-
  

int GetFlags()

-

功能:获取HiTraceId对象中设置的标志位。

-

输入参数:无。

-

输出参数:无。

-

返回值:跟踪指示位组合,具体含义见Begin函数中的定义。

-
  

void SetFlags(int flags)

-

功能:设置跟踪标志位到HiTraceId对象中。

-

输入参数:

-
  • flags:跟踪指示位组合,具体含义见Begin函数中的定义。
-

输出参数:无。

-

返回值:无。

-
  

uint64_t GetChainId()

-

功能:获取跟踪链ID。

-

输入参数:无。

-

输出参数:无。

-

返回值:跟踪链ID。

-
  

void SetChainId(uint64_t chainId)

-

功能:设置跟踪链ID到HiTraceId对象中。

-

输入参数:

-
  • chainId:跟踪链ID。
-

输出参数:无。

-

返回值:无。

-
  

uint64_t GetSpanId()

-

接口功能:获取当前HiTraceId对象中的分支ID。

-

输入参数:无。

-

输出参数:无。

-

返回值:当前分支ID。

-
  

void SetSpanId(uint64_t spanId)

-

功能:设置分支ID到HiTraceId对象中。

-

输入参数:

-
  • spanId:分支ID。
-

输出参数:无。

-

返回值:无。

-
  

uint64_t GetParentSpanId()

-

功能:获取当前HiTraceId对象中的父分支ID。

-

输入参数:无。

-

输出参数:无。

-

返回值:父分支ID。

-
  

void SetParentSpanId(uint64_t parentSpanId)

-

功能:设置父分支ID到HiTraceId对象中。

-

输入参数:

-
  • parentSpanId:父分支ID。
-

输出参数:无。

-

返回值:无。

-
  

int ToBytes(uint8_t* pIdArray, int len)

-

功能:将HiTraceId对象转换为字节数组,便于缓存或者通信传递。

-

输入参数:

-
  • pIdArray:字节数组指针,数组长度至少为HITRACE_ID_LEN。
  • len: 字节数组长度
-

输出参数:

-
  • pIdArray:字节数组指针,对象有效时存储转换后的对象数据。
-

返回值:0 转换失败; >0 有效对象转换数组长度。

-
- -## 通信调用处理 +HiTrace实现在C层,主要原理是在一次业务调用流程中,利用通信传递traceid,在业务处理前将traceid设置到当前线程的TLS(Thread Local Storage)中,业务处理结束清除当前线程的TLS;这样的话,在业务处理中可以从当前线程的上下文TLS取到traceid,自动附加到日志、事件信息中。 + + +### 接口形式对比 + + **表1** C++、C的函数接口 + +| | **C++** | **C** | +| -------- | -------- | -------- | +| **类** | **函数** | **函数** | +| HiTrace | HiTraceId Begin(const std::string& name, int flags) | HiTraceIdStruct HiTraceBegin(const char\* name, int flags) | +| | void End(const HiTraceId& id) | void HiTraceEnd(const HiTraceIdStruct\* pId) | +| | HiTraceId GetId(); | HiTraceIdStruct HiTraceGetId() | +| | void SetId(const HiTraceId& id) | void HiTraceSetId(const HiTraceIdStruct\* pId) | +| | void ClearId() | void HiTraceClearId() | +| | HiTraceId CreateSpan() | HiTraceIdStruct HiTraceCreateSpan() | +| | void Tracepoint(HiTraceTracepointType type, const HiTraceId& id, const char\* fmt, ...) | void HiTraceTracepoint(HiTraceTracepointType type, const HiTraceIdStruct_ pId, const char_ fmt, ...) | +| | void Tracepoint(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceId& id, const char\* fmt, ...) | void HiTraceTracepointEx(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceIdStruct_ pId, const char_ fmt, ...) | +| HiTraceId | HiTraceId(); | void HiTraceInitId(HiTraceIdStruct\* pId) | +| | HiTraceId(const uint8_t\* pIdArray, int len) | HiTraceIdStruct HiTraceBytesToId(const uint8_t\* pIdArray, int len) | +| | bool IsValid() | int HiTraceIsValid(const HiTraceIdStruct\* pId) | +| | bool IsFlagEnabled(HiTraceFlag flag) | int HiTraceIsFlagEnabled(const HiTraceIdStruct\* pId, HiTraceFlag flag) | +| | void EnableFlag(HiTraceFlag flag) | void HiTraceEnableFlag(HiTraceIdStruct\* pId, HiTraceFlag flag) | +| | int GetFlags() | int HiTraceGetFlags(const HiTraceIdStruct\* pId) | +| | void SetFlags(int flags) | void HiTraceSetFlags(HiTraceIdStruct\* pId, int flags) | +| | uint64_t GetChainId() | uint64_t HiTraceGetChainId(const HiTraceIdStruct\* pId) | +| | void SetChainId(uint64_t chainId) | void HiTraceSetChainId(HiTraceIdStruct\* pId, uint64_t chainId) | +| | uint64_t GetSpanId() | uint64_t HiTraceGetSpanId(const HiTraceIdStruct\* pId) | +| | void SetSpanId(uint64_t spanId) | void HiTraceSetSpanId(HiTraceIdStruct\* pId, uint64_t spanId) | +| | uint64_t GetParentSpanId() | uint64_t HiTraceGetParentSpanId(const HiTraceIdStruct\* pId) | +| | void SetParentSpanId(uint64_t parentSpanId) | void HiTraceSetParentSpanId(HiTraceIdStruct\* pId, uint64_t parentSpanId) | +| | int ToBytes(uint8_t\* pIdArray, int len) | int HiTraceIdToBytes(const HiTraceIdStruct_ pId, uint8_t_ pIdArray, int len) | + + +### 接口功能参数 + + **表2** C++接口说明函数参数和功能 + +| **类** | **方法** | **描述** | +| -------- | -------- | -------- | +| HiTrace | HiTraceId Begin(const std::string& name, int flags) | 功能:启动HiTrace跟踪、生成HiTraceId对象并设置到当前线程TLS中。
输入参数:
- name:业务流程名称。
- flags:跟踪指示位,可以组合使用,具体含义为:
  - HITRACE_FLAG_INCLUDE_ASYNC:同时跟踪同步调用和异步调用,缺省只跟踪同步调用。
  - HITRACE_FLAG_DONOT_CREATE_SPAN:不创建子分支,缺省创建子分支。
  - HITRACE_FLAG_TP_INFO:输出tracepoint信息,缺省不输出。
  - HITRACE_FLAG_NO_BE_INFO:不输出起始、结束信息,缺省输出。
  - HITRACE_FLAG_DONOT_ENABLE_LOG:不与日志关联输出,缺省关联。
  - HITRACE_FLAG_FAULT_TRIGGER:故障触发的跟踪,缺省为正常启动的。
  - HITRACE_FLAG_D2D_TP_INFO:输出设备间tracepoint信息,缺省不输出。
  - HITRACE_FLAG_DEFAULT: 缺省标志。
- 输出参数:无
- 返回值:启动跟踪超过返回有效HiTraceId对象,否则返回无效对象。
注意:嵌套启动跟踪时,内层启动调用返回无效对象。 | +| | void End(const HiTraceId& id) | 功能:根据Begin返回的HiTraceId停止HiTrace跟踪;清除当前线程TLS中HiTraceId内容。
输入参数:
- id:HiTraceId对象。
输出参数:无。
返回值:无。 | +| | HiTraceId GetId(); | 功能:从当前线程TLS中获取HiTraceId对象。
输入参数:无。
输出参数:无。
返回值:当前线程上下文的HiTraceId对象。 | +| | void SetId(const HiTraceId& id) | 功能:设置HiTraceId对象内容到当前线程TLS中。
输入参数:
- id:HiTraceId对象。
输出参数:无。
返回值:无。 | +| | void ClearId() | 功能:清除当前线程TLS中的HiTraceId对象。
输入参数:无。
输出参数:无。
返回值:无。 | +| | HiTraceId CreateSpan() | 接口功能:获取当前HiTraceId对象中的分支ID。
输入参数:无。
输出参数:无。
返回值:当前分支ID。 | +| | void Tracepoint(HiTraceTracepointType type, const HiTraceId& id, const char\* fmt, ...) | 功能:根据埋点信息类型输出HiTrace埋点信息,包括时间戳、子分支HiTraceId对象信息。
输入参数:
- type:埋点信息类型,具体为
  - HITRACE_TP_CS:Client Send,同步/异步通信客户端发送信息。
  - HITRACE_TP_SR:Server Receive, 同步/异步通信服务端接收信息。
  - HITRACE_TP_SS:Server Send,同步通信服务端发送响应信息。
  - HITRACE_TP_CR:Client Receive,同步通信客户端接收响应信息。
  - HITRACE_TP_GENERAL:普通输出信息。
- id:当前子分支id。
- fmt:格式化变参描述字符串。
- args:变参。
输出参数:无。
返回值:无。 | +| | void Tracepoint(HiTraceCommunicationMode mode, HiTraceTracepointType type, const HiTraceId& id, const char\* fmt, ...) | 功能:根据通信模式、埋点信息类型输出HiTrace埋点信息,包括时间戳、子分支HiTraceId对象信息。
输入参数:
- mode:通信模式,具体为
  - HITRACE_CM_DEFAULT:未指定通信模式。
  - HITRACE_CM_THREAD:线程间通信。
  - HITRACE_CM_PROCESS:进程间通信。
  - HITRACE_CM_DEVICE:设备间通信。
- type:埋点信息类型,具体为
  - HITRACE_TP_CS:Client Send,同步/异步通信客户端发送信息。
  - HITRACE_TP_SR:Server Receive, 同步/异步通信服务端接收信息。
  - HITRACE_TP_SS:Server Send,同步通信服务端发送响应信息。
  - HITRACE_TP_CR:Client Receive,同步通信客户端接收响应信息。
  - HITRACE_TP_GENERAL:普通输出信息。
- id:当前子分支id。
- fmt:格式化变参描述字符串。
- args:变参。
输出参数:无。
返回值:无。 | +| HiTraceId | HiTraceId(); | 功能:缺省构造函数,生成无效HiTraceId对象。
输入参数:无。
输出参数:无。
返回值:无。 | +| | HiTraceId(const uint8_t\* pIdArray, int len) | 功能:构造函数,根据字节数组创建跟踪HiTraceId对象。
输入参数:
- pIdArray:字节数组指针。
- len:字节数组长度。
输出参数:无。
返回值:无。 | +| | bool IsValid() | 功能:HiTraceId对象是否有效。
输入参数:无。
输出参数:无。
返回值:true 有效;false 无效。 | +| | bool IsFlagEnabled(HiTraceFlag flag) | 功能:HiTraceId对象的某标志是否置位。
输入参数:
- flag:跟踪指示位,具体含义见Begin函数中的定义。
输出参数:无。
返回值:true 该标志置位;false 该标志未置位。 | +| | void EnableFlag(HiTraceFlag flag) | 功能:设置某跟踪标志位到HiTraceId对象中。
输入参数:
- flag:跟踪指示位,具体含义见Begin函数中的定义。
输出参数:无。
返回值:无。 | +| | int GetFlags() | 功能:获取HiTraceId对象中设置的标志位。
输入参数:无。
输出参数:无。
返回值:跟踪指示位组合,具体含义见Begin函数中的定义。 | +| | void SetFlags(int flags) | 功能:设置跟踪标志位到HiTraceId对象中。
输入参数:
- flags:跟踪指示位组合,具体含义见Begin函数中的定义。
输出参数:无。
返回值:无。 | +| | uint64_t GetChainId() | 功能:获取跟踪链ID。
输入参数:无。
输出参数:无。
返回值:跟踪链ID。 | +| | void SetChainId(uint64_t chainId) | 功能:设置跟踪链ID到HiTraceId对象中。
输入参数:
- chainId:跟踪链ID。
输出参数:无。
返回值:无。 | +| | uint64_t GetSpanId() | 接口功能:获取当前HiTraceId对象中的分支ID。
输入参数:无。
输出参数:无。
返回值:当前分支ID。 | +| | void SetSpanId(uint64_t spanId) | 功能:设置分支ID到HiTraceId对象中。
输入参数:
- spanId:分支ID。
输出参数:无。
返回值:无。 | +| | uint64_t GetParentSpanId() | 功能:获取当前HiTraceId对象中的父分支ID。
输入参数:无。
输出参数:无。
返回值:父分支ID。 | +| | void SetParentSpanId(uint64_t parentSpanId) | 功能:设置父分支ID到HiTraceId对象中。
输入参数:
- parentSpanId:父分支ID。
输出参数:无。
返回值:无。 | +| | int ToBytes(uint8_t\* pIdArray, int len) | 功能:将HiTraceId对象转换为字节数组,便于缓存或者通信传递。
输入参数:
- pIdArray:字节数组指针,数组长度至少为HITRACE_ID_LEN。
- len: 字节数组长度
输出参数:
- pIdArray:字节数组指针,对象有效时存储转换后的对象数据。
返回值:0 转换失败; &gt;0 有效对象转换数组长度。 | + + +## 通信调用处理 业务使用时跨设备/跨进程/跨线程的调用是通过通信机制实现的,HiTrace需要通信机制传递traceid。 @@ -448,91 +113,92 @@ OpenHarmony系统内置部分通信机制(如ZIDL)已经支持传递traceid 下面描述了同步通信调用传递traceid的处理过程,异步通信调用处理类似。 -对于不支持的扩展通信机制可以参照该方式实现。 - -**图 5** 同步通信处理 -![](figure/同步通信处理.png "同步通信处理") + 对于不支持的扩展通信机制可以参照该方式实现。 + **图5** 同步通信处理 + ![zh-cn_image_0000001261032707](figures/zh-cn_image_0000001261032707.png) 处理流程: -1. client侧业务模块调用begin\(\)接口启动调用链跟踪。 -2. client侧业务模块发起同步调用transact,到client侧通信组件。 -3. client侧通信组件: - 1. 从当前线程TLS中获取traceid。 - 2. 生成子调用分支(child traceid)。 - 3. 将child traceid写入同步调用通信数据(transaction data)中。 - 4. 进行CS埋点(Client Send)。 - 5. 将通信数据发送到server侧通信组件。 - -4. server侧通信组件收到通信数据: - 1. 从数据消息包中取出traceid。 - 2. 将traceid设置到当前线程TLS中。 - 3. 进行SR埋点(Server Receive)。 - 4. 然后进行同步调用回调(onTransact)到server侧业务模块。 - -5. server侧业务模块进行服务处理,处理完毕发送处理结果(transact reply)到通信组件。 -6. server侧通信组件: - 1. 进行SS埋点(Server Send)。 - 2. 将响应数据发送到client侧通信组件。 - 3. 清除当前线程TLS中的traceid信息。 - -7. client侧通信组件收到响应数据: - 1. 进行CR埋点(Client Receive)。 - 2. 发送同步调用响应(transact reply)到client侧业务模块。 - -8. client侧业务模块进行同步调用响应处理。 -9. client侧业务模块在流程结束时调用end\(\)接口停止调用链跟踪。 +1. client侧业务模块调用begin()接口启动调用链跟踪。 -## 开发实例 +2. client侧业务模块发起同步调用transact,到client侧通信组件。 -### C++接口实例 +3. client侧通信组件: + 1. 从当前线程TLS中获取traceid。 + 2. 生成子调用分支(child traceid)。 + 3. 将child traceid写入同步调用通信数据(transaction data)中。 + 4. 进行CS埋点(Client Send)。 + 5. 将通信数据发送到server侧通信组件。 -1. 源代码开发 +4. server侧通信组件收到通信数据: + 1. 从数据消息包中取出traceid。 + 2. 将traceid设置到当前线程TLS中。 + 3. 进行SR埋点(Server Receive)。 + 4. 然后进行同步调用回调(onTransact)到server侧业务模块。 - 在类定义头文件或者类实现源文件中,包含hitrace头文件: +5. server侧业务模块进行服务处理,处理完毕发送处理结果(transact reply)到通信组件。 - ``` - #include "hitrace/trace.h" - ``` +6. server侧通信组件: + 1. 进行SS埋点(Server Send)。 + 2. 将响应数据发送到client侧通信组件。 + 3. 清除当前线程TLS中的traceid信息。 - 在业务类实现源文件中使用(启动/结束跟踪): +7. client侧通信组件收到响应数据: + 1. 进行CR埋点(Client Receive)。 + 2. 发送同步调用响应(transact reply)到client侧业务模块。 - ``` - using namespace OHOS::HiviewDFX; - HiTraceId traceId = HiTrace::Begin("MyServiceFlow", HITRACE_FLAG_DEFAULT); - ...... - HiTrace::End(traceId); - ``` +8. client侧业务模块进行同步调用响应处理。 -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: +9. client侧业务模块在流程结束时调用end()接口停止调用链跟踪。 - ``` - external_deps = [ "hiviewdfx:libhitrace" ] - ``` +## 开发实例 -### C接口实例 -1. 源代码开发 +### C++接口实例 - 在源文件中,包含hitrace头文件: +1. 源代码开发 + 在类定义头文件或者类实现源文件中,包含hitrace头文件: + + ``` + #include "hitrace/trace.h" + ``` - ``` - #include "hitrace/trace.h" - ``` + 在业务类实现源文件中使用(启动/结束跟踪): + + ``` + using namespace OHOS::HiviewDFX; + HiTraceId traceId = HiTrace::Begin("MyServiceFlow", HITRACE_FLAG_DEFAULT); + ...... + HiTrace::End(traceId); + ``` - 在业务类实现源文件中使用(启动/结束跟踪): +2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + external_deps = [ "hiviewdfx:libhitrace" ] + ``` - ``` - HiTraceIdStruct traceId = HiTraceBegin("MyServiceFlow", HITRACE_FLAG_DEFAULT); - ...... - HiTraceEnd(traceId); - ``` -2. 编译设置,在BUILD.gn里增加子系统SDK依赖: +### C接口实例 - ``` - external_deps = [ "hiviewdfx:libhitrace" ] - ``` +1. 源代码开发 + 在源文件中,包含hitrace头文件: + + ``` + #include "hitrace/trace.h" + ``` + 在业务类实现源文件中使用(启动/结束跟踪): + + ``` + HiTraceIdStruct traceId = HiTraceBegin("MyServiceFlow", HITRACE_FLAG_DEFAULT); + ...... + HiTraceEnd(traceId); + ``` +2. 编译设置,在BUILD.gn里增加子系统SDK依赖: + + ``` + external_deps = [ "hiviewdfx:libhitrace" ] + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-overview.md b/zh-cn/device-dev/subsystems/subsys-dfx-overview.md index 4d85164703418f35a1f5306d61130454cc079e3f..6f40ac19422d7c7520eb35febbe72356d7d74e1f 100755 --- a/zh-cn/device-dev/subsystems/subsys-dfx-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx-overview.md @@ -1,18 +1,22 @@ -# DFX概述 +# DFX概述 -- [基本概念](#section5635178134811) -在OpenHarmony中,DFX\([Design for X](https://en.wikipedia.org/wiki/Design_for_X)\)是为了提升质量属性的软件设计,目前包含的内容主要有:DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性。 +## 简介 + +在OpenHarmony中,DFX([Design for X](https://en.wikipedia.org/wiki/Design_for_X))是为了提升质量属性的软件设计,目前包含的内容主要有:DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性。 提供以下功能: -- HiLog流水日志,轻量系统类设备(参考内存≥128KB)、小型系统类设备(参考内存≥1MB)、标准系统类设备(参考内存≥128MB)适用。 +- HiLog流水日志,轻量系统类设备(参考内存≥128KiB)、小型系统类设备(参考内存≥1MiB)、标准系统类设备(参考内存≥128MB)适用。 + +- HiTrace分布式跟踪,标准系统类设备(参考内存≥128MiB)适用。 + +- HiCollie卡死故障检测,标准系统类设备(参考内存≥128MiB)适用。 -- HiTrace分布式跟踪,标准系统类设备(参考内存≥128MB)适用。 -- HiCollie卡死故障检测,标准系统类设备(参考内存≥128MB)适用。 -- HiSysEvent系统事件埋点,标准系统类设备(参考内存≥128MB)适用。 +- HiSysEvent系统事件埋点,标准系统类设备(参考内存≥128MiB)适用。 -## 基本概念 + +## 基本概念 **流水日志:** @@ -33,4 +37,3 @@ **系统事件:** 是OpenHarmony系统某种状态产生的一种标识,通过定义各种事件用于分析系统的状态变化情况。 - diff --git a/zh-cn/device-dev/subsystems/subsys-dfx.md b/zh-cn/device-dev/subsystems/subsys-dfx.md index 2fdce0127f362ed08c6148f268b6585aaaa55ea9..8b9776195470a88e6df782171eff1ae82e83e4a3 100644 --- a/zh-cn/device-dev/subsystems/subsys-dfx.md +++ b/zh-cn/device-dev/subsystems/subsys-dfx.md @@ -1,25 +1,15 @@ -# DFX +# DFX -- **[DFX概述](subsys-dfx-overview.md)** -- **[HiLog开发指导](subsys-dfx-hilog-rich.md)** -- **[HiLog\_Lite开发指导](subsys-dfx-hilog-lite.md)** +- **[DFX概述](subsys-dfx-overview.md)** -- **[HiTrace开发指导](subsys-dfx-hitrace.md)** +- **[HiLog开发指导](subsys-dfx-hilog-rich.md)** -- **[HiCollie开发指导](subsys-dfx-hicollie.md)** +- **[HiLog_Lite开发指导](subsys-dfx-hilog-lite.md)** -- **[HiSysEvent开发指导](subsys-dfx-hisysevent.md)** - - - [HiSysEvent打点配置指导](subsys-dfx-hisysevent-logging-config.md) - - - [HiSysEvent打点指导](subsys-dfx-hisysevent-logging.md) - - - [HiSysEvent订阅指导](subsys-dfx-hisysevent-listening.md) - - - [HiSysEvent查询指导](subsys-dfx-hisysevent-query.md) - - - [HiSysEvent工具使用指导](subsys-dfx-hisysevent-tool.md) +- **[HiTrace开发指导](subsys-dfx-hitrace.md)** +- **[HiCollie开发指导](subsys-dfx-hicollie.md)** +- **[HiSysEvent开发指导](subsys-dfx-hisysevent.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md b/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md index 8332aa22bd87afd1e6d8e6dff632b189cc0c19ea..db0fdc5a8b35378e39a9952310afc7d126befcd6 100644 --- a/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md @@ -1,190 +1,85 @@ -# 动画开发指导 +# 动画开发指导 -- [使用场景](#section726685714018) -- [接口说明](#section85794718418) -- [开发步骤](#section14101161317435) -## 使用场景 +## 使用场景 UI动画通过task处理机制每个tick调用一下用户设置的callback函数来实现,具体实现为AnimatorManager、Animator、AnimatorCallback三个类实现。 -- AnimatorManager:AnimatorManager为单例,在Init函数执行时将自己注册到系统task回调函数中,系统task机制保证每个tick会调用一下AnimatorManager的callback函数,同时AnimatorManager用来管理Animator实例。 -- Animator:Animator中可以设置动画相关的属性,包括动画的起止时间,动画开始和停止,动画状态的设置和获取等。 -- AnimatorCallback:具体每一个tick动画所要做的内容在AnimatorCallback类中实现,开发者需要自己实现Callback方法,动画执行时在Callback实现相应功能。 - -## 接口说明 - -**表 1** 动画接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

子模块

-

方法

-

功能

-

Animator

-

void Start ()

-

动画开始

-

Animator

-

void Stop ()

-

动画停止

-

Animator

-

void Pause ()

-

动画暂停

-

Animator

-

void Resume ()

-

动画恢复

-

Animator

-

uint8_t GetState () const

-

获取动画当前状态

-

Animator

-

void SetState (uint8_t state)

-

设置动画当前状态

-

Animator

-

uint32_t GetTime () const

-

获取动画总持续时间

-

Animator

-

void SetTime (uint32_t time)

-

设置动画总持续时间

-

Animator

-

uint32_t GetRunTime () const

-

获取动画当前已经持续的时间

-

Animator

-

void SetRunTime (uint32_t runTime)

-

设置动画当前已经持续的时间

-

Animator

-

bool IsRepeat () const

-

获取动画是否循环播放

-

AnimatorCallback

-

virtual void Callback (UIView *view)=0

-

由用户实现,动画回调函数

-

AnimatorCallback

-

virtual void OnStop(UIView& view) {}

-

由用户实现,动画停止后的回调函数

-

AnimatorManager

-

static AnimatorManager* GetInstance()

-

获取AnimatorManager实例

-

AnimatorManager

-

void Add (Animator *animator)

-

添加动画

-

AnimatorManager

-

void Remove(const Animator* animator);

-

删除动画

-
- -## 开发步骤 - -1. 实现AnimatorCallback的回调函数。 - - ``` - class AnimatorCallbackDemo : public OHOS::AnimatorCallback { - public: - AnimatorCallbackDemo(int16_t startPos, int16_t endPos, uint16_t time) - : start_(startPos), end_(endPos), time_(time), curTime_(0) {} +- AnimatorManager:AnimatorManager为单例,在Init函数执行时将自己注册到系统task回调函数中,系统task机制保证每个tick会调用一下AnimatorManager的callback函数,同时AnimatorManager用来管理Animator实例。 + +- Animator:Animator中可以设置动画相关的属性,包括动画的起止时间,动画开始和停止,动画状态的设置和获取等。 + +- AnimatorCallback:具体每一个tick动画所要做的内容在AnimatorCallback类中实现,开发者需要自己实现Callback方法,动画执行时在Callback实现相应功能。 + + +## 接口说明 + + **表1** 动画接口说明 + +| 子模块 | 方法 | 功能 | +| -------- | -------- | -------- | +| Animator | void  Start () | 动画开始 | +| Animator | void  Stop () | 动画停止 | +| Animator | void  Pause () | 动画暂停 | +| Animator | void  Resume () | 动画恢复 | +| Animator | uint8_t  GetState () const | 获取动画当前状态 | +| Animator | void  SetState (uint8_t state) | 设置动画当前状态 | +| Animator | uint32_t  GetTime () const | 获取动画总持续时间 | +| Animator | void  SetTime (uint32_t time) | 设置动画总持续时间 | +| Animator | uint32_t  GetRunTime () const | 获取动画当前已经持续的时间 | +| Animator | void  SetRunTime (uint32_t runTime) | 设置动画当前已经持续的时间 | +| Animator | bool  IsRepeat () const | 获取动画是否循环播放 | +| AnimatorCallback | virtual void  Callback (UIView \*view)=0 | 由用户实现,动画回调函数 | +| AnimatorCallback | virtual void OnStop(UIView& view) {} | 由用户实现,动画停止后的回调函数 | +| AnimatorManager | static AnimatorManager\* GetInstance() | 获取AnimatorManager实例 | +| AnimatorManager | void  Add (Animator \*animator) | 添加动画 | +| AnimatorManager | void Remove(const Animator\* animator); | 删除动画 | + + +## 开发步骤 + +1. 实现AnimatorCallback的回调函数。 - virtual void Callback(OHOS::UIView* view) - { - curTime_++; - int16_t pos = EasingEquation::CubicEaseIn(start_, end_, curTime_, time_); - view->Invalidate(); - view->SetPosition(pos, view->GetY()); - view->Invalidate(); - } - protected: - int16_t start_; - int16_t end_; - uint16_t time_; - uint16_t curTime_; - }; - ``` - -2. 将AnimatorCallback添加到Animator中。 - - ``` - UIImageView* image = new UIImageView(); - image->SetSrc("..\\config\\images\\A021_001.bin"); - image->SetPosition(0, 50); - AnimatorCallbackDemo* callback = new AnimatorCallbackDemo(0, 338, 60); - Animator* animator = new Animator(callback, image, 0, true); - ``` - -3. 将Animator添加到AnimatorManager中。 - - ``` - AnimatorManager::GetInstance()->Add(animator); - ``` - -4. 点击下图下方的按钮,检查对应的动画运行效果。 - - **图 1** 动画实现效果图 - ![](figure/动画实现效果图.gif "动画实现效果图") + ``` + class AnimatorCallbackDemo : public OHOS::AnimatorCallback { + public: + AnimatorCallbackDemo(int16_t startPos, int16_t endPos, uint16_t time) + : start_(startPos), end_(endPos), time_(time), curTime_(0) {} + + virtual void Callback(OHOS::UIView* view) + { + curTime_++; + int16_t pos = EasingEquation::CubicEaseIn(start_, end_, curTime_, time_); + view->Invalidate(); + view->SetPosition(pos, view->GetY()); + view->Invalidate(); + } + protected: + int16_t start_; + int16_t end_; + uint16_t time_; + uint16_t curTime_; + }; + ``` + +2. 将AnimatorCallback添加到Animator中。 + + ``` + UIImageView* image = new UIImageView(); + image->SetSrc("..\\config\\images\\A021_001.bin"); + image->SetPosition(0, 50); + AnimatorCallbackDemo* callback = new AnimatorCallbackDemo(0, 338, 60); + Animator* animator = new Animator(callback, image, 0, true); + ``` + +3. 将Animator添加到AnimatorManager中。 + + ``` + AnimatorManager::GetInstance()->Add(animator); + ``` +4. 点击下图下方的按钮,检查对应的动画运行效果。 + + **图1** 动画实现效果图 + ![zh-cn_image_0000001055504010](figures/zh-cn_image_0000001055504010.gif) diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-common-guide.md b/zh-cn/device-dev/subsystems/subsys-graphics-common-guide.md index d9b0d48c87587588b3bbd4b39c83e636001dcbd6..01fb40c66d33ca6a60f1d2cd5c056be01d96eae2 100644 --- a/zh-cn/device-dev/subsystems/subsys-graphics-common-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-graphics-common-guide.md @@ -1,555 +1,381 @@ -# 普通组件开发指导 - -- [UIButton](#section145353310214) -- [使用场景](#section1169616141577) -- [接口说明](#section341211538315) -- [开发步骤](#section22501726193214) -- [UIImageView](#section19523161611259) -- [使用场景](#section1274484210400) -- [接口说明](#section74981992411) -- [开发步骤(自适应)](#section144341333134114) -- [开发步骤(平铺模式)](#section97178160421) -- [UILabel](#section16588132012911) -- [使用场景](#section6870195634218) -- [接口说明](#section2012714510433) -- [开发步骤(默认模式)](#section83221538114410) -- [开发步骤(背景色和透明度)](#section933360204510) -- [开发步骤(字符间距)](#section19447826124518) -- [开发步骤(大小自适应)](#section101711842154617) -- [开发步骤(省略号模式)](#section1249519410471) -- [开发步骤(滚动模式)](#section15643122618478) +# 普通组件开发指导 + 普通组件均继承于基类UIView,不可以添加子组件,常用的普通组件有button、image、label等。 -**图 1** 普通组件树结构 -![](figure/普通组件树结构.png "普通组件树结构") + + **图1** 普通组件树结构 + + ![zh-cn_image_0000001057990796](figures/zh-cn_image_0000001057990796.png) + + UIView为基础类,UIAbstractProgress、UIArcLabel(旋转字体)、UIButton(按键)、UICanvas(画布)、UILabel(字体)、UIImageView(图片)从UIView继承。UIBoxProgress、UICircleProgress从UIAbstractProgress继承,UILabelButton和UIRepeatButton从UIButton继承,UIImageAnimatorView和UITextureMapper从UIImageView继承。 -## UIButton -## 使用场景 +## UIButton + + +### 使用场景 UIButton组件,提供可点击功能,同时可设置不同状态下样式。 -## 接口说明 - -**表 1** button接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetImageSrc (const char *defaultImgSrc, const char *triggeredImgSrc)

-

设置button图片

-

void SetImagePosition (const int16_t x, const int16_t y)

-

设置button图片位置

-

int16_t GetImageX () const

-

获取图片X坐标

-

int16_t GetImageY () const

-

获取图片Y坐标

-

const ImageInfo* GetCurImageSrc() const

-

获取当前状态图片

-

Style& GetStyleForState (ButtonState state)

-

设置button当前状态的style

-

voidSetStyleForState (const Style &style, ButtonState state)

-

设置button指定状态的style

-

void Disable ()

-

去使能button

-

void Enable ()

-

使能button

-
- -## 开发步骤 - -1. 实现点击事件。 - - ``` - class TestBtnOnClickListener : public OHOS::UIView::OnClickListener { - bool OnClick(UIView& view, const ClickEvent& event) override - { - int16_t width = view.GetWidth() + 10; - int16_t height = view.GetHeight() + 10; - view.Resize(width, height); - view.Invalidate(); - return true; - } - }; - ``` - -2. 创建一个UIButton。 - - ``` - UIButton* button = new UIButton(); - button->SetPosition(50, 50); - button->SetWidth(100); - button->SetHeight(50); - ``` - -3. 给UIButton注册点击事件回调。 - - ``` - button->SetOnClickListener(new TestBtnOnClickListener()); - ``` - -4. 检查Button点击效果如下图所示,Button逐渐变大。 - - **图 2** UIButton点击效果 - ![](figure/UIButton点击效果.gif "UIButton点击效果") - - -## UIImageView - -## 使用场景 -图片组件,提供图片显示,透明度设置,图片旋转、缩放功能。支持的图片格式为RGB565、RGB888、RGBA8888、PNG、JPG。 +### 接口说明 -## 接口说明 - -**表 2** image接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetSrc (const char *src)

-

设置二进制图片路径

-

void SetSrc (const ImageInfo *src)

-

设置图片指针

-

void SetAutoEnable (bool enable)

-

设置组件大小跟随image大小变化

-

const void* GetSrcType () const

-

获取图片类型

-

bool GetAutoEnable () const

-

获取组件大小是否跟随image大小变化

-

void SetBlurLevel(BlurLevel level)

-

设置模糊等级

-

BlurLevel GetBlurLevel() const

-

获取模糊等级

-

void SetTransformAlgorithm(TransformAlgorithm algorithm)

-

设置旋转算法

-

TransformAlgorithm GetTransformAlgorithm() const

-

获取旋转算法

-
- -## 开发步骤(自适应) - -1. 创建一个UIImageView。 - - ``` - UIImageView* imageView = new UIImageView(); - imageView->SetPosition(0, 30); - ``` - -2. 设置二进制格式的图片。 - - ``` - imageView->SetSrc("..\\config\\images\\A021_001.bin"); - ``` - -3. 检查UIImageView控件大小与图片相同。 - - **图 3** 自适应模式图片效果图 - ![](figure/自适应模式图片效果图.png "自适应模式图片效果图") - - -## 开发步骤(平铺模式) - -1. 创建一个UIImageView。 - - ``` - UIImageView* imageView = new UIImageView(); - imageView->SetPosition(0, 30); - ``` - -2. 设置图片。 - - ``` - imageView->SetSrc("..\\config\\images\\A021_001.bin"); - ``` - -3. 取消图片自适应,设置图片大小,平铺显示效果。 - - ``` - imageView->SetAutoEnable(false); - imageView->Resize(454, 150); - ``` - -4. 检查UIImageView控件显示为平铺效果。 - - **图 4** 平铺模式图片效果图 - ![](figure/平铺模式图片效果图.png "平铺模式图片效果图") - - -## UILabel - -## 使用场景 + **表1** button接口说明 + +| 方法 | 功能 | +| -------- | -------- | +| void SetImageSrc (const char \*defaultImgSrc, const char \*triggeredImgSrc) | 设置button图片 | +| void SetImagePosition (const int16_t x, const int16_t y) | 设置button图片位置 | +| int16_t GetImageX () const | 获取图片X坐标 | +| int16_t GetImageY () const | 获取图片Y坐标 | +| const ImageInfo\* GetCurImageSrc() const | 获取当前状态图片 | +| Style&  GetStyleForState (ButtonState state) | 设置button当前状态的style | +| voidSetStyleForState (const Style &style, ButtonState state) | 设置button指定状态的style | +| void Disable () | 去使能button | +| void Enable () | 使能button | -标签(label)是在一块区域上显示文本字符串的组件,可设置区域背景色、文字的显示样式和长文本的显示效果等。 -## 接口说明 - -**表 3** label接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetText(const char* text);

-

设置文字

-

const char* GetText() const;

-

获取text

-

void SetLineBreakMode(const uint8_t lineBreakMode);

-

设置label模式,例如截断,自动扩展等。

-

uint8_t GetLineBreakMode() const

-

获取label模式

-

void SetTextColor(ColorType color)

-

设置文本颜色

-

ColorType GetTextColor() const

-

获取文本颜色

-

void SetAlign(UITextLanguageAlignment horizontalAlign,

-

UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP);

-

设置文本对齐方式

-

UITextLanguageAlignment GetHorAlign() const

-

获取文本水平对齐方式

-

UITextLanguageAlignment GetVerAlign() const

-

获取文本竖直对齐方式

-

void SetDirect(UITextLanguageDirect direct)

-

设置文本显示方向

-

UITextLanguageDirect GetDirect() const

-

获取文本显示方向

-

void SetFontId(uint8_t fontId);

-

设置动态字体id

-

uint8_t GetFontId() const

-

获取动态字体id

-

void SetFont(const char *name, uint8_t size);

-

设置字的名字和大小

-

void SetAnimatorSpeed(uint16_t animSpeed);

-

设置字体旋转的速度

-

uint16_t GetTextWidth();

-

获取字体的宽

-

uint16_t GetTextHeight();

-

获取字体的高

-

void SetRollStartPos(int16_t pos)

-

设置旋转的位置

-

int16_t GetRollStartPos() const

-

获取旋转的位置

-

void SetTextRotation(LabelRotateDegree angle)

-

设置文本旋转角度枚举值

-

LabelRotateDegree GetTextRotation() const

-

获取文本旋转角度枚举值

-

uint16_t GetTextRotateDegree() const

-

获取文本旋转角度数值

-
- -## 开发步骤(默认模式) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置文本数据。 - - ``` - label->SetText("label"); - ``` - -4. 检查label大小和显示效果正常,如下图所示。 - - ![](figure/zh-cn_image_0000001051782526.png) - - -## 开发步骤(背景色和透明度) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置背景颜色及透明度效果。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_BACKGROUND_OPA, 127); - label->SetText("Label"); - ``` - -4. 检查label背景色为Gray,如下图所示。 - - ![](figure/zh-cn_image_0000001052582522.png) - - -## 开发步骤(字符间距) +### 开发步骤 -1. 创建label,设置大小和位置信息。 +1. 实现点击事件。 + + ``` + class TestBtnOnClickListener : public OHOS::UIView::OnClickListener { + bool OnClick(UIView& view, const ClickEvent& event) override + { + int16_t width = view.GetWidth() + 10; + int16_t height = view.GetHeight() + 10; + view.Resize(width, height); + view.Invalidate(); + return true; + } + }; + ``` - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` +2. 创建一个UIButton。 + + ``` + UIButton* button = new UIButton(); + button->SetPosition(50, 50); + button->SetWidth(100); + button->SetHeight(50); + ``` -2. 设置字形信息。 +3. 给UIButton注册点击事件回调。 + + ``` + button->SetOnClickListener(new TestBtnOnClickListener()); + ``` - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` +4. 检查Button点击效果如下图所示,Button逐渐变大。 + + **图2** UIButton点击效果 + + ![zh-cn_image_0000001151367836](figures/zh-cn_image_0000001151367836.gif) -3. 设置字体颜色和字间距效果。 - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_LETTER_SPACE, 5); - label->SetText("Label"); - ``` +## UIImageView -4. 检查label字符间距为5,如下图所示。 - ![](figure/zh-cn_image_0000001052942531.png) +### 使用场景 +图片组件,提供图片显示,透明度设置,图片旋转、缩放功能。支持的图片格式为RGB565、RGB888、RGBA8888、PNG、JPG。 -## 开发步骤(大小自适应) -当文本过长时,可根据文本信息自动调整label组件大小,也可以设置文本截断或者文本滚动效果。 +### 接口说明 -1. 创建label,设置大小和位置信息。 + **表2** image接口说明 - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` +| 方法 | 功能 | +| -------- | -------- | +| void SetSrc (const char \*src) | 设置二进制图片路径 | +| void SetSrc (const ImageInfo \*src) | 设置图片指针 | +| void SetAutoEnable (bool enable) | 设置组件大小跟随image大小变化 | +| const void\* GetSrcType () const | 获取图片类型 | +| bool GetAutoEnable () const | 获取组件大小是否跟随image大小变化 | +| void SetBlurLevel(BlurLevel level) | 设置模糊等级 | +| BlurLevel GetBlurLevel() const | 获取模糊等级 | +| void SetTransformAlgorithm(TransformAlgorithm algorithm) | 设置旋转算法 | +| TransformAlgorithm GetTransformAlgorithm() const | 获取旋转算法 | -2. 设置字形信息。 - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` +### 开发步骤(自适应) -3. 设置字体颜色为Gray,组件大小自适应文本内容。 +1. 创建一个UIImageView。 + + ``` + UIImageView* imageView = new UIImageView(); + imageView->SetPosition(0, 30); + ``` - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); - label->SetText("123\n567890"); - ``` +2. 设置二进制格式的图片。 + + ``` + imageView->SetSrc("..\\config\\images\\A021_001.bin"); + ``` -4. 检查label大小自适应文本内容,如下图所示。 +3. 检查UIImageView控件大小与图片相同。 + + **图3** 自适应模式图片效果图 - ![](figure/zh-cn_image_0000001052782555.png) + ![zh-cn_image_0000001151527640](figures/zh-cn_image_0000001151527640.png) -## 开发步骤(省略号模式) +### 开发步骤(平铺模式) -省略号模式指文本内容显示不下时,在末尾显示省略号。 +1. 创建一个UIImageView。 + + ``` + UIImageView* imageView = new UIImageView(); + imageView->SetPosition(0, 30); + ``` -1. 创建label,设置大小和位置信息。 +2. 设置图片。 + + ``` + imageView->SetSrc("..\\config\\images\\A021_001.bin"); + ``` - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` +3. 取消图片自适应,设置图片大小,平铺显示效果。 + + ``` + imageView->SetAutoEnable(false); + imageView->Resize(454, 150); + ``` -2. 设置字形信息。 +4. 检查UIImageView控件显示为平铺效果。 + + **图4** 平铺模式图片效果图 + + ![zh-cn_image_0000001197407405](figures/zh-cn_image_0000001197407405.png) - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` -3. 设置换行模式为DOT模式 +## UILabel - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); - label->SetText("123567890"); - ``` -4. 检查label DOT模式效果,如下图所示,末尾显示省略号。 +### 使用场景 - ![](figure/zh-cn_image_0000001052662559.png) +标签(label)是在一块区域上显示文本字符串的组件,可设置区域背景色、文字的显示样式和长文本的显示效果等。 -## 开发步骤(滚动模式) +### 接口说明 + + **表3** label接口说明 + +| 方法 | 功能 | +| -------- | -------- | +| void SetText(const char\* text); | 设置文字 | +| const char\* GetText() const; | 获取text | +| void SetLineBreakMode(const uint8_t lineBreakMode); | 设置label模式,例如截断,自动扩展等。 | +| uint8_t GetLineBreakMode() const | 获取label模式 | +| void SetTextColor(ColorType color) | 设置文本颜色 | +| ColorType GetTextColor() const | 获取文本颜色 | +| void SetAlign(UITextLanguageAlignment horizontalAlign,
UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP); | 设置文本对齐方式 | +| UITextLanguageAlignment GetHorAlign() const | 获取文本水平对齐方式 | +| UITextLanguageAlignment GetVerAlign() const | 获取文本竖直对齐方式 | +| void SetDirect(UITextLanguageDirect direct) | 设置文本显示方向 | +| UITextLanguageDirect GetDirect() const | 获取文本显示方向 | +| void SetFontId(uint8_t fontId); | 设置动态字体id | +| uint8_t GetFontId() const | 获取动态字体id | +| void SetFont(const char \*name, uint8_t size); | 设置字的名字和大小 | +| void SetAnimatorSpeed(uint16_t animSpeed); | 设置字体旋转的速度 | +| uint16_t GetTextWidth(); | 获取字体的宽 | +| uint16_t GetTextHeight(); | 获取字体的高 | +| void SetRollStartPos(int16_t pos) | 设置旋转的位置 | +| int16_t GetRollStartPos() const | 获取旋转的位置 | +| void SetTextRotation(LabelRotateDegree angle) | 设置文本旋转角度枚举值 | +| LabelRotateDegree GetTextRotation() const | 获取文本旋转角度枚举值 | +| uint16_t GetTextRotateDegree() const | 获取文本旋转角度数值 | + + +### 开发步骤(默认模式) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置文本数据。 + + ``` + label->SetText("label"); + ``` + +4. 检查label大小和显示效果正常,如下图所示。 + + **图5** 默认模式显示效果图 + + ![zh-cn_image_0000001154150600](figures/zh-cn_image_0000001154150600.png) + + +### 开发步骤(背景色和透明度) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置背景颜色及透明度效果。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_BACKGROUND_OPA, 127); + label->SetText("Label"); + ``` + +4. 检查label背景色为Gray,如下图所示。 + + **图6** 设置背景色显示效果图 + + ![zh-cn_image_0000001154150422](figures/zh-cn_image_0000001154150422.png) + + +### 开发步骤(字符间距) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置字体颜色和字间距效果。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_LETTER_SPACE, 5); + label->SetText("Label"); + ``` + +4. 检查label字符间距为5,如下图所示。 + + **图7** 设置文字颜色、字间距显示效果图 + + ![zh-cn_image_0000001200109969](figures/zh-cn_image_0000001200109969.png) + + +### 开发步骤(大小自适应) -文本滚动显示。 +当文本过长时,可根据文本信息自动调整label组件大小,也可以设置文本截断或者文本滚动效果。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置字体颜色为Gray,组件大小自适应文本内容。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); + label->SetText("123\n567890"); + ``` -1. 创建label,设置大小和位置信息。 +4. 检查label大小自适应文本内容,如下图所示。 - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` + **图8** 自适应模式显示效果图 -2. 设置字形信息。 + ![zh-cn_image_0000001200029923](figures/zh-cn_image_0000001200029923.png) - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` -3. 设置换行模式为滚动模式 +### 开发步骤(省略号模式) - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_BACKGROUND_OPA, 127); - label->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); - label->SetText("123567890"); - ``` +省略号模式指文本内容显示不下时,在末尾显示省略号。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` -4. 检查label滚动模式效果,如下图所示。 +3. 设置换行模式为DOT模式 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); + label->SetText("123567890"); + ``` - ![](figure/20200721-223604(eSpace).gif) +4. 检查label DOT模式效果,如下图所示,末尾显示省略号。 + + **图9** DOT模式显示效果图 + ![zh-cn_image_0000001200029619](figures/zh-cn_image_0000001200029619.png) + +### 开发步骤(滚动模式) + +文本滚动显示。 +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置换行模式为滚动模式 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_BACKGROUND_OPA, 127); + label->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); + label->SetText("123567890"); + ``` + +4. 检查label滚动模式效果,如下图所示。 + + **图10** 滚动模式显示效果图 + + ![zh-cn_image_0000001200109273](figures/zh-cn_image_0000001200109273.gif) diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-container-guide.md b/zh-cn/device-dev/subsystems/subsys-graphics-container-guide.md index 52da564931e3f8ff58c2e0379c98dbcbc993aa58..145fce508b5208b2a8dc7941b87ac67960ca9288 100644 --- a/zh-cn/device-dev/subsystems/subsys-graphics-container-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-graphics-container-guide.md @@ -1,228 +1,129 @@ -# 容器类组件开发指导 +# 容器类组件开发指导 -- [UIViewGroup](#section145471898812) -- [使用场景](#section0916112362216) -- [接口说明](#section12641756192212) -- [开发步骤](#section5412161692311) -- [UIScrollView](#section174961523161315) -- [使用场景](#section8937101902413) -- [接口说明](#section14789133142420) -- [开发步骤](#section1769754422417) 容器类组件,指能包含其它UI组件的组件,容器类组件继承于UIViewGroup(带Add方法),基于实际组件的使用场景,将需要增加其他子组件的组件,放置到容器类继承结构下。如UIAnalogClock内,通常会Add需要的计步信息,时分秒图标等。 -**图 1** 普通容器类组件结构 -![](figure/普通容器类组件结构.png "普通容器类组件结构") + + **图1** 普通容器类组件结构 + + ![zh-cn_image_0000001057990780](figures/zh-cn_image_0000001057990780.png) + RootView、UIAbstractScroll、UIPicker组件从UIViewGroup继承,UIList、UIScrollView、UISwipeView组件从UIAbstractScroll继承。 -## UIViewGroup -## 使用场景 +## UIViewGroup + + +### 使用场景 UIViewGroup是容器类组件基类,实现增加、删除、插入等操作,通过增加方法可以添加子组件。普通容器类组件子组件需要设置位置信息,位置信息为相对父组件的相对坐标。组件树结构如下图: -**图 2** 组件树结构示意图 -![](figure/组件树结构示意图.png "组件树结构示意图") + **图2** 组件树结构示意图 + + ![zh-cn_image_0000001197407385](figures/zh-cn_image_0000001197407385.png) 往根节点rootView里添加ViewGroup1容器组件和View1组件,往ViewGroup1容器组件里再添加View2组件和ViewGroup2容器组件,在View1之后添加View3组件。 -- 关于渲染:容器类组件在渲染时会遍历所有子组件OnDraw方法,以达到刷新所有组件的目的。 -- 关于坐标:子组件位置信息为相对父组件的相对坐标,系统在渲染时计算绝对坐标并显示。 -- 关于树结构遍历:UIViewGroup提供如下方法实现遍历、查找、管理组件树。 - -## 接口说明 - -**表 1** ViewGroup接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

virtual void Add(UIView* view)

-

添加子组件

-

virtual void Insert(UIView* prevView, UIView* insertView)

-

插入子组件

-

virtual void Remove(UIView* view)

-

删除子组件

-

virtual void RemoveAll()

-

删除所有子组件

-

virtual void GetTargetView(const Point& point, UIView** last)

-

获取目标视图

-

virtual void MoveChildByOffset(int16_t x, int16_t y)

-

偏移子组件

-

UIView* GetChildrenHead() const

-

获取视图头节点

-

UIView* GetChildrenTail() const

-

获取视图最后那个节点

-

virtual UIView* GetChildById(const char* id) const override

-

通过id获取子视图

-
- -## 开发步骤 - -1. 构造button实例并设置坐标信息。 - - ``` - UILabelButton* btn1 = new UILabelButton(); - btn1->SetPosition(0, 0, 100, 50); - btn1->SetText("btn1"); - - UILabelButton* btn2 = new UILabelButton(); - btn2->SetPosition(50, 50, 100, 50); - btn2->SetText("btn2"); - - UILabelButton* btn3 = new UILabelButton(); - btn3->SetPosition(100, 100, 100, 50); - btn3->SetText("btn3"); - ``` - -2. 构造UIViewGroup实例,并设置坐标信息。 - - ``` - UIViewGroup* group = new UIViewGroup(); - group->SetPosition(0, 0, 300, 300); - ``` - -3. 使用Add方法添加Button实例到UIViewGroup。 - - ``` - group->Add(btn1); - group->Add(btn2); - group->Add(btn3); - ``` - -4. 检查ViewGroup效果如下图所示。 - - **图 3** ViewGroup添加view实例效果图 - ![](figure/ViewGroup添加view实例效果图.png "ViewGroup添加view实例效果图") - - -## UIScrollView - -## 使用场景 +- 关于渲染:容器类组件在渲染时会遍历所有子组件OnDraw方法,以达到刷新所有组件的目的。 + +- 关于坐标:子组件位置信息为相对父组件的相对坐标,系统在渲染时计算绝对坐标并显示。 + +- 关于树结构遍历:UIViewGroup提供如下方法实现遍历、查找、管理组件树。 + + +### 接口说明 + + **表1** ViewGroup接口说明 + +| 方法 | 功能 | +| -------- | -------- | +| virtual void Add(UIView\* view) | 添加子组件 | +| virtual void Insert(UIView\* prevView, UIView\* insertView) | 插入子组件 | +| virtual void Remove(UIView\* view) | 删除子组件 | +| virtual void RemoveAll() | 删除所有子组件 | +| virtual void GetTargetView(const Point& point, UIView\*\* last) | 获取目标视图 | +| virtual void MoveChildByOffset(int16_t x, int16_t y) | 偏移子组件 | +| UIView\* GetChildrenHead() const | 获取视图头节点 | +| UIView\* GetChildrenTail() const | 获取视图最后那个节点 | +| virtual UIView\* GetChildById(const char\* id) const override | 通过id获取子视图 | + + +### 开发步骤 + +1. 构造button实例并设置坐标信息。 + + ``` + UILabelButton* btn1 = new UILabelButton(); + btn1->SetPosition(0, 0, 100, 50); + btn1->SetText("btn1"); + + UILabelButton* btn2 = new UILabelButton(); + btn2->SetPosition(50, 50, 100, 50); + btn2->SetText("btn2"); + + UILabelButton* btn3 = new UILabelButton(); + btn3->SetPosition(100, 100, 100, 50); + btn3->SetText("btn3"); + ``` + +2. 构造UIViewGroup实例,并设置坐标信息。 + + ``` + UIViewGroup* group = new UIViewGroup(); + group->SetPosition(0, 0, 300, 300); + ``` + +3. 使用Add方法添加Button实例到UIViewGroup。 + + ``` + group->Add(btn1); + group->Add(btn2); + group->Add(btn3); + ``` + +4. 检查ViewGroup效果如下图所示。 + + **图3** ViewGroup添加view实例效果图 + + ![zh-cn_image_0000001197367485](figures/zh-cn_image_0000001197367485.png) + + +## UIScrollView + + +### 使用场景 UIScrollView提供可滑动的容器类组件,子组件可在触摸事件驱动下上下、左右滑动,并提供水平和垂直方向的游标显示功能。 -## 接口说明 - -**表 2** ScrollView接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void ScrollBy(int16_t xDistance, int16_t yDistance)

-

移动视图

-

void SetScrollbarWidth(uint8_t width)

-

设置滑动条宽度

-

void SetHorizontalScrollState(bool state)

-

设置水平滑动状态

-

bool GetHorizontalScrollState() const

-

获取水平是否可滑动状态

-

void SetVerticalScrollState(bool state)

-

设置垂直滑动状态

-

bool GetVerticalScrollState() const

-

获取垂直是否可滑动状态

-

void SetXScrollBarVisible(bool state)

-

设置X轴滑动条是否可见

-

void SetYScrollBarVisible(bool state)

-

设置Y轴滑动条是否可见

-

void RegisterScrollListener(OnScrollListener* scrollListener)

-

注册滑动事件回调类

-

void RefreshScrollBar()

-

刷新滑动条

-

virtual void OnScrollStart() {}

-

滚动开始回调函数

-

virtual void OnScrollEnd() {}

-

滚动结束回调函数

-

uint8_t GetScrollState() const

-

获取滚动状态

-

void SetScrollState(uint8_t state)

-

设置滚动状态

-
- -## 开发步骤 + +### 接口说明 + + **表2** ScrollView接口说明 + +| 方法 | 功能 | +| -------- | -------- | +| void ScrollBy(int16_t xDistance, int16_t yDistance) | 移动视图 | +| void SetScrollbarWidth(uint8_t width) | 设置滑动条宽度 | +| void SetHorizontalScrollState(bool state) | 设置水平滑动状态 | +| bool GetHorizontalScrollState() const | 获取水平是否可滑动状态 | +| void SetVerticalScrollState(bool state) | 设置垂直滑动状态 | +| bool GetVerticalScrollState() const | 获取垂直是否可滑动状态 | +| void SetXScrollBarVisible(bool state) | 设置X轴滑动条是否可见 | +| void SetYScrollBarVisible(bool state) | 设置Y轴滑动条是否可见 | +| void RegisterScrollListener(OnScrollListener\* scrollListener) | 注册滑动事件回调类 | +| void RefreshScrollBar() | 刷新滑动条 | +| virtual void OnScrollStart() {} | 滚动开始回调函数 | +| virtual void OnScrollEnd() {} | 滚动结束回调函数 | +| uint8_t GetScrollState() const | 获取滚动状态 | +| void SetScrollState(uint8_t state) | 设置滚动状态 | + + +### 开发步骤 添加两个button子组件,并显示水平、垂直方向游标。 + ``` scrollView* scroll = new UIScrollView(); scroll->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full); @@ -239,6 +140,6 @@ scroll->Add(button1); scroll->Add(button2); ``` -**图 4** 水平、垂直方向可滑动效果图 -![](figure/水平-垂直方向可滑动效果图.gif "水平-垂直方向可滑动效果图") - + **图4** 水平、垂直方向可滑动效果图 + + ![zh-cn_image_0000001151367828](figures/zh-cn_image_0000001151367828.gif) diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-layout-guide.md b/zh-cn/device-dev/subsystems/subsys-graphics-layout-guide.md index f03df38642b7f5892957eedc54a9648b0168e3be..721e05bd120d81de07e9baecd9584872508d3d69 100644 --- a/zh-cn/device-dev/subsystems/subsys-graphics-layout-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-graphics-layout-guide.md @@ -1,216 +1,157 @@ -# 布局容器类组件开发指导 - -- [UISwipeView](#section13631719181717) -- [使用场景](#section11299120102617) -- [接口说明](#section767434119261) -- [开发步骤(水平滑动,不可循环)](#section111911175287) -- [开发步骤(水平滑动,可循环)](#section1976914915282) -- [GridLayout](#section46819199173) -- [使用场景](#section831618247294) -- [接口说明](#section597214622912) -- [开发步骤](#section1418253410306) +# 布局容器类组件开发指导 -布局类容器组件由视图基础类组成,通过直接设置视图位置,可以达到嵌套和重叠布局的目的;通过设置布局类型和边距达到规格化布局子组件的目的;通过调用相关接口可实现根据父组件及兄弟节点布局视图的目的。 -## UISwipeView +布局类容器组件由视图基础类组成,通过直接设置视图位置,可以达到嵌套和重叠布局的目的;通过设置布局类型和边距达到规格化布局子组件的目的;通过调用相关接口可实现根据父组件及兄弟节点布局视图的目的。 -## 使用场景 -UISwipeView继承UIViewGroup,除提供容器类组件Add、Remove、Insert等方法外还提供按页面滑动功能,滑动结束后当前页面居中对齐显示。该组件分为水平方向和垂直方向,通过Add方法添加的子组件会根据Add的顺序和UISwipeView方向自动水平对齐或则垂直对齐。 +## UISwipeView -## 接口说明 - -**表 1** SwipeView接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetCurrentPage(uint16_t index);

-

设置当前页

-

uint16_t GetCurrentPage()

-

获取当前页

-

UIView* GetCurrentView() const

-

获取当前页组件

-

void SetOnSwipeListener(OnSwipeListener& onSwipeListener)

-

设置滑动回调类

-

void SetAnimatorTime(uint16_t time);

-

设置动画事件

-

void SetLoopState(bool loop)

-

设置是否循环

-

UIView* GetViewByIndex(uint16_t index);

-

通过index获取view

-
- -## 开发步骤(水平滑动,不可循环) - -1. 创建一个水平滑动的UISwipeView。 - - ``` - UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); - ``` - -2. 向UISwipeView中添加子组件。 - - ``` - UILabelButton* button1 = new UILabelButton(); - button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button1->SetText("button1"); - swipe->Add(button1); - UILabelButton* button2 = new UILabelButton(); - button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button2->SetText("button2"); - swipe->Add(button2); - UILabelButton* button3 = new UILabelButton(); - button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button3->SetText("button3"); - swipe->Add(button3); - ``` - -3. 检查实现效果,水平滑动,不可循环。 - - **图 1** UISwipeView水平滑动效果图 - - ![](figure/zh-cn_image_0000001053247975.gif) +### 使用场景 +UISwipeView继承UIViewGroup,除提供容器类组件Add、Remove、Insert等方法外还提供按页面滑动功能,滑动结束后当前页面居中对齐显示。该组件分为水平方向和垂直方向,通过Add方法添加的子组件会根据Add的顺序和UISwipeView方向自动水平对齐或则垂直对齐。 -## 开发步骤(水平滑动,可循环) -1. 创建一个水平滑动的UISwipeView并添加子组件。 +### 接口说明 - ``` - UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); - UILabelButton* button1 = new UILabelButton(); - button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button1->SetText("button1"); - swipe->Add(button1); - UILabelButton* button2 = new UILabelButton(); - button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button2->SetText("button2"); - swipe->Add(button2); - UILabelButton* button3 = new UILabelButton(); - button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button3->SetText("button3"); - swipe->Add(button3); - ``` + **表1** SwipeView接口说明 -2. 设置UISwipeView循环滑动。 +| 方法 | 功能 | +| -------- | -------- | +| void SetCurrentPage(uint16_t index); | 设置当前页 | +| uint16_t GetCurrentPage() | 获取当前页 | +| UIView\* GetCurrentView() const | 获取当前页组件 | +| void SetOnSwipeListener(OnSwipeListener& onSwipeListener) | 设置滑动回调类 | +| void SetAnimatorTime(uint16_t time); | 设置动画事件 | +| void SetLoopState(bool loop) | 设置是否循环 | +| UIView\* GetViewByIndex(uint16_t index); | 通过index获取view | - ``` - swipe->SetLoopState(true); - ``` -3. 检查实现效果,水平循环滑动。 +### 开发步骤(水平滑动,不可循环) - **图 2** UISwipeView水平滑动循环效果图 +1. 创建一个水平滑动的UISwipeView。 + + ``` + UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); + ``` + +2. 向UISwipeView中添加子组件。 + + ``` + UILabelButton* button1 = new UILabelButton(); + button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button1->SetText("button1"); + swipe->Add(button1); + UILabelButton* button2 = new UILabelButton(); + button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button2->SetText("button2"); + swipe->Add(button2); + UILabelButton* button3 = new UILabelButton(); + button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button3->SetText("button3"); + swipe->Add(button3); + ``` + +3. 检查实现效果,水平滑动,不可循环。 + + **图1** UISwipeView水平滑动效果图 + + ![zh-cn_image_0000001153991438](figures/zh-cn_image_0000001153991438.gif) + + +### 开发步骤(水平滑动,可循环) + +1. 创建一个水平滑动的UISwipeView并添加子组件。 + + ``` + UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); + UILabelButton* button1 = new UILabelButton(); + button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button1->SetText("button1"); + swipe->Add(button1); + UILabelButton* button2 = new UILabelButton(); + button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button2->SetText("button2"); + swipe->Add(button2); + UILabelButton* button3 = new UILabelButton(); + button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button3->SetText("button3"); + swipe->Add(button3); + ``` + +2. 设置UISwipeView循环滑动。 + + ``` + swipe->SetLoopState(true); + ``` + +3. 检查实现效果,水平循环滑动。 + + **图2** UISwipeView水平滑动循环效果图 + + ![zh-cn_image_0000001200110781](figures/zh-cn_image_0000001200110781.gif) + + +## GridLayout + + +### 使用场景 + +提供基础布局能力,可设置网格行数和列数,通过Add方法添加的子组件在调用LayoutChildren()方法后自动进行排列布局。 + + +### 接口说明 + + **表2** GridLayout接口说明 + +| 方法 | 功能 | +| -------- | -------- | +| void SetRows(const uint16_t& rows) | 设置行数 | +| void SetCols(const uint16_t& cols) | 设置列数 | +| void LayoutChildren(bool needInvalidate = false) | 布局子组件 | + + +### 开发步骤 + +1. 构造GridLayout并设置位置、大小信息。 + + ``` + GridLayout* layout_ = new GridLayout(); + layout_->SetPosition(0, g_y, HROIZONTAL_RESOLUTION, 200); + layout_->SetLayoutDirection(LAYOUT_HOR); + layout_->SetRows(2); + layout_->SetCols(2); + ``` + +2. 构造子组件button。 + + ``` + UILabelButton* bt1 = new UILabelButton(); + bt1->SetPosition(0,0,100,50); + bt1->SetText("bt1"); + UILabelButton* bt2 = new UILabelButton(); + bt2->SetPosition(0, 0, 100, 50); + bt2->SetText("bt2"); + UILabelButton* bt3 = new UILabelButton(); + bt3->SetPosition(0, 0, 100, 50); + bt3->SetText("bt3"); + UILabelButton* bt4 = new UILabelButton(); + bt4->SetPosition(0, 0, 100, 50); + bt4->SetText("bt4"); + ``` + +3. 添加子组件并调用LayoutChildren()。 + + ``` + layout_->Add(bt1); + layout_->Add(bt2); + layout_->Add(bt3); + layout_->Add(bt4); + layout_->LayoutChildren(); + ``` + +4. 检查button组件布局效果如下图所示。 + **图3** 设置2\*2网格并添加4个button组件进行布局 - ![](figure/zh-cn_image_0000001053207924.gif) - - -## GridLayout - -## 使用场景 - -提供基础布局能力,可设置网格行数和列数,通过Add方法添加的子组件在调用LayoutChildren\(\)方法后自动进行排列布局。 - -## 接口说明 - -**表 2** GridLayout接口说明 - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetRows(const uint16_t& rows)

-

设置行数

-

void SetCols(const uint16_t& cols)

-

设置列数

-

void LayoutChildren(bool needInvalidate = false)

-

布局子组件

-
- -## 开发步骤 - -1. 构造GridLayout并设置位置、大小信息。 - - ``` - GridLayout* layout_ = new GridLayout(); - layout_->SetPosition(0, g_y, HROIZONTAL_RESOLUTION, 200); - layout_->SetLayoutDirection(LAYOUT_HOR); - layout_->SetRows(2); - layout_->SetCols(2); - ``` - -2. 构造子组件button。 - - ``` - UILabelButton* bt1 = new UILabelButton(); - bt1->SetPosition(0,0,100,50); - bt1->SetText("bt1"); - UILabelButton* bt2 = new UILabelButton(); - bt2->SetPosition(0, 0, 100, 50); - bt2->SetText("bt2"); - UILabelButton* bt3 = new UILabelButton(); - bt3->SetPosition(0, 0, 100, 50); - bt3->SetText("bt3"); - UILabelButton* bt4 = new UILabelButton(); - bt4->SetPosition(0, 0, 100, 50); - bt4->SetText("bt4"); - ``` - -3. 添加子组件并调用LayoutChildren\(\)。 - - ``` - layout_->Add(bt1); - layout_->Add(bt2); - layout_->Add(bt3); - layout_->Add(bt4); - layout_->LayoutChildren(); - ``` - -4. 检查button组件布局效果如下图所示。 - - **图 3** 设置2\*2网格并添加4个button组件进行布局 - ![](figure/设置2-2网格并添加4个button组件进行布局.png "设置2-2网格并添加4个button组件进行布局") - - + ![zh-cn_image_0000001197367495](figures/zh-cn_image_0000001197367495.png) diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-overview.md b/zh-cn/device-dev/subsystems/subsys-graphics-overview.md index 49c1f610f94a083758882211c59ab8ca7b1f2150..3b1f71aba168cc2d739a86636f0514d618145e66 100755 --- a/zh-cn/device-dev/subsystems/subsys-graphics-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-graphics-overview.md @@ -1,49 +1,42 @@ -# 图形图像概述 +# 图形图像概述 -- [UI组件](#section1987017145112) -- [布局](#section662016231612) -- [动画](#section73736284117) -- [Input事件](#section672194012114) -- [渲染](#section14338859916) OpenHarmony图形系统,提供基础UI组件和容器类组件,包括button、image、label、list、animator、scroll view、swipe view、font、clock、chart、canvas、slider、layout等。同时提供截屏、导出组件树的DFX能力。模块内部实现组件渲染、动画、输入事件分发等功能。 -## UI组件 + +## UI组件 实现各种控件,如按钮、文本、进度条等各种基本控件。 提供界面切换、图片序列帧等复杂控件。 -## 布局 + +## 布局 实现网格布局、灵活布局(如居中、左对齐、右对齐)。 布局为一次性布局。布局函数每运行一次,会计算一次控件的位置,但是控件位置由其他方式改变时(如拖动),其他相关联的控件位置不会自动发生变化,需要重新调用一次布局函数。 -## 动画 + +## 动画 根据tick事件,由Task Manager周期性调用回调函数处理属性变化,然后触发刷新重新绘制组件,达到组件动画效果。 提供动画的开始/停止、暂停/恢复、创建/销毁等各种操作 ,用于实现动画效果。 -## Input事件 - -Input事件包括触摸屏触摸输入事件和物理按键输入事件,GUI引擎每运行一次,Input Manager会读取一次所有注册的硬件设备的输入,转化为各种事件供UI控件使用。 - -## 渲染 - -- 2D图形渲染 - - 实现线、矩形、三角形、弧线的绘制操作。 +## Input事件 -- 图像渲染 - - 实现各种类型图片的绘制API,如RGB565、RGB888、ARGB8888、PNG、JPG格式。 +Input事件包括触摸屏触摸输入事件和物理按键输入事件,GUI引擎每运行一次,Input Manager会读取一次所有注册的硬件设备的输入,转化为各种事件供UI控件使用。 -- 字体渲染 +## 渲染 - 支持矢量字体的实时绘制。 +- 2D图形渲染 + 实现线、矩形、三角形、弧线的绘制操作。 +- 图像渲染 + 实现各种类型图片的绘制API,如RGB565、RGB888、ARGB8888、PNG、JPG格式。 +- 字体渲染 + 支持矢量字体的实时绘制。 diff --git a/zh-cn/device-dev/subsystems/subsys-graphics.md b/zh-cn/device-dev/subsystems/subsys-graphics.md index 27feed54e9015bfebd8d33c9bbe1c90176937c85..c346c09cdd37185d0415612cbb15b537007d8581 100644 --- a/zh-cn/device-dev/subsystems/subsys-graphics.md +++ b/zh-cn/device-dev/subsystems/subsys-graphics.md @@ -1,13 +1,13 @@ -# 图形图像 +# 图形图像 -- **[图形图像概述](subsys-graphics-overview.md)** -- **[容器类组件开发指导](subsys-graphics-container-guide.md)** -- **[布局容器类组件开发指导](subsys-graphics-layout-guide.md)** +- **[图形图像概述](subsys-graphics-overview.md)** -- **[普通组件开发指导](subsys-graphics-common-guide.md)** +- **[容器类组件开发指导](subsys-graphics-container-guide.md)** -- **[动画开发指导](subsys-graphics-animation-guide.md)** +- **[布局容器类组件开发指导](subsys-graphics-layout-guide.md)** +- **[普通组件开发指导](subsys-graphics-common-guide.md)** +- **[动画开发指导](subsys-graphics-animation-guide.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md index 824d3461ea0f803b8e568fedc442c45c86592eee..34eda873e65c6e73b27876588fdaf09207b230e0 100644 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md @@ -1,115 +1,63 @@ -# 相机开发概述 +# 相机开发概述 -- [基本概念](#section175012297491) -- [运作机制](#section193961322175011) -## 基本概念 +## 基本概念 相机是OpenHarmony多媒体进程提供的服务之一,提供了相机的录像、预览、拍照功能,支持多用户并发取流。 在进行应用的开发前,开发者应了解以下基本概念: -- 视频帧 +- 视频帧 + 视频流指的是将一系列图片数据按照固定时间间隔排列形成的数据流,每一张图片数据成为一帧,这样的一帧称为视频帧。 - 视频流指的是将一系列图片数据按照固定时间间隔排列形成的数据流,每一张图片数据成为一帧,这样的一帧称为视频帧。 +- 帧速率(FPS: Frames Per Second) + 视频播放每秒钟刷新图片的速度,或是视频每秒的帧数,帧速率越高,视频的观感越流畅。 -- 帧速率\(FPS: Frames Per Second\) +- 分辨率 + 每一帧的图片信息都是由像素点组成的,分辨率描述了一张图片中像素点的个数。例如1920\*1080(1080P),是指图片宽1920像素,高1080像素。 - 视频播放每秒钟刷新图片的速度,或是视频每秒的帧数,帧速率越高,视频的观感越流畅。 -- 分辨率 +## 运作机制 - 每一帧的图片信息都是由像素点组成的,分辨率描述了一张图片中像素点的个数。例如1920\*1080\(1080P\),是指图片宽1920像素,高1080像素。 +- 多媒体服务进程 + 多媒体服务作为系统服务,在系统启动时由Init进程拉起,并初始化和分配媒体硬件资源(内存/显示硬件/图像传感器/编解码器等)。初始化过程解析配置文件,确定了多媒体各个服务的能力和资源上限,通常由OEM厂商通过配置文件进行配置。相机服务在多媒体进程初始化时有以下配置项: + - 内存池:所有媒体服务依赖于内存池中的内存轮转运行 + - 图像传感器:包括了传感器类型、分辨率、ISP等 + - 图像处理器:分辨率、码率、图像翻转等 + - 图像编码器:编码格式、码率、分辨率等 -## 运作机制 +- 关键类的解释 + 应用通过持有下面4个类,配置和使用Camera的功能,包括了Camera类和它的三个异步回调类,三类回调分别对应了不同类型的异步处理场景,详见下表。 + **表1** 关键类的解释 + + | 对象 | 用途 | 举例 | + | -------- | -------- | -------- | + | Camera | 对相机进行静态配置(通过配置类),触发相机基本功能 | 拍照/录像/预览 | + | CameraDeviceCallback | 处理相机硬件状态变化 | 可用/不可用 | + | CameraStateCallback | 处理camera自身状态变化 | 创建/释放 | + | FrameStateCallback | 处理帧状态的变化 | 拍照开始和结束/帧率发生变化 | -- 多媒体服务进程 +- 流的传递 + Surface是多媒体传递音视频的基本数据结构,Camera一般作为Surface中数据的生产者,在不同的场景下有特定的消费者。 - 多媒体服务作为系统服务,在系统启动时由Init进程拉起,并初始化和分配媒体硬件资源(内存/显示硬件/图像传感器/编解码器等)。初始化过程解析配置文件,确定了多媒体各个服务的能力和资源上限,通常由OEM厂商通过配置文件进行配置。相机服务在多媒体进程初始化时有以下配置项: + 相机的预览和录像输出均为视频流,拍照输出为图像帧,二者均通过Surface类进行传递。Surface类可以屏蔽进程内/跨进程的场景,进行多媒体信息流的传递。 - - 内存池:所有媒体服务依赖于内存池中的内存轮转运行 - - 图像传感器:包括了传感器类型、分辨率、ISP等 - - 图像处理器:分辨率、码率、图像翻转等 - - 图像编码器:编码格式、码率、分辨率等 + 以录像为例,用户首先创建Recorder实例,并从Recorder中获取对应Surface,再将此Surface传递给Camera实例,此时Camera将作为生产者向Surface注入视频流,而Recorder作为消费者从Surface中取出视频流进行保存,用户的行为类似桥接,把二者通过Surface连接起来。 + 类似的,用户也可以自行创建Surface传递给Camera实例,并实现消费者逻辑(例如通过网络传输视频流,或是将拍照的帧数据保存成图片文件)。 -- 关键类的解释 + 图形图像模块也通过Surface从Camera获取流资源,具体步骤详见[图形图像开发指导](../subsystems/subsys-graphics-overview.md)。 - 应用通过持有下面4个类,配置和使用Camera的功能,包括了Camera类和它的三个异步回调类,三类回调分别对应了不同类型的异步处理场景,详见[表1](#table486418149411)。 - - **表 1** 关键类的解释 - - - - - - - - - - - - - - - - - - - - - - - - -

对象

-

用途

-

举例

-

Camera

-

对相机进行静态配置(通过配置类),触发相机基本功能

-

拍照/录像/预览

-

CameraDeviceCallback

-

处理相机硬件状态变化

-

可用/不可用

-

CameraStateCallback

-

处理camera自身状态变化

-

创建/释放

-

FrameStateCallback

-

处理帧状态的变化

-

拍照开始和结束/帧率发生变化

-
- -- 流的传递 - - Surface是多媒体传递音视频的基本数据结构,Camera一般作为Surface中数据的生产者,在不同的场景下有特定的消费者。 - - 相机的预览和录像输出均为视频流,拍照输出为图像帧,二者均通过Surface类进行传递。Surface类可以屏蔽进程内/跨进程的场景,进行多媒体信息流的传递。 - - 以录像为例,用户首先创建Recorder实例,并从Recorder中获取对应Surface,再将此Surface传递给Camera实例,此时Camera将作为生产者向Surface注入视频流,而Recorder作为消费者从Surface中取出视频流进行保存,用户的行为类似桥接,把二者通过Surface连接起来。 - - 类似的,用户也可以自行创建Surface传递给Camera实例,并实现消费者逻辑(例如通过网络传输视频流,或是将拍照的帧数据保存成图片文件)。 - - 图形图像模块也通过Surface从Camera获取流资源,具体步骤详见[图形图像开发指导](subsys-graphics-overview.md)。 - -- 相机运行流程 - 1. Camera创建流程 - - 本进程通过CameraManager创建Camera实例,并从服务端绑定camera设备,创建成功后异步通知developer。类之间的时序图如下: - - **图 1** Camera创建时序图 - - - ![](figure/zh-cn_image_0000001054101094.png) - - 1. Camera录像/预览流程 - - 开发者首先通过CameraKit创建Camera,然后FrameConfig类对录像或者预览帧属性进行配置。录像/预览时序如下: - - **图 2** Camera录像/预览时序图 - - - ![](figure/zh-cn_image_0000001054421113.png) +- 相机运行流程 + 1. Camera创建流程 + 本进程通过CameraManager创建Camera实例,并从服务端绑定camera设备,创建成功后异步通知developer。类之间的时序图如下: + **图1** Camera创建时序图 + ![zh-cn_image_0000001200114819](figures/zh-cn_image_0000001200114819.png) + 1. Camera录像/预览流程 + 开发者首先通过CameraKit创建Camera,然后FrameConfig类对录像或者预览帧属性进行配置。录像/预览时序如下: + **图2** Camera录像/预览时序图 + ![zh-cn_image_0000001200115193](figures/zh-cn_image_0000001200115193.png) diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md index e0b36aed77c40460af653c70f6f2de1c96ef7baf..2eac5dfab3b3735135aa86035346c6f91ba6a377 100644 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md @@ -1,445 +1,192 @@ -# 拍照开发指导 +# 拍照开发指导 -- [使用场景](#section1963312376119) -- [接口说明](#section56549532016) -- [约束与限制](#section1165911177314) -- [开发步骤](#section138543918214) -## 使用场景 +## 使用场景 使用Camera产生图片帧(拍照)。 -## 接口说明 -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

类名

-

接口名

-

描述

-

CameraKit

-

int32_t GetCameraIds(std::list<string> cameraList)

-

获取cameraId列表

-

CameraKit

-

CameraAbility& GetCameraAbility(string cameraId)

-

获取指定camera的能力

-

CameraKit

-

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

-

注册camera设备状态回调

-

CameraKit

-

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

-

去注册camera设备状态回调

-

CameraKit

-

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

-

创建camera实例

-

CameraKit

-

const CameraInfo *GetCameraInfo(std::string cameraId);

-

创建cameraInfo实例

-

Camera

-

string GetCameraId()

-

获取cameraID

-

Camera

-

CameraConfig& GetCameraConfig()

-

获取camera配置信息

-

Camera

-

FrameConfig& GetFrameConfig(int32_t type)

-

获取捕获帧类型

-

Camera

-

void Configure(CameraConfig& config)

-

配置camera

-

Camera

-

void Release()

-

释放camera

-

Camera

-

int TriggerLoopingCapture(FrameConfig& frameConfig)

-

开始循环帧捕获

-

Camera

-

void StopLoopingCapture()

-

停止循环帧捕获

-

Camera

-

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

-

抓图

-

CameraConfig

-

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

-

设置帧状态回调

-

CameraConfig

-

static CameraConfig* CreateCameraConfig()

-

创建camera配置信息实例

-

CameraAbility

-

std::list<Size> GetSupportedSizes(int format)

-

根据类型获取支持输出图像尺寸大小

-

CameraAbility

-

std::list<T> GetParameterRange(uint32_t key)

-

获取支持的参数范围

-

CameraAbility

-

std::list<int32_t> GetSupportedAfModes() const;

-

获取支持的自动对焦模式列表

-

CameraAbility

-

std::list<int32_t> GetSupportedAeModes() const;

-

获取支持的自动曝光模式列表

-

CameraDevice

-

CameraDeviceCallback()

-

camera设备回调类构造函数

-

CameraDevice

-

void OnCameraStatus​(std::string cameraId, int32_t status)

-

camera设备状态变化时的回调

-

CameraStateCallback

-

CameraStateCallback​()

-

camera状态回调类构造函数

-

CameraStateCallback

-

void OnConfigured​(Camera& camera)

-

camera配置成功回调

-

CameraStateCallback

-

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

-

camera配置失败回调

-

CameraStateCallback

-

void OnCreated​(Camera& camera)

-

camera创建成功回调

-

CameraStateCallback

-

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

-

camera创建失败回调

-

CameraStateCallback

-

void OnReleased​(Camera& camera)

-

camera释放回调

-

FrameStateCallback

-

FrameStateCallback​()

-

帧状态回调类构造函数

-

FrameStateCallback

-

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

-

拍照帧完成回调

-

FrameStateCallback

-

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

-

拍照帧异常回调

-

FrameConfig

-

int32_t GetFrameConfigType()

-

获取帧配置类型

-

FrameConfig

-

std::list<OHOS::Surface> GetSurfaces()

-

获取帧配置的surface

-

FrameConfig

-

void AddSurface(OHOS::AGP::UISurface& surface);

-

添加surface

-

FrameConfig

-

void RemoveSurface(OHOS::AGP::UISurface& surface);

-

删除surface

-

FrameConfig

-

void GetVendorParameter(uint8_t *value, uint32_t len);

-

获取自定义参数

-

FrameConfig

-

void SetVendorParameter(uint8_t *value, uint32_t len);

-

设置自定义参数

-

CameraInfo

-

int32_t GetCameraType() const;

-

获取相机类型

-

CameraInfo

-

int32_t GetCameraFacingType() const;

-

获取相机朝向

-
- -## 约束与限制 +### 接口说明 + + **表1** API列表 + +| 类名 | 接口名 | 描述 | +| -------- | -------- | -------- | +| CameraKit | int32_t GetCameraIds(std::list<string> cameraList) | 获取cameraId列表 | +| CameraKit | CameraAbility& GetCameraAbility(string cameraId) | 获取指定camera的能力 | +| CameraKit | void RegisterCameraDeviceCallback(CameraDeviceCallback\* callback, EventHandler\* handler) | 注册camera设备状态回调 | +| CameraKit | void UnregisterCameraDeviceCallback(CameraDeviceCallback\* callback) | 去注册camera设备状态回调 | +| CameraKit | void CreateCamera(string cameraId, CameraStateCallback\* callback, EventHandler\* handler) | 创建camera实例 | +| Camera | string GetCameraId() | 获取cameraID | +| Camera | CameraConfig& GetCameraConfig() | 获取camera配置信息 | +| Camera | FrameConfig& GetFrameConfig(int32_t type) | 获取捕获帧类型 | +| Camera | void Configure(CameraConfig& config) | 配置camera | +| Camera | void Release() | 释放camera | +| Camera | int TriggerLoopingCapture(FrameConfig& frameConfig) | 开始循环帧捕获 | +| Camera | void StopLoopingCapture() | 停止循环帧捕获 | +| Camera | int32_t TriggerSingleCapture(FrameConfig& frameConfig) | 截图 | +| CameraConfig | void SetFrameStateCallback(FrameStateCallback\* callback, EventHandler\* handler); | 设置帧状态回调 | +| CameraConfig | static CameraConfig\* CreateCameraConfig() | 创建camera配置信息实例 | +| CameraAbility | std::list<Size> GetSupportedSizes(int format) | 根据类型获取支持输出图像尺寸大小 | +| CameraAbility | std::list<T> GetParameterRange(uint32_t key) | 获取支持的参数范围 | +| CameraDevice | CameraDeviceCallback() | camera设备回调类构造函数 | +| CameraDevice | void OnCameraStatus​(std::string cameraId, int32_t status) | camera设备状态变化时的回调 | +| CameraStateCallback | CameraStateCallback​() | camera状态回调类构造函数 | +| CameraStateCallback | void OnConfigured​(Camera& camera) | camera配置成功回调 | +| CameraStateCallback | void OnConfigureFailed​(Camera& camera,int32_t errorCode) | camera配置失败回调 | +| CameraStateCallback | void OnCreated​(Camera& camera) | camera创建成功回调 | +| CameraStateCallback | void OnCreateFailed​(std::string cameraId,int32_t errorCode) | camera创建失败回调 | +| CameraStateCallback | void OnReleased​(Camera& camera) | camera释放回调 | +| FrameStateCallback | FrameStateCallback​() | 帧状态回调类构造函数 | +| FrameStateCallback | void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult) | 拍照帧完成回调 | +| FrameStateCallback | void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult) | 拍照帧异常回调 | +| FrameConfig | int32_t GetFrameConfigType() | 获取帧配置类型 | +| FrameConfig | std::list<OHOS::Surface> GetSurfaces() | 获取帧配置的surface | +| FrameConfig | void AddSurface(OHOS::AGP::UISurface& surface); | 添加surface | +| FrameConfig | void RemoveSurface(OHOS::AGP::UISurface& surface); | 删除surface | + + +## 约束与限制 无。 -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - camKit->CreateCamera(camId, CamStateMng, eventHdlr); - ``` - -6. 根据[步骤1](#li378084192111)、[步骤2](#li8716104682913)、[步骤3](#li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - return; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,自定义相机状态发生变化(配置成功/失败,创建成功/失败)时的操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + camKit->CreateCamera(camId, CamStateMng, eventHdlr); + ``` + +6. 根据步骤1、步骤2、步骤3中的回调设计,同步等待 OnCreated 回调拿到 cam_ 之后,进行相关操作。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md index 4594ff3706efbd014555fbfc421f153f289a7c29..5a2309b89f816cf4ba5a49e9acb5b017fb8ef19e 100755 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md @@ -1,43 +1,41 @@ -# 预览开发指导 +# 预览开发指导 -- [使用场景](#section186634310418) -- [接口说明](#section125479541744) -- [约束与限制](#section1165911177314) -- [开发步骤](#section34171333656) -## 使用场景 +## 使用场景 使用camera产生视频流并播放。 -## 接口说明 -参考“拍照开发指导”的“接口说明”。 - -## 约束与限制 - -无。 +### 接口说明 -## 开发步骤 - -1. 参考“拍照开发指导”中步骤1、步骤2、步骤3、步骤4。 -2. 设置预览显示的区域。 +参考“拍照开发指导”的“接口说明”。 - ``` - Surface *surface = Surface::CreateSurface(); - /* 设置显示区域 */ - surface->SetUserData("region_position_x", "480"); // 矩形左上角横坐标 - surface->SetUserData("region_position_y", "270"); // 矩形左上角纵坐标 - surface->SetUserData("region_width", "960"); // 宽 - surface->SetUserData("region_height", "540"); // 高 - - fc->AddSurface(*surface); - ``` -3. 开始和结束预览。 +## 约束与限制 - ``` - stateCallback->camera_->TriggerLoopingCapture(*fc); // start previewing - stateCallback->camera_->StopLoopingCapture(); // stop previewing - ``` +无。 +## 开发步骤 + +1. 参考“拍照开发指导”中步骤1、步骤2、步骤3、步骤4。 + +2. 设置预览显示的区域。 + + ``` + Surface *surface = Surface::CreateSurface(); + /* 设置显示区域 */ + surface->SetUserData("region_position_x", "480"); // 矩形左上角横坐标 + surface->SetUserData("region_position_y", "270"); // 矩形左上角纵坐标 + surface->SetUserData("region_width", "960"); // 宽 + surface->SetUserData("region_height", "540"); // 高 + + fc->AddSurface(*surface); + ``` + +3. 开始和结束预览。 + + ``` + stateCallback->camera_->TriggerLoopingCapture(*fc); // start previewing + stateCallback->camera_->StopLoopingCapture(); // stop previewing + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md index ef3a6f69aebe9f6d07d71ecfc2f116ae55913af5..6f52057ab662f8370eda9bc530319aa55692e9ab 100755 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md @@ -1,43 +1,41 @@ -# 录像开发指导 +# 录像开发指导 -- [使用场景](#section186634310418) -- [接口说明](#section125479541744) -- [约束与限制](#section1165911177314) -- [开发步骤](#section1196016315516) -## 使用场景 +## 使用场景 使用camera采集视频码流。 -## 接口说明 -参考“拍照开发指导”的“接口说明”。 - -## 约束与限制 - -无。 +### 接口说明 -## 开发步骤 - -1. 参考“拍照开发指导”中步骤1、步骤2、步骤3、步骤4。 -2. 获取录像FrameConfig。 +参考“拍照开发指导”的“接口说明”。 - ``` - /* 从recorder获取surface */ - Surface *surface = recorder_->GetSurface(0); - surface->SetWidthAndHeight(1920, 1080); - surface->SetQueueSize(3); - surface->SetSize(1024 * 1024); - /* 将surface配置到帧配置中 */ - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_RECORD); - fc->AddSurface(*surface); - ``` -3. 开启和停止录像。 +## 约束与限制 - ``` - stateCallback->camera_->TriggerLoopingCapture(*fc); // 开始录像 - stateCallback->camera_->StopLoopingCapture(); // 结束录像 - ``` +无。 +## 开发步骤 + +1. 参考“拍照开发指导”中步骤1、步骤2、步骤3、步骤4。 + +2. 获取录像FrameConfig。 + + ``` + /* 从recorder获取surface */ + Surface *surface = recorder_->GetSurface(0); + surface->SetWidthAndHeight(1920, 1080); + surface->SetQueueSize(3); + surface->SetSize(1024 * 1024); + /* 将surface配置到帧配置中 */ + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_RECORD); + fc->AddSurface(*surface); + ``` + +3. 开启和停止录像。 + + ``` + stateCallback->camera_->TriggerLoopingCapture(*fc); // 开始录像 + stateCallback->camera_->StopLoopingCapture(); // 结束录像 + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md index ad7796b6926b7f89505b6508cda2e796fd961e64..405b0886e32be5db5d8779c87e188304391b1325 100644 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md @@ -1,11 +1,11 @@ -# 相机 +# 相机 -- **[相机开发概述](subsys-multimedia-camera-overview.md)** -- **[拍照开发指导](subsys-multimedia-camera-photo-guide.md)** -- **[录像开发指导](subsys-multimedia-camera-record-guide.md)** +- **[相机开发概述](subsys-multimedia-camera-overview.md)** -- **[预览开发指导](subsys-multimedia-camera-preview-guide.md)** +- **[拍照开发指导](subsys-multimedia-camera-photo-guide.md)** +- **[录像开发指导](subsys-multimedia-camera-record-guide.md)** +- **[预览开发指导](subsys-multimedia-camera-preview-guide.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md b/zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md index 442d452b40bbc88fe73ed2f290efc278711f5fa3..0a105ae54259ba2f51177028f823b7051b9a00df 100755 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md @@ -1,81 +1,41 @@ -# 音视频开发概述 +# 音视频开发概述 -- [基本概念](#section967213571204) -- [编解码规格](#section1582020483111) OpenHarmony音视频包括音视频播放和录制。 -- OpenHarmony音视频播放模块支持音视频播放业务的开发,主要包括音视频文件和音视频流播放、音量和播放进度控制等。 -- OpenHarmony录制模块支持音视频录制业务的开发,提供音视频录制相关的功能,包括设置录制视频画面尺寸、音视频编码码率、编码器类型、视频帧率、音频采样率、录制文件输出格式等。 -## 基本概念 +- OpenHarmony音视频播放模块支持音视频播放业务的开发,主要包括音视频文件和音视频流播放、音量和播放进度控制等。 -在进行应用的开发OpenHarmony前,开发者应了解以下基本概念: - -- 流媒体技术 - - 流媒体技术是把连续的影像和声音信息进行编码处理后放在网络服务器上,让浏览者一边下载、一边观看与收听,而不需要等整个多媒体文件下载完成就可以即时观看、收听的技术。 +- OpenHarmony录制模块支持音视频录制业务的开发,提供音视频录制相关的功能,包括设置录制视频画面尺寸、音视频编码码率、编码器类型、视频帧率、音频采样率、录制文件输出格式等。 -- 视频帧率 +## 基本概念 - 帧率是用于测量显示帧数的度量,帧数就是在每秒钟时间里传输的图片数量。每秒钟帧数 \(FPS\) 越多,所显示的画面就会越流畅。 +在进行应用的开发OpenHarmony前,开发者应了解以下基本概念: -- 码率 +- 流媒体技术 + 流媒体技术是把连续的影像和声音信息进行编码处理后放在网络服务器上,让浏览者一边下载、一边观看与收听,而不需要等整个多媒体文件下载完成就可以即时观看、收听的技术。 - 码率就是数据传输时单位时间传送的数据位数,常用单位是kbps即千位每秒。 +- 视频帧率 + 帧率是用于测量显示帧数的度量,帧数就是在每秒钟时间里传输的图片数量。每秒钟帧数 (FPS) 越多,所显示的画面就会越流畅。 -- 采样率 +- 码率 + 码率就是数据传输时单位时间传送的数据位数,常用单位是kbps即千位每秒。 - 采样率为每秒从连续信号中提取并组成离散信号的采样个数,单位用赫兹(Hz)来表示。 +- 采样率 + 采样率为每秒从连续信号中提取并组成离散信号的采样个数,单位用赫兹(Hz)来表示。 -## 编解码规格 +## 编解码规格 OpenHarmony音视频编解码能力取决于具体设备类型,以当前已支持的开发板为例,规格见下表: -**表 1** 不同开发板编解码规格 - - - - - - - - - - - - - - - - - - - - - - - - -

设备类型

-

开发板类型

-

解码规格

-

编码规格

-

带屏摄像头类产品

-

Hi3516

-
  • 音频解码:支持MPEG-4 AAC Profile (AAC LC)、MPEG Audio Layer 3 (MP3)格式解码,支持单/双声道,支持MPEG-4(.mp4,.m4a)、MP3(.mp3)容器格式。
  • 视频解码:支持H.265 HEVC/H.264 AVC格式解码(限自身编码码流),支持MPEG-4(.mp4)容器格式。
-
  • 音频编码:支持音频AAC_LC编码,支持单/双声道,支持MPEG-4(.mp4)容器格式。
  • 视频编码:支持视频H.264/H.265编码,支持MPEG-4(.mp4)容器格式。
-

无屏摄像头类产品

-

Hi3518

-
  • 音频解码:支持MPEG-4 AAC Profile (AAC LC)、MPEG Audio Layer 3 (MP3)格式解码,支持单/双声道,支持MPEG-4(.mp4,.m4a)、MP3(.mp3)容器格式。
  • 视频解码:-
-
  • 音频编码:支持音频AAC_LC编码,支持单/双声道,支持MPEG-4(.mp4)容器格式。
  • 视频编码:支持视频H.264/H.265编码,支持MPEG-4(.mp4)容器格式。
-

WLAN连接类设备

-

Hi3861

-

-

-

-

-
+ **表1** 不同开发板编解码规格 -Hi3516和Hi3518更多详细的编解码规格请参考开发板自带的资料。 +| 设备类型 | 开发板类型 | 解码规格 | 编码规格 | +| -------- | -------- | -------- | -------- | +| 带屏摄像头类产品 | Hi3516 | - 音频解码:支持MPEG-4 AAC Profile (AAC LC)格式解码,支持单/双声道,支持MPEG-4(.mp4,.m4a)容器格式。
- 视频解码:支持H.265 HEVC/H.264 AVC格式解码(限自身编码码流),支持MPEG-4(.mp4)容器格式。 | - 音频编码:支持音频AAC_LC编码,支持单/双声道,支持MPEG-4(.mp4)容器格式。
- 视频编码:支持视频H.264/H.265编码,支持MPEG-4(.mp4)容器格式。 | +| 无屏摄像头类产品 | Hi3518 | - 音频解码:支持MPEG-4 AAC Profile (AAC LC)格式解码,支持单/双声道,支持MPEG-4(.mp4,.m4a)容器格式。
- 视频解码:- | - 音频编码:支持音频AAC_LC编码,支持单/双声道,支持MPEG-4(.mp4)容器格式。
- 视频编码:支持视频H.264/H.265编码,支持MPEG-4(.mp4)容器格式。 | +| WLAN连接类设备 | Hi3861 | - | - | +Hi3516和Hi3518更多详细的编解码规格请参考开发板自带的资料。 diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md index 0024dc47b5e5efe4236cd2483eb9211858feffdc..0faa0bb8400afe4fe7fe93857ff97c6c533958b3 100755 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md @@ -1,342 +1,114 @@ -# 音视频播放开发指导 +# 音视频播放开发指导 -- [使用场景](#section186634310418) -- [接口说明](#section125479541744) -- [约束与限制](#section1165911177314) -- [开发步骤](#section34171333656) -## 使用场景 +## 使用场景 音视频播放是将音视频文件或音视频流数据进行解码并通过输出设备进行播放的过程,同时对播放任务进行管理。 -## 接口说明 -音视频播放API接口功能如下,具体的API详见接口文档。 - -**表 1** 音视频播放API接口 +## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

类名

-

接口名

-

描述

-

Player

-

int32_t SetSource(const Source &source);

-

设置播放源

-

Player

-

int32_t Prepare();

-

准备播放

-

Player

-

int32_t Play();

-

开始播放

-

Player

-

bool IsPlaying()

-

判断是否播放中

-

Player

-

int32_t Pause();

-

暂停播放

-

Player

-

int32_t Stop();

-

停止播放

-

Player

-

int32_t Rewind(int_64 mSeconds, int32_t mode);

-

改变播放位置

-

Player

-

int32_t SetVolume(float leftVolume, float rightVolume);

-

设置音量,包括左声道和右声道。

-

Player

-

int32_t SetVideoSurface(Surface *surface)

-

设置播放窗口

-

Player

-

int32_t EnableSingleLooping(bool loop)

-

设置循环播放

-

Player

-

bool IsSingleLooping();

-

判断是否循环播放

-

Player

-

int32_t GetCurrentTime(int64_t &time) const;

-

获取当前播放时长

-

Player

-

int32_t GetDuration(int64_t &duration) const;

-

获取总播放时长

-

Player

-

int32_t GetVideoWidth(int32_t &videoWidth);

-

获取视频源宽度

-

Player

-

int32_t GetVideoHeight(int32_t &videoHeight);

-

获取视频源高度

-

Player

-

int32_t Reset();

-

重置播放器

-

Player

-

int32_t Release();

-

释放播放器资源

-

Player

-

void SetPlayerCallback(const std::shared_ptr<PlayerCallback> &cb);

-

设置播放回调函数

-

Source

-

Source(const std::string& uri);

-

基于uri创建Source实例

-

Source

-

Source(const std::shared_ptr<StreamSource> &stream, const Format &formats);

-

基于流创建Source实例

-

Source

-

SourceType GetSourceType() const;

-

获取源类型

-

Source

-

const std::string &GetSourceUri() const;

-

获取音视频uri

-

Source

-

const std::shared_ptr<StreamSource> &GetSourceStream() const;

-

获取音视频流

-

Source

-

const Format &GetSourceStreamFormat() const;

-

获取音视频流格式

-

Format

-

bool PutIntValue(const std::string &key, int32_t value);

-

设置整数类型的元数据

-

Format

-

bool PutLongValue(const std::string &key, int64_t value);

-

设置长整数类型的元数据

-

Format

-

bool PutFloatValue(const std::string &key, float value);

-

设置单精度浮点类型的元数据

-

Format

-

bool PutDoubleValue(const std::string &key, double value);

-

设置双精度浮点类型的元数据

-

Format

-

bool PutStringValue(const std::string &key, const std::string &value);

-

设置字符串类型的元数据

-

Format

-

bool GetIntValue(const std::string &key, int32_t &value) const;

-

获取整数类型的元数据值

-

Format

-

bool GetLongValue(const std::string &key, int64_t &value) const;

-

获取长整数类型的元数据值

-

Format

-

bool GetFloatValue(const std::string &key, float &value) const;

-

获取单精度浮点类型的元数据值

-

Format

-

bool GetDoubleValue(const std::string &key, double &value) const;

-

获取双精度浮点类型的元数据值

-

Format

-

bool GetStringValue(const std::string &key, std::string &value) const;

-

获取字符串类型的元数据值

-

Format

-

const std::map<std::string, FormatData *> &GetFormatMap() const;

-

获取元数据映射表

-

Format

-

bool CopyFrom(const Format &format);

-

用输入Format设置所有元数据

-
+音视频播放API接口功能如下,具体的API详见接口文档。 -## 约束与限制 + **表1** 音视频播放API接口 + +| 类名 | 接口名 | 描述 | +| -------- | -------- | -------- | +| Player | int32_t SetSource(const Source &source); | 设置播放源 | +| Player | int32_t Prepare(); | 准备播放 | +| Player | int32_t Play(); | 开始播放 | +| Player | bool IsPlaying() | 判断是否播放中 | +| Player | int32_t Pause(); | 暂停播放 | +| Player | int32_t Stop(); | 停止播放 | +| Player | int32_t Rewind(int_64 mSeconds, int32_t mode); | 改变播放位置 | +| Player | int32_t SetVolume(float leftVolume, float rightVolume); | 设置音量,包括左声道和右声道。 | +| Player | int32_t SetVideoSurface(Surface \*surface) | 设置播放窗口 | +| Player | int32_t EnableSingleLooping(bool loop) | 设置循环播放 | +| Player | bool IsSingleLooping(); | 判断是否循环播放 | +| Player | int32_t GetCurrentTime(int64_t &time) const; | 获取当前播放时长 | +| Player | int32_t GetDuration(int64_t &duration) const; | 获取总播放时长 | +| Player | int32_t GetVideoWidth(int32_t &videoWidth); | 获取视频源宽度 | +| Player | int32_t GetVideoHeight(int32_t &videoHeight); | 获取视频源高度 | +| Player | int32_t Reset(); | 重置播放器 | +| Player | int32_t Release(); | 释放播放器资源 | +| Player | void SetPlayerCallback(const std::shared_ptr<PlayerCallback> &cb); | 设置播放回调函数 | +| Source | Source(const std::string& uri); | 基于uri创建Source实例 | +| Source | Source(const std::shared_ptr<StreamSource> &stream, const Format &formats); | 基于流创建Source实例 | +| Source | SourceType GetSourceType() const; | 获取源类型 | +| Source | const std::string &GetSourceUri() const; | 获取音视频uri | +| Source | const std::shared_ptr<StreamSource> &GetSourceStream() const; | 获取音视频流 | +| Source | const Format &GetSourceStreamFormat() const; | 获取音视频流格式 | +| Format | bool PutIntValue(const std::string &key, int32_t value); | 设置整数类型的元数据 | +| Format | bool PutLongValue(const std::string &key, int64_t value); | 设置长整数类型的元数据 | +| Format | bool PutFloatValue(const std::string &key, float value); | 设置单精度浮点类型的元数据 | +| Format | bool PutDoubleValue(const std::string &key, double value); | 设置双精度浮点类型的元数据 | +| Format | bool PutStringValue(const std::string &key, const std::string &value); | 设置字符串类型的元数据 | +| Format | bool GetIntValue(const std::string &key, int32_t &value) const; | 获取整数类型的元数据值 | +| Format | bool GetLongValue(const std::string &key, int64_t &value) const; | 获取长整数类型的元数据值 | +| Format | bool GetFloatValue(const std::string &key, float &value) const; | 获取单精度浮点类型的元数据值 | +| Format | bool GetDoubleValue(const std::string &key, double &value) const; | 获取双精度浮点类型的元数据值 | +| Format | bool GetStringValue(const std::string &key, std::string &value) const; | 获取字符串类型的元数据值 | +| Format | const std::map<std::string, FormatData \*> &GetFormatMap() const; | 获取元数据映射表 | +| Format | bool CopyFrom(const Format &format); | 用输入Format设置所有元数据 | + + +## 约束与限制 输入源为音视频流时,不支持播放进度控制和获取文件时长。 -## 开发步骤 - -1. 实现PlayerCallback回调,通过SetPlayerCallback函数进行绑定,用于事件处理。 - - ``` - class TestPlayerCallback : public PlayerCallback{ - void OnPlaybackComplete() override - { - //此处实现代码用于处理文件播放完成的事件 - } - void OnError(int32_t errorType, int32_t errorCode) override - { - //此处实现代码处理错误事件 - } - void OnInfo(int type, int extra) override - { - //此处实现代码处理普通事件 - } - void OnRewindToComplete() override - { - //此处实现代码处理进度控制完成的事件 - } - }; - - ``` - -2. 创建Player实例,设置播放源并开始播放。 - - ``` - Player *player = new Player(); - std::shared_ptr callback = std::make_shared(); - player->SetPlayerCallback(callback);//设置player回调 - std::string uri(filePath);//此处filePath为本地文件路径 - Source source(uri);//保存uri到source实例 - player->SetSource(source);//将source设置到player - player->Prepare();//准备播放 - player->SetVideoSurface(surface);//设置播放窗口 - player->Play();//开始播放 - ``` - -3. 根据场景需要进行播放控制。 - - ``` - player->SetVolume(lvolume, rvolume);//设置左右声道声音 - player->EnableSingleLooping(true);//设置循环播放 - player->Pause();//暂停 - player->Play();//继续播放 - ``` - -4. 播放任务结束后,进行资源释放。 - - ``` - player->Stop(); //停止播放 - player->Release();//释放资源 - ``` - +## 开发步骤 + +1. 实现PlayerCallback回调,通过SetPlayerCallback函数进行绑定,用于事件处理。 + + ``` + class TestPlayerCallback : public PlayerCallback{ + void OnPlaybackComplete() override + { + //此处实现代码用于处理文件播放完成的事件 + } + void OnError(int32_t errorType, int32_t errorCode) override + { + //此处实现代码处理错误事件 + } + void OnInfo(int type, int extra) override + { + //此处实现代码处理普通事件 + } + void OnRewindToComplete() override + { + //此处实现代码处理进度控制完成的事件 + } + }; + + ``` + +2. 创建Player实例,设置播放源并开始播放。 + + ``` + Player *player = new Player(); + std::shared_ptr callback = std::make_shared(); + player->SetPlayerCallback(callback);//设置player回调 + std::string uri(filePath);//此处filePath为本地文件路径 + Source source(uri);//保存uri到source实例 + player->SetSource(source);//将source设置到player + player->Prepare();//准备播放 + player->SetVideoSurface(surface);//设置播放窗口 + player->Play();//开始播放 + ``` + +3. 根据场景需要进行播放控制。 + + ``` + player->SetVolume(lvolume, rvolume);//设置左右声道声音 + player->EnableSingleLooping(true);//设置循环播放 + player->Pause();//暂停 + player->Play();//继续播放 + ``` + +4. 播放任务结束后,进行资源释放。 + + ``` + player->Stop(); //停止播放 + player->Release();//释放资源 + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md index 19887e60b975c7284406d903acb4c451934eb823..615c46573a0cf46d7c428f215641c8554a53c37e 100755 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md @@ -1,287 +1,107 @@ -# 音视频录制开发指导 +# 音视频录制开发指导 -- [使用场景](#section186634310418) -- [接口说明](#section125479541744) -- [约束与限制](#section1165911177314) -- [开发步骤](#section34171333656) -## 使用场景 +## 使用场景 音视频录制的主要功能是录制音视频,并根据设置的编码格式、采样率、码率等参数封装输出文件。 -## 接口说明 -音视频录制API接口如下,具体的API详见接口文档。 - -**表 1** 音视频录制API接口 +## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

类名

-

接口名

-

功能

-

Recorder

-

int32_t SetVideoSource(VideoSourceType source, int32_t &sourceId)

-

设置录制视频源

-

Recorder

-

int32_t SetVideoEncoder(int32_t sourceId, VideoCodecFormat encoder)

-

设置录制的视频编码器类型

-

Recorder

-

int32_t SetVideoSize(int32_t sourceId, int32_t width, int32_t height)

-

设置录制的视频宽和高

-

Recorder

-

int32_t SetVideoFrameRate(int32_t sourceId, int32_t frameRate)

-

设置要录制的视频帧率

-

Recorder

-

int32_t SetVideoEncodingBitRate(int32_t sourceId, int32_t rate)

-

设置录制视频编码的码率

-

Recorder

-

int32_t SetCaptureRate(int32_t sourceId, double fps)

-

设置视频帧的捕获帧率

-

Recorder

-

std::shared_ptr<OHOS::Surface> GetSurface(int32_t sourceId);

-

获取对应输入源的surface

-

Recorder

-

int32_t SetAudioSource(AudioSourceType source, int32_t &sourceId)

-

设置录制音频源

-

Recorder

-

int32_t SetAudioEncoder(int32_t sourceId, AudioCodecFormat encoder)

-

设置录制的音频编码器类型

-

Recorder

-

int32_t SetAudioSampleRate(int32_t sourceId, int32_t rate)

-

设置录制的音频采样率

-

Recorder

-

int32_t SetAudioChannels(int32_t sourceId, int32_t num)

-

设置要录制的音频通道数

-

Recorder

-

int32_t SetAudioEncodingBitRate(int32_t sourceId, int32_t bitRate)

-

设置录制音频编码的码率

-

Recorder

-

int32_t SetMaxDuration(int32_t duration)

-

设置录制文件的最大时长

-

Recorder

-

int32_t SetOutputFormat(OutputFormatType format)

-

设置输出文件格式

-

Recorder

-

int32_t SetOutputPath(const string &path);

-

设置输出文件保存路径

-

Recorder

-

int32_t SetOutputFile(int32_t fd)

-

设置输出文件的fd

-

Recorder

-

int32_t SetNextOutputFile(int32_t fd);

-

设置下一个输出文件的fd

-

Recorder

-

int32_t SetMaxFileSize(int64_t size)

-

设置录制会话的最大文件大小

-

Recorder

-

int32_t SetRecorderCallback(const std::shared_ptr<RecorderCallback> &callback)

-

注册录制侦听器回调

-

Recorder

-

int32_t Prepare()

-

准备录制

-

Recorder

-

int32_t Start()

-

开始录制

-

Recorder

-

int32_t Pause()

-

暂停录制

-

Recorder

-

int32_t Resume()

-

恢复录制

-

Recorder

-

int32_t Stop(bool block)

-

停止录制

-

Recorder

-

int32_t Reset();

-

重置录制

-

Recorder

-

int32_t Release()

-

释放录制资源

-

Recorder

-

int32_t SetFileSplitDuration(FileSplitType type, int64_t timestamp, uint32_t duration)

-

设置切分录像

-

Recorder

-

int32_t SetParameter(int32_t sourceId, const Format &format)

-

设置录制的扩展参数

-
+音视频录制API接口如下,具体的API详见接口文档。 -## 约束与限制 + **表1** 音视频录制API接口 + +| 类名 | 接口名 | 功能 | +| -------- | -------- | -------- | +| Recorder | int32_t SetVideoSource(VideoSourceType source, int32_t &sourceId) | 设置录制视频源 | +| Recorder | int32_t SetVideoEncoder(int32_t sourceId, VideoCodecFormat encoder) | 设置录制的视频编码器类型 | +| Recorder | int32_t SetVideoSize(int32_t sourceId, int32_t width, int32_t height) | 设置录制的视频宽和高 | +| Recorder | int32_t SetVideoFrameRate(int32_t sourceId, int32_t frameRate) | 设置要录制的视频帧率 | +| Recorder | int32_t SetVideoEncodingBitRate(int32_t sourceId, int32_t rate) | 设置录制视频编码的码率 | +| Recorder | int32_t SetCaptureRate(int32_t sourceId, double fps) | 设置视频帧的捕获帧率 | +| Recorder | std::shared_ptr<OHOS::Surface> GetSurface(int32_t sourceId); | 获取对应输入源的surface | +| Recorder | int32_t SetAudioSource(AudioSourceType source, int32_t &sourceId) | 设置录制音频源 | +| Recorder | int32_t SetAudioEncoder(int32_t sourceId, AudioCodecFormat encoder) | 设置录制的音频编码器类型 | +| Recorder | int32_t SetAudioSampleRate(int32_t sourceId, int32_t rate) | 设置录制的音频采样率 | +| Recorder | int32_t SetAudioChannels(int32_t sourceId, int32_t num) | 设置要录制的音频通道数 | +| Recorder | int32_t SetAudioEncodingBitRate(int32_t sourceId, int32_t bitRate) | 设置录制音频编码的码率 | +| Recorder | int32_t SetMaxDuration(int32_t duration) | 设置录制文件的最大时长 | +| Recorder | int32_t SetOutputFormat(OutputFormatType format) | 设置输出文件格式 | +| Recorder | int32_t SetOutputPath(const string &path); | 设置输出文件保存路径 | +| Recorder | int32_t SetOutputFile(int32_t fd) | 设置输出文件的fd | +| Recorder | int32_t SetNextOutputFile(int32_t fd); | 设置下一个输出文件的fd | +| Recorder | int32_t SetMaxFileSize(int64_t size) | 设置录制会话的最大文件大小 | +| Recorder | int32_t SetRecorderCallback(const std::shared_ptr<RecorderCallback> &callback) | 注册录制侦听器回调 | +| Recorder | int32_t Prepare() | 准备录制 | +| Recorder | int32_t Start() | 开始录制 | +| Recorder | int32_t Pause() | 暂停录制 | +| Recorder | int32_t Resume() | 恢复录制 | +| Recorder | int32_t Stop(bool block) | 停止录制 | +| Recorder | int32_t Reset(); | 重置录制 | +| Recorder | int32_t Release() | 释放录制资源 | +| Recorder | int32_t SetFileSplitDuration(FileSplitType type, int64_t timestamp, uint32_t duration) | 设置切分录像 | +| Recorder | int32_t SetParameter(int32_t sourceId, const Format &format) | 设置录制的扩展参数 | + + +## 约束与限制 无。 -## 开发步骤 - -1. 创建Recorder实例。 - - ``` - Recorder *recorder = new Recorder(); - ``` - -2. 设置Recorder参数,包括设置音视频源信息,音视频编码格式,采样率,码率,视频宽高等信息。 - - ``` - int32_t sampleRate = 48000; - int32_t channelCount = 1; - AudioCodecFormat audioFormat = AAC_LC; - AudioSourceType inputSource = AUDIO_MIC; - int32_t audioEncodingBitRate = sampleRate; - VideoSourceType source = VIDEO_SOURCE_SURFACE_ES; - int32_t frameRate = 30; - double fps = 30; - int32_t rate = 4096; - int32_t sourceId = 0; - int32_t audioSourceId = 0; - int32_t width = 1920; - int32_t height = 1080; - VideoCodecFormat encoder = H264; - recorder->SetVideoSource(source, sourceId ); // 设置视频源,获得sourceId - recorder->SetVideoEncoder(sourceId, encoder); // 设置视频编码格式 - recorder->SetVideoSize(sourceId, width, height); // 设置视频宽高 - recorder->SetVideoFrameRate(sourceId, frameRate); // 设置视频帧率 - recorder->SetVideoEncodingBitRate(sourceId, rate); // 设置视频编码码率 - recorder->SetCaptureRate(sourceId, fps); // 设置视频帧的捕获帧率 - recorder->SetAudioSource(inputSource, audioSourceId); // 设置音频源,获得audioSourceId - recorder->SetAudioEncoder(audioSourceId, audioFormat); // 设置音频编码格式 - recorder->SetAudioSampleRate(audioSourceId, sampleRate); // 设置音频采样率 - recorder->SetAudioChannels(audioSourceId, channelCount); // 设置音频通道数 - recorder->SetAudioEncodingBitRate(audioSourceId, audioEncodingBitRate); // 设置音频编码码率 - ``` - -3. 准备录制,Recorder进行录制前的准备工作。 - - ``` - recorder->Prepare(); // 准备录制 - ``` - -4. 开始录制,Recorder会根据设置的音频源和视频源进行录制。 - - ``` - recorder->Start(); // 开始录制 - ``` - -5. 结束录制,释放资源。 - - ``` - recorder->Stop(); // 停止录制 - recorder->Release(); // 释放录制资源 - ``` - +## 开发步骤 + +1. 创建Recorder实例。 + + ``` + Recorder *recorder = new Recorder(); + ``` + +2. 设置Recorder参数,包括设置音视频源信息,音视频编码格式,采样率,码率,视频宽高等信息。 + + ``` + int32_t sampleRate = 48000; + int32_t channelCount = 1; + AudioCodecFormat audioFormat = AAC_LC; + AudioSourceType inputSource = AUDIO_MIC; + int32_t audioEncodingBitRate = sampleRate; + VideoSourceType source = VIDEO_SOURCE_SURFACE_ES; + int32_t frameRate = 30; + double fps = 30; + int32_t rate = 4096; + int32_t sourceId = 0; + int32_t audioSourceId = 0; + int32_t width = 1920; + int32_t height = 1080; + VideoCodecFormat encoder = H264; + recorder->SetVideoSource(source, sourceId ); // 设置视频源,获得sourceId + recorder->SetVideoEncoder(sourceId, encoder); // 设置视频编码格式 + recorder->SetVideoSize(sourceId, width, height); // 设置视频宽高 + recorder->SetVideoFrameRate(sourceId, frameRate); // 设置视频帧率 + recorder->SetVideoEncodingBitRate(sourceId, rate); // 设置视频编码码率 + recorder->SetCaptureRate(sourceId, fps); // 设置视频帧的捕获帧率 + recorder->SetAudioSource(inputSource, audioSourceId); // 设置音频源,获得audioSourceId + recorder->SetAudioEncoder(audioSourceId, audioFormat); // 设置音频编码格式 + recorder->SetAudioSampleRate(audioSourceId, sampleRate); // 设置音频采样率 + recorder->SetAudioChannels(audioSourceId, channelCount); // 设置音频通道数 + recorder->SetAudioEncodingBitRate(audioSourceId, audioEncodingBitRate); // 设置音频编码码率 + ``` + +3. 准备录制,Recorder进行录制前的准备工作。 + + ``` + recorder->Prepare(); // 准备录制 + ``` + +4. 开始录制,Recorder会根据设置的音频源和视频源进行录制。 + + ``` + recorder->Start(); // 开始录制 + ``` + +5. 结束录制,释放资源。 + + ``` + recorder->Stop(); // 停止录制 + recorder->Release(); // 释放录制资源 + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-video.md b/zh-cn/device-dev/subsystems/subsys-multimedia-video.md index 2a59765280656395693afc362f32fac0bc6c1447..c4792d2597a4f16e61f2effe0678fd2fbd207b74 100644 --- a/zh-cn/device-dev/subsystems/subsys-multimedia-video.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-video.md @@ -1,9 +1,9 @@ -# 音视频 +# 音视频 -- **[音视频开发概述](subsys-multimedia-video-overview.md)** -- **[音视频播放开发指导](subsys-multimedia-video-play-guide.md)** -- **[音视频录制开发指导](subsys-multimedia-video-record-guide.md)** +- **[音视频开发概述](subsys-multimedia-video-overview.md)** +- **[音视频播放开发指导](subsys-multimedia-video-play-guide.md)** +- **[音视频录制开发指导](subsys-multimedia-video-record-guide.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia.md b/zh-cn/device-dev/subsystems/subsys-multimedia.md index 50fb9b91f2f47741ba7aa0efe8fa2935e52fd1de..8bf07519c0f6aa809929f082d99727a25572f2a3 100644 --- a/zh-cn/device-dev/subsystems/subsys-multimedia.md +++ b/zh-cn/device-dev/subsystems/subsys-multimedia.md @@ -1,7 +1,7 @@ -# 媒体 +# 媒体 -- **[相机](subsys-multimedia-camera.md)** -- **[音视频](subsys-multimedia-video.md)** +- **[相机](subsys-multimedia-camera.md)** +- **[音视频](subsys-multimedia-video.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-ota-guide.md b/zh-cn/device-dev/subsystems/subsys-ota-guide.md index 2518293cb580659f5dce2699ade13ad9c53e5ca5..0f373114da8e29832ea543f4f5d527903fe7596d 100644 --- a/zh-cn/device-dev/subsystems/subsys-ota-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-ota-guide.md @@ -1,9 +1,11 @@ # OTA升级 + ## 概述 OTA(Over the Air)提供对设备远程升级的能力,可以让您的设备(如IP摄像头等),轻松支持远程升级能力。目前轻量和小型系统仅支持全量包升级,暂不支持差分包升级。全量包升级是将新系统全部内容做成升级包,进行升级;差分包升级是将新老系统的差异内容做成升级包,进行升级。 + ## 约束与限制 - 支持基于Hi3861/Hi3518EV300/Hi3516DV300芯片的开源套件。 @@ -15,7 +17,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 ## 生成公私钥对 -1. 准备工作:在Windows PC 上,下载安装[OpenSSL工具](http://slproweb.com/products/Win32OpenSSL.html),并配置环境变量。 +1. 准备工作:在Windows上,下载安装[OpenSSL工具](http://slproweb.com/products/Win32OpenSSL.html),并配置环境变量。 2. 使用OpenSSL工具生成公私钥对。 @@ -25,6 +27,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 4. 对使用 Hi3518EV300/Hi3516DV300 套件的轻量和小型系统,在上一步的基础上,还需用public_arr.txt里面的全部内容替换uboot模块device\hisilicon\third_party\uboot\u-boot-2020.01\product\hiupdate\verify\update_public_key.c 中的g_pub_key中的全部内容。 示例,uboot模块的公钥: + ``` static unsigned char g_pub_key[PUBKEY_LEN] = { 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, @@ -39,6 +42,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 ### 轻量与小型系统升级包制作 1. 创建目标版本(target_package)文件夹,文件格式如下: + ``` target_package ├── OTA.tag @@ -56,6 +60,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 3. 填写“update_config”文件夹中的“updater_specified_config.xml”组件配置文件。 组件配置文件“updater_specified_config.xml”,格式如下: + ``` @@ -70,21 +75,32 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 ``` - **表1** 组件配置文件节点说明 - - | 信息类别 | 节点名称 | 节点标签 | 是否必填 | 内容说明 | + **表1** 组件配置文件节点说明 + + | 信息类别 | 节点名称 | 节点标签 | 是否必填 | 内容说明 | + | -------- | -------- | -------- | -------- | -------- | + | 头信息(head节点) | info节点 | / | 必填 | 该节点内容配置为:head info | + | fileVersion | 必填 | 保留字段,内容不影响升级包生成 | + | prdID | 必填 | 保留字段,内容不影响升级包生成 | + | softVersion | 必填 | 软件版本号,即升级包版本号,版本必须在“VERSION.mbn”范围内,否则无法生产升级 | + | date | 必填 | 升级包制作日期,保留字段,不影响升级包生成 | + | time | 必填 | 升级包制作时间,保留字段,不影响升级包生成 | + + **表2** 组件配置文件节点说明 + + | 信息类别 | 节点名称 | 节点标签 | 是否必填 | 内容说明 | | -------- | -------- | -------- | -------- | -------- | - | 头信息(head节点) | info节点 | / | 必填 | 该节点内容配置为:head info。 | - | | | fileVersion | 必填 | 保留字段,内容不影响升级包生成。 | - | | | prdID | 必填 | 保留字段,内容不影响升级包生成。 | - | | | softVersion | 必填 | 软件版本号,即升级包版本号,版本必须在“VERSION.mbn”范围内,否则无法生产升级。 | - | | | date | 必填 | 升级包制作日期,保留字段,不影响升级包生成。 | - | | | time | 必填 | 升级包制作时间,保留字段,不影响升级包生成。 | - | 组件信息(group节点) | component节点 | / | 必填 | 该节点内容配置为:要打入升级包的组件/镜像文件的路径,默认为版本包根路径。 | - | | | compAddr | 必填 | 该组件所对应的分区名称,例如:system、vendor等。 | - | | | compId | 必填 | 组件Id,不同组件Id不重复。 | - | | | resType | 必填 | 保留字段,不影响升级包生成。 | - | | | compType | 必填 | 处理方式全量/差分,配置镜像处理方式的,0为全量处理、1为差分处理。 | + | 头信息(head节点) | info节点 | / | 必填 | 该节点内容配置为:head info | + | 头信息(head节点) | info节点 | fileVersion | 必填 | 保留字段,内容不影响升级包生成 | + | 头信息(head节点) | info节点 | prdID | 必填 | 保留字段,内容不影响升级包生成 | + | 头信息(head节点) | info节点 | softVersion | 必填 | 软件版本号,即升级包版本号,版本必须在“VERSION.mbn”范围内,否则无法生产升级 | + | 头信息(head节点) | info节点 | _date_ | _必填_ | 升级包制作日期,保留字段,不影响升级包生成 | + | 头信息(head节点) | info节点 | _time_ | _必填_ | 升级包制作时间,保留字段,不影响升级包生成 | + | 组件信息(group节点) | component节点 | / | 必填 | 该节点内容配置为:要打入升级包的组件/镜像文件的路径,默认为版本包根路径 | + | 组件信息(group节点) | component节点 | compAddr | 必填 | 该组件所对应的分区名称,例如:system、vendor等。 | + | 组件信息(group节点) | component节点 | compId | 必填 | 组件Id,不同组件Id不重复 | + | 组件信息(group节点) | component节点 | resType | 必填 | 保留字段,不影响升级包生成 | + | 组件信息(group节点) | component节点 | compType | 必填 | 处理方式全量/差分,配置镜像处理方式的,0为全量处理、1为差分处理。 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 对轻量系统/小型系统,不支持做差分升级,component标签中,属性compType值,不能配为‘1’,必须全部配置为‘0’。 @@ -92,6 +108,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 > 对轻量系统/小型系统,不支持变分区升级包的制作。 4. 创建“OTA.tag文件”,内容为OTA升级包的魔数,固定如下: + ``` package_type:ota1234567890qwertw ``` @@ -99,12 +116,14 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 5. 创建“config文件”,内容为设置bootargs以及bootcmd的信息。 例如配置如下: + ``` setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M (u-boot.bin),9M(kernel.bin),50M(rootfs_ext4.img),50M(userfs.img)' setenv bootcmd 'mmc read 0x0 0x82000000 0x800 0x4800;bootm 0x82000000' ``` 6. 执行升级包制作命令。 + ``` python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem -nz -nl2x ``` @@ -120,6 +139,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 1. 创建目标版本(target_package)文件夹,文件格式如下: + ``` target_package ├── {component_1} @@ -140,6 +160,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 例如配置如下: + ``` HI3516 HI3518 @@ -153,6 +174,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 例如配置如下: + ``` Hi3516DV300-eng 10 QP1A.190711.001 Hi3516DV300-eng 10 QP1A.190711.020 @@ -165,6 +187,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 分区表会随镜像一起生成,格式如下: + ``` @@ -175,15 +198,15 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 **表2** 分区表Part标签说明 - | 标签名称 | 标签说明 | + | 标签名称 | 标签说明 | | -------- | -------- | - | Sel | 该分区是否生效,1表明生效,0表明不生效。 | - | PartitionName | 分区名称,例如:fastboot、boot等。 | - | FlashType | flash磁盘类型,例如emmc、ufs等。 | - | FileSystem | 文件系统类型,例如ext3/4、f2fs等,也可能为none。 | - | Start | 分区起始位置,所有分区最起始为0,单位为兆(M)。 | - | Length | 分区占用长度,单位为兆(M)。 | - | SelectFile | 实际镜像或文件所在路径。 | + | Sel | 该分区是否生效,1表明生效,0表明不生效。 | + | PartitionName | 分区名称,例如:fastboot、boot等。 | + | FlashType | flash磁盘类型,例如emmc、ufs等。 | + | FileSystem | 文件系统类型,例如ext3/4、f2fs等,也可能为none。 | + | Start | 分区起始位置,所有分区最起始为0,单位为兆(M)。 | + | Length | 分区占用长度,单位为兆(M)。 | + | SelectFile | 实际镜像或文件所在路径。 | 8. 执行升级包制作命令。 @@ -191,6 +214,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 命令如下: + ``` python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem ``` @@ -203,6 +227,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 命令如下: + ``` python build_update.py ./target_package/ ./output_package/ -s ./source_package.zip -pk ./rsa_private_key3072.pem ``` @@ -216,6 +241,7 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 命令如下: + ``` python build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key3072.pem -pf ./partition_file.xml ``` @@ -266,7 +292,8 @@ OTA(Over the Air)提供对设备远程升级的能力,可以让您的设 ### 示例代码 -使用OpenHarmony的“升级包格式和校验方法“进行升级。 + 使用OpenHarmony的“升级包格式和校验方法“进行升级。 + ``` int main(int argc, char **argv) { @@ -340,7 +367,8 @@ int main(int argc, char **argv) ### 示例代码 -使用非OpenHarmony的“升级包格式和校验方法“进行升级。 + 使用非OpenHarmony的“升级包格式和校验方法“进行升级。 + ``` int main(int argc, char **argv) { @@ -415,7 +443,8 @@ int main(int argc, char **argv) 对于使用Hi3518EV300/Hi3516DV300开源套件的轻量和小型系统,在需要实现防回滚功能的版本中,需要增加LOCAL_VERSION的值,如"ohos default 1.0"->"ohos default 1.1",LOCAL_VERSION在device\hisilicon\third_party\uboot\u-boot-2020.01\product\hiupdate\ota_update\ota_local_info.c中。 -示例,增加版本号。 + 示例,增加版本号。 + ``` const char *get_local_version(void) { diff --git a/zh-cn/device-dev/subsystems/subsys-ota.md b/zh-cn/device-dev/subsystems/subsys-ota.md new file mode 100644 index 0000000000000000000000000000000000000000..841cd25bd0fe235d13a67f57ed4c1d737862853c --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-ota.md @@ -0,0 +1,5 @@ +# 升级服务 + + + +- **[OTA升级](subsys-ota-guide.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-remote-start.md b/zh-cn/device-dev/subsystems/subsys-remote-start.md index 9d456643d321650e42b869ab992d76f617c48022..0cf26f8b0538e29872aa139f5a22e63220384376 100755 --- a/zh-cn/device-dev/subsystems/subsys-remote-start.md +++ b/zh-cn/device-dev/subsystems/subsys-remote-start.md @@ -1,113 +1,83 @@ -# 分布式远程启动 +# 分布式远程启动 -- [概述](#section186634310418) -- [基本概念](#section982651246) -- [接口说明](#section125479541744) -- [约束与限制](#section1165911177314) -- [开发步骤](#section34171333656) -## 概述 +## 概述 -分布式任务调度模块,通过主从设备服务代理机制,在OpenHarmony操作系统上建立起分布式服务平台,支持主设备\(搭载OpenHarmony的智慧屏设备\)启动从设备\(IP Camera、运动手表等小内存OpenHarmony设备\)FA的能力。 +分布式任务调度模块,通过主从设备服务代理机制,在OpenHarmony操作系统上建立起分布式服务平台,支持主设备(搭载OpenHarmony的智慧屏设备)启动从设备(IP Camera、运动手表等小内存OpenHarmony设备)FA的能力。 以智慧屏节目开播提醒为例,智慧屏上在喜欢的节目菜单中,点击“开播后提醒我”按钮,等节目开播后,智慧屏会拉起运动手表上的节目开播提醒FA。通过该FA用户可以快速知道喜欢的节目已经开始,达到协同互助的作用。 -## 基本概念 -- FA +## 基本概念 - Feature Ability代表有界面的Ability,用于与用户进行交互。 +- FA + Feature Ability代表有界面的Ability,用于与用户进行交互。 +- 远程启动 + 即跨设备启动FA,与本地启动FA相对应。 -- 远程启动 - 即跨设备启动FA,与本地启动FA相对应。 +## 接口说明 +智慧屏端分布式开放能力如下表,包含在AbilitySlice类中,具体的API接口详见OpenHarmony应用接入接口文档: -## 接口说明 + **表1** 分布式远程启动FA的API接口功能介绍 -智慧屏端分布式开放能力如下表,包含在AbilitySlice类中,具体的API接口详见OpenHarmony应用接入接口文档: +| 接口名 | 描述 | +| -------- | -------- | +| void startAbility(Want want) | 远程启动FA,Want参数命名以实际开发平台API为准。 | -**表 1** 分布式远程启动FA的API接口功能介绍 - - - - - - - - - - -

接口名

-

描述

-

void startAbility(Want want)

-

远程启动FA,Want参数命名以实际开发平台API为准。

-
- -**表 2** 参数Want功能介绍 - - - - - - - - - - - - -

参数名

-

类型

-

说明

-

want

-

ohos.aafwk.content.Want

-

当开发者需要调用该接口启动远程FA时,需要显式指定待启动FA的设备id、bundleName和abilityName。

-
- -## 约束与限制 - -- 支持主设备侧远程启动从设备侧FA,不支持从设备远程启动主设备FA。 -- 远程启动前必须确保OpenHarmony设备间分布式组网成功(需要在同一网段内,可互相ping通),否则无法远程启动。 -- 当前只支持拥有共同公钥信息的主从设备间FA(即主从设备的FA使用相同华为证书)的拉起。 - -## 开发步骤 + **表2** 参数Want功能介绍 -智慧屏侧通过如下操作启动从设备侧FA,从设备侧FA默认已开发。 +| 参数名 | 类型 | 说明 | +| -------- | -------- | -------- | +| want | ohos.aafwk.content.Want | 当开发者需要调用该接口启动远程FA时,需要显式指定待启动FA的设备id、bundleName和abilityName。 | + + +## 约束与限制 -1. 打开DevEco Studio,完成智慧屏侧FA开发。 -2. 获取目标在线从设备的设备ID。 - - ``` - // 引入设备选择头文件 - import ohos.distributedschedule.interwork.DeviceInfo; - import ohos.distributedschedule.interwork.DeviceManager; - - // 获取在线设备列表 - List deviceInfoListOnline = DeviceManager.getDmsDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); - String remote_device_id; - if (deviceInfoListOnline.size() > 0) - { - remote_device_id = deviceInfoListOnline[0].GetDeviceId(); // 获取在线列表中第一台设备的设备ID - } - ``` - -3. 构造want,首先使用ElementName类表明需要启动的远端设备ID,包名,Ability类名,传入want中,然后设置want中的分布式标志位Want.FLAG\_ABILITYSLICE\_MULTI\_DEVICE表示需要远程启动。 - - ``` - // 引入相关头文件 - import ohos.aafwk.ability.Ability; - import ohos.aafwk.content.Want; - import ohos.bundle.ElementName; - - // 启动远程设备FA - Want want = new Want(); // 封装启动远端FA的Want - // 使用步骤2中获取的设备ID,并指定FA信息 - ElementName name = new ElementName(remote_device_id, "com.huawei.remote_package_name", "remote_class_name"); - want.setElement(name); // 将待启动的FA信息添加到Want中 - want.setFlags(Want.FLAG_ABILITYSLICE_MULTI_DEVICE); // 设置分布式标记,若不设置将无法使用分布式能力 - startAbility(want); // 按照Want启动指定FA,Want参数命名以实际开发平台API为准 - ``` +- 支持主设备侧远程启动从设备侧FA,不支持从设备远程启动主设备FA。 +- 远程启动前必须确保OpenHarmony设备间分布式组网成功(需要在同一网段内,可互相ping通),否则无法远程启动。 + +- 当前只支持拥有共同公钥信息的主从设备间FA(即主从设备的FA使用相同华为证书)的拉起。 + + +## 开发步骤 + +智慧屏侧通过如下操作启动从设备侧FA,从设备侧FA默认已开发。 +1. 打开DevEco Studio,完成智慧屏侧FA开发。 + +2. 获取目标在线从设备的设备ID。 + + ``` + // 引入设备选择头文件 + import ohos.distributedschedule.interwork.DeviceInfo; + import ohos.distributedschedule.interwork.DeviceManager; + + // 获取在线设备列表 + List deviceInfoListOnline = DeviceManager.getDmsDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); + String remote_device_id; + if (deviceInfoListOnline.size() > 0) + { + remote_device_id = deviceInfoListOnline[0].GetDeviceId(); // 获取在线列表中第一台设备的设备ID + } + ``` + +3. 构造want,首先使用ElementName类表明需要启动的远端设备ID,包名,Ability类名,传入want中,然后设置want中的分布式标志位Want.FLAG_ABILITYSLICE_MULTI_DEVICE表示需要远程启动。 + + ``` + // 引入相关头文件 + import ohos.aafwk.ability.Ability; + import ohos.aafwk.content.Want; + import ohos.bundle.ElementName; + + // 启动远程设备FA + Want want = new Want(); // 封装启动远端FA的Want + // 使用步骤2中获取的设备ID,并指定FA信息 + ElementName name = new ElementName(remote_device_id, "com.huawei.remote_package_name", "remote_class_name"); + want.setElement(name); // 将待启动的FA信息添加到Want中 + want.setFlags(Want.FLAG_ABILITYSLICE_MULTI_DEVICE); // 设置分布式标记,若不设置将无法使用分布式能力 + startAbility(want); // 按照Want启动指定FA,Want参数命名以实际开发平台API为准 + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md b/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md index 7196714e220ec5db74474fd7840b6c7521730f2c..bfaaafc5743c44dd37e0b0470bb08b37cd0fec82 100644 --- a/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md +++ b/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md @@ -1,139 +1,118 @@ -# IPC通信鉴权开发指导 +# IPC通信鉴权开发指导 -- [场景介绍](#section18502174174019) -- [接口说明](#section1633115419401) -- [开发步骤](#section022611498210) -- [常见问题](#section15729104510271) -## 场景介绍 +## 场景介绍 系统服务通过IPC跨进程方式开放的接口,需要对接口调用者进行鉴权操作。在Samgr中注册的系统服务,可以通过进程间通信的方式暴露接口给其他进程访问,同时需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则访问会被拒绝。 当开发一个系统服务时,如果需要对外开放某些接口,开发者可以通过IPC通信鉴权组件配置这些接口的访问策略。当其他服务通过IPC方式访问这些接口时,会触发Samgr服务调用IPC通信鉴权组件的接口检查调用者服务是否有权限调用该接口。 -## 接口说明 + +## 接口说明 IPC通信鉴权提供的API,仅供Samgr调用,开发者在开发服务时需要配置对应的访问策略,Samgr会调用如下接口获取和检查调用者是否具有正确的访问权限,提供的API列表如下。 -**表 1** IPC通信鉴权API接口功能介绍 - - - - - - - - - - - - - -

接口名

-

描述

-

int GetCommunicationStrategy(RegParams params, PolicyTrans **policies, unsigned int *policyNum)

-

服务注册过程中查询调用接口对应的访问策略,仅供Samgr调用

-

int IsCommunicationAllowed(AuthParams params)

-

检查访问主体进程是否有权限调用受访客体进程的接口,仅供Samgr调用

-
- -## 开发步骤 + **表1** IPC通信鉴权API接口功能介绍 -本部分以BMS服务通过IPC通信方式对外开放接口为例,讲解如何通过IPC通信鉴权组件配置对应接口的访问策略。这里BMS在Samgr中注册的service为bundlems,为开放的接口注册的Feature为BmsFeature。 +| 接口名 | 描述 | +| -------- | -------- | +| int GetCommunicationStrategy(RegParams params, PolicyTrans \*\*policies, unsigned int \*policyNum) | 服务注册过程中查询调用接口对应的访问策略,仅供Samgr调用 | +| int IsCommunicationAllowed(AuthParams params) | 检查访问主体进程是否有权限调用受访客体进程的接口,仅供Samgr调用 | -1. OpenHarmony侧在源码路径下的头文件base/security/permission/services/permission\_lite/ipc\_auth/include/policy\_preset.h中配置相应的访问策略,产品侧独有的在vendor/hisilicon/产品名称/hals/security/permission\_lite/ipc\_auth/include/policy\_preset\_product.h中配置相应的访问策略,配置策略后将头文件中的宏POLICY\_PRODUCT 配置为1;访问策略主要有三种类型: - - (1)type为RANGE类型:允许某个特定范围UID的进程访问,需要指定uidMin和uidMax; - - (2)type为FIXED类型:允许指定的几个UID的进程访问,需要指定fixedUid,最多配置8个; - - (3)type为BUNDLENAME类型:只允许特定的应用访问,需要指定bundleName(包名); - - ``` - FeaturePolicy bmsFeature[] = { - { - "BmsFeature", - { - { - .type=FIXED, // 允许指定UID的进程访问的方式 - .fixedUid={2, 3, 8} - }, - { - .type=RANGE, // 允许特定范围内的UID的进程访问的方式 - .uidMin=100, - .uidMax=__INT_MAX__, - }, - } - }, - { - "BmsInnerFeature", - { - { - .type=FIXED, // 允许指定UID的进程访问的方式 - .fixedUid={2, 3, 8} - }, - { - .type=RANGE, - .uidMin=100, - .uidMax=999, - }, - } - }, - }; - ``` - -2. 将步骤1中定义的Feature的策略加配到全局策略中,需要配置feature数量; - - ``` - static PolicySetting g_presetPolicies[] = { - {"permissionms", pmsFeature, 1}, - {"abilityms", amsFeature, 2}, - {"bundlems", bmsFeature, 2}, // 步骤1定义的BMS的feature,数量为2 - {"dtbschedsrv", dmsFeature, 1}, - {"samgr", samgrFeature, 1}, - {"appspawn", appspawnFeature, 1}, - {"WMS", wmsFeature, 1}, - {"bundle_daemon", bdsFeature, 1}, - }; - ``` - -3. 将步骤1中定义的BmsFeature注册到Samgr; - - ``` - const char BMS_SERVICE[] = "bundlems"; - const char BMS_FEATURE[] = "BmsFeature"; - static void Init() - { - SamgrLite *sm = SAMGR_GetInstance(); - if (sm == nullptr) { - return; - } - // 注册服务到Samgr - sm->RegisterFeature(BMS_SERVICE, reinterpret_cast(BundleMsFeature::GetInstance())); - sm->RegisterFeatureApi(BMS_SERVICE, BMS_FEATURE, - GetBmsFeatureApi(reinterpret_cast(BundleMsFeature::GetInstance()))); - HILOG_DEBUG(HILOG_MODULE_APP, "BundleMS feature start success"); - } - APP_FEATURE_INIT(Init); - ``` +## 开发步骤 -完成以上开发步骤后,开发者在Samgr注册服务时,Samgr会调用IPC通信鉴权组件的GetCommunicationStrategy接口获取服务的访问策略;当其他服务或应用通过IPC方式访问这些服务时,Samgr会调用IPC通信鉴权组件的IsCommunicationAllowed接口检查调用者服务的权限,如果满足访问策略,则可以访问开发者接口,否则拒绝访问。 +本部分以BMS服务通过IPC通信方式对外开放接口为例,讲解如何通过IPC通信鉴权组件配置对应接口的访问策略。这里BMS在Samgr中注册的service为bundlems,为开放的接口注册的Feature为BmsFeature。 -## 常见问题 +1. OpenHarmony侧在源码路径下的头文件base/security/permission/services/permission_lite/ipc_auth/include/policy_preset.h中配置相应的访问策略,产品侧独有的在vendor/hisilicon/产品名称/hals/security/permission_lite/ipc_auth/include/policy_preset_product.h中配置相应的访问策略,配置策略后将头文件中的宏POLICY_PRODUCT 配置为1;访问策略主要有三种类型: + (1)type为RANGE类型:允许某个特定范围UID的进程访问,需要指定uidMin和uidMax; + + (2)type为FIXED类型:允许指定的几个UID的进程访问,需要指定fixedUid,最多配置8个; + + (3)type为BUNDLENAME类型:只允许特定的应用访问,需要指定bundleName(包名); + + ``` + FeaturePolicy bmsFeature[] = { + { + "BmsFeature", + { + { + .type=FIXED, // 允许指定UID的进程访问的方式 + .fixedUid={2, 3, 8} + }, + { + .type=RANGE, // 允许特定范围内的UID的进程访问的方式 + .uidMin=100, + .uidMax=__INT_MAX__, + }, + } + }, + { + "BmsInnerFeature", + { + { + .type=FIXED, // 允许指定UID的进程访问的方式 + .fixedUid={2, 3, 8} + }, + { + .type=RANGE, + .uidMin=100, + .uidMax=999, + }, + } + }, + }; + ``` + +2. 将步骤1中定义的Feature的策略加配到全局策略中,需要配置feature数量; + + ``` + static PolicySetting g_presetPolicies[] = { + {"permissionms", pmsFeature, 1}, + {"abilityms", amsFeature, 2}, + {"bundlems", bmsFeature, 2}, // 步骤1定义的BMS的feature,数量为2 + {"dtbschedsrv", dmsFeature, 1}, + {"samgr", samgrFeature, 1}, + {"appspawn", appspawnFeature, 1}, + {"WMS", wmsFeature, 1}, + {"bundle_daemon", bdsFeature, 1}, + }; + ``` + +3. 将步骤1中定义的BmsFeature注册到Samgr; + + ``` + const char BMS_SERVICE[] = "bundlems"; + const char BMS_FEATURE[] = "BmsFeature"; + static void Init() + { + SamgrLite *sm = SAMGR_GetInstance(); + if (sm == nullptr) { + return; + } + // 注册服务到Samgr + sm->RegisterFeature(BMS_SERVICE, reinterpret_cast(BundleMsFeature::GetInstance())); + sm->RegisterFeatureApi(BMS_SERVICE, BMS_FEATURE, + GetBmsFeatureApi(reinterpret_cast(BundleMsFeature::GetInstance()))); + HILOG_DEBUG(HILOG_MODULE_APP, "BundleMS feature start success"); + } + APP_FEATURE_INIT(Init); + ``` -- 开发新服务后,在Samgr注册失败问题 +完成以上开发步骤后,开发者在Samgr注册服务时,Samgr会调用IPC通信鉴权组件的GetCommunicationStrategy接口获取服务的访问策略;当其他服务或应用通过IPC方式访问这些服务时,Samgr会调用IPC通信鉴权组件的IsCommunicationAllowed接口检查调用者服务的权限,如果满足访问策略,则可以访问开发者接口,否则拒绝访问。 - **现象描述** - 开发完新服务后,在启动时出现服务在Samgr注册失败问题。 +## 常见问题 - **可能原因** +- 开发新服务后,在Samgr注册失败问题 + **现象描述** - 服务注册过程中,Samgr需要从IPC通信鉴权模块获取该服务的访问策略,但是未在该模块配置该服务的UID。 + 开发完新服务后,在启动时出现服务在Samgr注册失败问题。 - **解决办法** + **可能原因** - 在base/security/permission/services/permission\_lite/ipc\_auth/src/ipc\_auth\_impl.c中配置有效的服务的UID。 + 服务注册过程中,Samgr需要从IPC通信鉴权模块获取该服务的访问策略,但是未在该模块配置该服务的UID。 + **解决办法** + 在base/security/permission/services/permission_lite/ipc_auth/src/ipc_auth_impl.c中配置有效的服务的UID。 diff --git a/zh-cn/device-dev/subsystems/subsys-security-devicesecuritylevel.md b/zh-cn/device-dev/subsystems/subsys-security-devicesecuritylevel.md index 86252a4e700a8ae390e1126e7f629ca3eeab9605..8b0a56360ced6cdc6fa6b17a88794a93853f0575 100644 --- a/zh-cn/device-dev/subsystems/subsys-security-devicesecuritylevel.md +++ b/zh-cn/device-dev/subsystems/subsys-security-devicesecuritylevel.md @@ -16,11 +16,11 @@ OpenHarmony设备安全等级管理(DSLM)模块,负责管理各种不同 OpenHarmony系统安全架构如下图所示: - ![OpenHarmony系统安全架构](figure/ohos_system_security_architecture.png) + ![OpenHarmony系统安全架构](figures/ohos_system_security_architecture.png) 上图为典型的OpenHarmony单设备系统安全架构,在不同种类OpenHarmony设备上的实现可以存在差异,取决于设备的威胁分析(风险高低)和设备的软硬件资源。OpenHarmony在参考业界权威的安全分级模型基础上,结合OpenHarmony实际的业务场景和设备分类,将OpenHarmony设备的安全能力划分为 5 个安全等级:SL1 ~ SL5。OpenHarmony操作系统生态体系中,要求高一级的设备安全能力默认包含低一级的设备安全能力。分级概要可参考下图: - ![OpenHarmony设备安全等级](figure/ohos_device_security_level.png) + ![OpenHarmony设备安全等级](figures/ohos_device_security_level.png) - SL1为OpenHarmony设备中最低的安全等级。这类设备通常搭载轻量级系统和使用低端微处理器,业务形态较为单一,不涉及敏感数据的处理。本安全等级要求消除常见的错误,支持软件的完整性保护。若无法满足本等级的要求,则只能作为配件受OpenHarmony设备操控,无法反向操控OpenHarmony设备并进行更复杂的业务协同。 diff --git a/zh-cn/device-dev/subsystems/subsys-security-dslm.md b/zh-cn/device-dev/subsystems/subsys-security-dslm.md new file mode 100644 index 0000000000000000000000000000000000000000..a24c909f04fa14eb54a59d2e12e5dc9597756813 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-dslm.md @@ -0,0 +1,538 @@ +# 设备安全等级管理开发指南 + + +## 概述 + + +### 功能简介 + +OpenHarmony的分布式技术可以实现不同设备的资源融合,将多个设备虚拟成一个“超级虚拟终端”。在这个“超级虚拟终端”的内部,处理、流转各类用户数据时,需要确保各个节点不因安全能力薄弱,成为整个“超级虚拟终端”的薄弱点,因此引入设备安全等级管理(DSLM)模块来解决这类问题。 + +OpenHarmony设备安全等级管理(DSLM)模块,负责管理各种不同形态和种类的OpenHarmony设备的设备安全等级。在各类分布式业务中,当OpenHarmony对各类用户数据进行流转或处理的时候,可以调用本模块提供的接口获取相关目标设备的安全等级,并根据获取到的等级进行相应的处理。 + + +### 基本概念 + +- 设备安全等级 + +OpenHarmony设备的安全等级取决于设备的系统安全能力。OpenHarmony系统安全能力,根植于硬件实现的三个可信根:启动、存储、计算。基于基础安全工程能力,重点围绕以下三点构建相关的安全技术和能力:设备完整性保护、数据机密性保护、漏洞攻防对抗。 + +OpenHarmony系统安全架构如下图所示: + +![zh-cn_image_0000001217051568](figures/zh-cn_image_0000001217051568.png) + +上图为典型的OpenHarmony单设备系统安全架构,在不同种类OpenHarmony设备上的实现可以存在差异,取决于设备的威胁分析(风险高低)和设备的软硬件资源。OpenHarmony在参考业界权威的安全分级模型基础上,结合OpenHarmony实际的业务场景和设备分类,将OpenHarmony设备的安全能力划分为 5 个安全等级:SL1 ~ SL5。OpenHarmony操作系统生态体系中,要求高一级的设备安全能力默认包含低一级的设备安全能力。分级概要可参考下图: + +![zh-cn_image_0000001217371532](figures/zh-cn_image_0000001217371532.png) + +- SL1为OpenHarmony设备中最低的安全等级。这类设备通常搭载轻量级系统和使用低端微处理器,业务形态较为单一,不涉及敏感数据的处理。本安全等级要求消除常见的错误,支持软件的完整性保护。若无法满足本等级的要求,则只能作为配件受OpenHarmony设备操控,无法反向操控OpenHarmony设备并进行更复杂的业务协同。 + +- SL2安全等级的OpenHarmony设备,可对自身数据进行标记并定义访问控制规则,实现自主的访问控制,需要具备基础的抗渗透能力。此级别设备可支持轻量化的可安全隔离环境,用于部署少量必需的安全业务。 + +- SL3安全等级的OpenHarmony设备,具备较为完善的安全保护能力。其操作系统具有较为完善的安全语义,可支持强制访问控制。系统可结构化为关键保护元素和非关键保护元素,其关键保护元素被明确定义的安全策略模型保护。此级别设备应具备一定的抗渗透能力,可对抗常见的漏洞利用方法。 + +- SL4安全等级的OpenHarmony设备,可信基应保持足够的精简,具备防篡改的能力。SL4的实现应足够精简和安全,可对关键保护元素的访问控制进行充分的鉴定和仲裁。此级别设备具备相当的抗渗透能力,可抑制绝大多数软件攻击。 + +- SL5安全等级的OpenHarmony设备,为OpenHarmony设备中具备最高等级安全防护能力的设备。系统核心软件模块应进行形式化验证。关键硬件模块如可信根、密码计算引擎等应具备防物理攻击能力,可应对实验室级别的攻击。此级别设备应具备高安全单元,如专用的安全芯片,用于强化设备的启动可信根、存储可信根、运行可信根。 + - DSLM + +DSLM(Device Security Level Managerment), 是OpenHarmony设备安全等级管理的管理模块。负责各OpenHarmony设备之间的设备安全等级信息的同步和验证。并对外提供查询各设备的安全等级的接口。 + + +### 运作机制 + +当“超级虚拟终端”内的各个设备有了自己的“设备安全等级”,这个“超级虚拟终端”的内部,各类用户数据的处理或流转便有了决策依据。例如:分布式文件存储服务,在处理某些敏感数据时,默认不允许相关数据存储在安全等级低于SL3的设备。 + + +### 约束与限制 + +OpenHarmony设备的默认安全等级为SL1,设备制造商可以根据设备实际情况定制更高的安全等级。详细请参考章节[设备安全等级定制](#设备安全等级定制)。 + + +## 开发指导 + + +### 场景介绍 + +各子系统在处理、流转各类用户数据时,可以调用DSLM模块提供的接口,获取相关设备的安全等级信息。并结合其所处理数据的实际情况,决策数据的进一步处理。 + + +### 接口说明 + +所有接口均为native C内部接口,仅提供底层能力,不对App开放。相关接口列表如下: + + | | | +| -------- | -------- | +| 接口名 | 说明 | +| int32_t RequestDeviceSecurityInfo(const DeviceIdentify \*identify, const RequestOption \*option, DeviceSecurityInfo \*\*info); | 请求获取某设备的设备安全等级信息(同步接口) | +| int32_t RequestDeviceSecurityInfoAsync(const DeviceIdentify \*identify, const RequestOption \*option, DeviceSecurityInfoCallback callback); | 请求获取某设备的设备安全等级信息(异步接口) | +| void FreeDeviceSecurityInfo(DeviceSecurityInfo \*info); | 释放设备安全等级信息 | +| int32_t GetDeviceSecurityLevelValue(const DeviceSecurityInfo \*info, int32_t \*level); | 从设备安全等级信息中提取对应的设备安全等级 | + + +### 开发步骤 + +1. 编译依赖添加 + + ``` + external_deps += [ "device_security_level:dslm_sdk" ] + ``` + +2. 头文件依赖添加 + + ``` + #include "device_security_defines.h" // 关键数据结构定义头文件 + #include "device_security_info.h" // 接口函数定义头文件 + ``` + +3. 接口调用 + + ``` + // 查询参数1, 构造获取需要查询设备的设备UDID + const DeviceIdentify *device = GetDestDeviceUdid(); + + // 查询参数2,查询RequestOption构造 + const RequestOption *option = DEFAULT_OPTION; + + // 查询参数3,设备安全等级信息指针,用来接收返回结果 + DeviceSecurityInfo *info = NULL; + + // 调用RequestDeviceSecurityInfo接口获取对端设备的设备安全等级信息: + int32_t ret = RequestDeviceSecurityInfo(device, DEFAULT_OPTION, &info); + + int32_t level = 0; + // 从设备安全等级信息中提取设备安全等级字段 + ret = GetDeviceSecurityLevelValue(info, &level); + if (ret == SUCCESS) { + // 查询成功。 + return; + } + // 结束处理前,需要释放内存 + FreeDeviceSecurityInfo(info); + ``` + + +### 开发示例 + +假设需要开发具备文件分享功能的某业务,为了防止部分敏感文件被无意识的分享出来。可以在其发送任意文件前增加如下判断处理: + +- 当目标设备的设备安全等级大于或者等于SL3时,默认允许该文件的传递。 + +- 当目标设备的设备安全等级小于SL3时,默认拒绝该文件的外传,同时弹框告知用户。 + +1. 同步接口使用示例 + + ``` + void CheckDestDeviceSecurityLevel(const DeviceIdentify *device, RequestOption *option) + { + // 设备安全等级信息指针 + DeviceSecurityInfo *info = NULL; + // 调用同步接口获取设备的安全等级等级信息 + int32_t ret = RequestDeviceSecurityInfo(device, option, &info); + if (ret != SUCCESS) { + // 获取信息失败。此场景建议开发者根据实际情况进行重试 + return; + } + int32_t level = 0; + // 从设备安全等级信息中提取设备安全等级字段 + ret = GetDeviceSecurityLevelValue(info, &level); + if (ret != SUCCESS) { + // 提取信息失败, 此场景建议开发者根据实际情况进行重试 + return; + } + // 成功获取到设备安全等级,确认当前操作允许的最低安全等级 + // 假设当前操作允许的最低设备安全等级为3 + if (level >= 3) { + // 目标设备的设备安全等级满足要求, 相关业务正常处理 + } else { + // 目标设备的设备安全等级不满足要求, 建议开发者结合实际业务场景进行相应处理,例如告警、弹窗提示用户等 + } + // 结束处理前,需要释放内存 + FreeDeviceSecurityInfo(info); + } + ``` + +2. 异步接口使用示例 + + ``` + // 回调函数 + void DeviceSecurityInfoCallback(const DeviceIdentify *identify, struct DeviceSecurityInfo *info) + { + int32_t level = 0; + // 从设备安全等级信息中提取设备安全等级字段 + int32_t ret = GetDeviceSecurityLevelValue(info, &level); + if (ret != SUCCESS) { + // 获取信息失败。此场景建议开发者根据实际情况进行重试 + return; + } + // 成功获取到设备安全等级,确认当前操作允许的最低安全等级 + // 假设当前操作允许的最低设备安全等级为3 + if (level >= 3) { + // 目标设备的设备安全等级满足要求, 相关业务正常处理 + } else { + // 目标设备的设备安全等级不满足要求, 建议开发者结合实际业务场景进行相应处理,例如告警、弹窗提示用户等 + } + // 结束处理前,需要释放内存 + FreeDeviceSecurityInfo(info); + } + + void CheckDestDeviceSecurityLevelAsync(const DeviceIdentify *device, RequestOption *option) + { + // 调用异步接口获取设备设备的安全等级等级信息 + int ret = RequestDeviceSecurityInfoAsync(device, option, DeviceSecurityInfoCallback); + if (ret != SUCCESS) { + // 获取信息失败,此场景建议开发者根据实际情况进行重试 + // 此场景下callback不会回调。 + return; + } + // 调用成功,等待callback回调。 + } + ``` + + +## 设备安全等级定制 + + +### 设备安全等级凭据 + +为了保证设备安全等级信息的完整性和不可抵赖性。设备的安全等级信息需要封装在“设备安全等级凭据”(简称为“凭据”)文件中在设备间进行传递,凭据中除了包含设备的安全等级信息之外,还可以包含设备型号、设备版本号等其它设备固有属性,同时使用PKI技术对上述信息进行签名。并结合[设备认证](https://gitee.com/openharmony/security_deviceauth)、[HUKS](https://gitee.com/openharmony/security_huks)等OpenHarmony其他基础安全能力。最大程度的保证了凭据传递的安全性。 + + +### 默认实现 + +OpenHarmony的设备安全等级管理模块提供了安全等级信息同步与验证的默认实现。它假定所有OpenHarmony设备的安全等级为SL1,并且采用了一套较为宽松的验证方案。详细细节可以参考[相关源码](https://gitee.com/openharmony/security_device_security_level/tree/master/oem_property/ohos)。 + +设备制造商可以根据设备实际情况,参考[基本概念](#基本概念)章节的描述,修改默认的设备安全等级信息。与此同时,设备制造商还可以将OpenHarmony中的默认实现替换为更加严格的验证策略,包括但不限于采用更加精确的一机一凭据策略、从服务器定期下载更新的凭据并严格认证凭据的签发者和有效期、使用TEE(Trusted Execution Environment)甚至SE(Secure Element)对凭据文件进行进一步的签名等流程。 + + +### 凭据文件生成步骤 + +凭据文件为4段BASE64编码的字符串,中间用"."链接,示例如下: + + +``` +... +``` + + +### 1. 构造header + +当前header为固定的json字符串,其格式化显示如下 + + +``` +{ + "typ": "DSL" +} +``` + + 对原header字符串进行BASE64编码,得到 + +``` + +``` +: + + +``` +eyJ0eXAiOiAiRFNMIn0= +``` + + +### 2. 构造payload + +根据设备实际情况构造payload的json字符串,示例如下: + + +``` +{ + "type": "debug", + "manufacture": "ohos", + "brand": "rk3568", + "model": "rk3568", + "softwareVersion": "3.2.2", + "securityLevel": "SL1", + "signTime": "20220209150259", + "version": "1.0.1" +} +``` + +对payload字符串进行BASE64编码,得到<base64-payload>: + + +``` +eyJ0eXBlIjogImRlYnVnIiwgIm1hbnVmYWN0dXJlIjogIm9ob3MiLCAiYnJhbmQiOiAicmszNTY4IiwgIm1vZGVsIjogInJrMzU2OCIsICJzb2Z0d2FyZVZlcnNpb24iOiAiMy4yLjIiLCAic2VjdXJpdHlMZXZlbCI6ICJTTDEiLCAic2lnblRpbWUiOiAiMjAyMjAyMDkxNTAyNTkiLCAidmVyc2lvbiI6ICIxLjAuMSJ9 +``` + +payload中各字段说明如下: + + | | | | | +| -------- | -------- | -------- | -------- | +| 字段名 | 字段说明 | 是否必选字段 | 取值范围 | +| type | 凭据发布类型 | 是 | [debug release] | +| manufacture | 设备制造商信息 | 是 | string [0..128] | +| brand | 设备品牌信息 | 是 | string [0..128] | +| model | 设备型号信息 | 是 | string [0..128] | +| softwareVersion | 设备软件版本号信息 | 是 | string [0..128] | +| securityLevel | 设备安全等级信息 | 是 | [SL1 SL2 SL3 SL4 SL5] | +| signTime | 本凭据签名时间 | 是 | string [0..128] | +| version | 本凭据版本号 | 是 | string [0..32] | +| sn | 设备SN序列号 | 否 | string [0..128] | +| udid | 设备UDID序列号 | 否 | string [0..128] | + + +### 3. 构造signature + +signature是对前面header和payload的签名 + + +### 3.1 构造构建待签名的原始数据 + +将BASE64编码后的header和payload合并,中间用符号"."连接,得到<base64-head>.<base64-payload> + +示例如下: + + +``` +eyJ0eXAiOiAiRFNMIn0=.eyJ0eXBlIjogImRlYnVnIiwgIm1hbnVmYWN0dXJlIjogIm9ob3MiLCAiYnJhbmQiOiAicmszNTY4IiwgIm1vZGVsIjogInJrMzU2OCIsICJzb2Z0d2FyZVZlcnNpb24iOiAiMy4yLjIiLCAic2VjdXJpdHlMZXZlbCI6ICJTTDEiLCAic2lnblRpbWUiOiAiMjAyMjAyMDkxNTAyNTkiLCAidmVyc2lvbiI6ICIxLjAuMSJ9 +``` + + +### 3.2 生成签名私钥 + +凭据文件使用ECDSA签名算法对原始数据进行签名,首先生成签名用ECDSA密钥对:<ecc-l3-pk> 和 <ecc-l3-sk> + +> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** +> 本流程需要在安全可靠的环境中执行,例如符合相关安全要求的服务器密码机中,以确保用于签名的密钥不被泄露 + + +### 3.3 对原始数据进行签名 + +将 <base64-head>.<base64-payload>作为参数,使用刚刚生成的ECC私钥<ecc-l3-sk>对其进行签名,并对签名结果进行BASE64编码,得到签名结果值<base64-signature>: + + +``` +MGUCMDb9xoiFzTWVkHDU3VWSVQ59gLyw4TchZ0+eQ3vUfQsLt3Hkg0r7a/PmhkNr3X/mTgIxAIywIRE6vRTRs0xk6xKp8A0XwMMiIyjZlujPJfasCvFonpsvXLAqCAIYbe1J0k4Zfg== +``` + + +### 4. 构造attestation + +> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** +> 本流程需要在安全可靠的环境中执行,例如符合相关安全要求的服务器密码机中,以确保用于签名的密钥不被泄露 +> +> 本流程涉及到的各密钥对不需要每次都重复生成,在确保密钥安全的前提下,后续可以直接复用。 + + +### 4.1 生成三级签名验证信息 + +1. 首先生成二级签名用ECDSA密钥对:<ecc-l2-pk>和<ecc-l2-sk> + +2. 使用<ecc-l2-sk> 对3.2章节生成的<ecc-l3-pk>进行签名,得到<ecc-l3-pk-signature> + +3. 将<ecc-l3-pk>和<ecc-l3-pk-signature>组合成json字符串示例如下: + + +``` +{ + "userPublicKey": "", + "signature": "" +} +``` + + +### 4.2 生成二级签名验证信息 + +1. 生成一级签名用ECDSA密钥对:<ecc-root-pk>和<ecc-root-sk> + +2. 使用<ecc-root-sk> 对4.1章节生成的<ecc-l2-pk>进行签名,得到<ecc-l2-pk-signature> + +3. 将<ecc-l3-pk>和<ecc-l3-pk-signature>组合成json字符串示例如下: + + +``` +{ + "userPublicKey": "", + "signature": "" +} +``` + + +### 4.3 生成根签名验证信息 + +1. 使用<ecc-root-sk> 对4.2章节生成的<ecc-root-pk>进行签名(即自签名),得到<ecc-root-pk-self-signature> + +2. 将<ecc-root-pk>和<ecc-root-pk-self-signature>组合成json字符串 + +示例如下: + + +``` +{ + "userPublicKey": "", + "signature": "" +} +``` + + +### 4.4 合并生成attestation + +1. 将上述三组签名信息合并到一个json数组中: + + ``` + [ + { + "userPublicKey": "", + "signature": "" + }, + { + "userPublicKey": "", + "signature": "" + }, + { + "userPublicKey": "", + "signature": "" + } + ] + ``` + +2. 对该数据进行base64编码,得到<base64-attestation> + + ``` + W3sidXNlclB1YmxpY0tleSI6ICJNSG93RkFZSEtvWkl6ajBDQVFZSkt5UURBd0lJQVFFTEEySUFCREdOMU9xYWZrWFc2a0l1SEZrMVQ0TS84RVJUY3p0eWRDaGtramFROEkzNEc2Q3E1aTNJcnczVnRhQS9KTTF2a0lHOUZDVWRUaHZFUlJFUTFUdG9xemdxZW9SUzVwQW1EYUUyalEwYzdDem8rOHVUWTRIYW1weXZ1TENtenlYUXFnPT0iLCAic2lnbmF0dXJlIjogIk1HTUNMeHVjUnoyZndKZ092QkxyU1U3K1hlVTA3R0EyVXhZbDFMbEJLUnVIUS9wZlNWVHBEd0ZHSTNTb3h5ODR3NThIQWpBeGRtNEY3b3YvYUtEL0NFZi9QZlZDWHVlbE1mQys1L3pkUExXUUJEVnlGdWQrNVdYL3g4U083VXM5UGFhRW1mZz0ifSwgeyJ1c2VyUHVibGljS2V5IjogIk1Ib3dGQVlIS29aSXpqMENBUVlKS3lRREF3SUlBUUVMQTJJQUJHMWU3TDJVd1AyWWxTajB2RWViUGJpNVpLMDh5NS9UeHRWb3VrRFpIUGtSNlRtb2JoVGpyMVRVNzZpUkU4bDlWQlhuU1h1QVB6cjBuSHdKVkdVZVJMdmp4MVh0YUZReE9QNjhjNlIvRTdFWkZ2STdRUFg1N0tvRkhYdkEvVlJaNnc9PSIsICJzaWduYXR1cmUiOiAiTUdRQ01FUVdFNnk0Rm42SFg1ekFvTzNkYzl5cG1Sd2lBclplc2o5aVBROTZEaEhuNXJkRTdNaGFMdWNRZ0MvaXhjSWJsZ0l3QkN5aFBvRUg2RjFITFlwM2xqbWVncVlZQ1E5NHEyZm1kbDB6dHhrWEVTOVpPOVRNSUZQRVpKYlpmUnU5ZHcyOSJ9LCB7InVzZXJQdWJsaWNLZXkiOiAiTUhvd0ZBWUhLb1pJemowQ0FRWUpLeVFEQXdJSUFRRUxBMklBQkZRUUlDWmpWUTV4bkE0c2RMbUJzUmVaMzRJeWdkSmZhanA3SnRReFBzU2RwWTJXV0FneXp6Rm40OFFRRWhoU1BtdzhJYUU3VlJKRENBT3FYRnhGektJbFBFTDFvcFJDUmhhWmJrRzc5Y3ZrWC9HVVhlaFVYc2V2ZGhyb2VRVERFdz09IiwgInNpZ25hdHVyZSI6ICJNR1FDTUdQRndvSDJLbHhwbVZhWXRWV1ViMHpDSUJxYXFXY2F6czFqOVp4YklLUmVkR2tJY0VJdHN0UFoxdnVTanYvNDJnSXdSeGZPcTRoQTdNMHlGV2ZPSndqRTlTc2JsYXhvRDNiRTZCYzN2QjUyMmsyQ0ZJNWJqelpkeUFTVW04d2J2TW5WIn1d + ``` + + +### 5. 构造完整的凭据 + +用符号"."连接上述四段数据,最终得到 <base64-header>.<base64-payload>.<base64-signature>.<base64-attestation>,其示例如下: + + +``` +eyJ0eXAiOiAiRFNMIn0=.eyJ0eXBlIjogImRlYnVnIiwgIm1hbnVmYWN0dXJlIjogIm9ob3MiLCAiYnJhbmQiOiAicmszNTY4IiwgIm1vZGVsIjogInJrMzU2OCIsICJzb2Z0d2FyZVZlcnNpb24iOiAiMy4yLjIiLCAic2VjdXJpdHlMZXZlbCI6ICJTTDEiLCAic2lnblRpbWUiOiAiMjAyMjAyMDkxNTAyNTkiLCAidmVyc2lvbiI6ICIxLjAuMSJ9.MGUCMDb9xoiFzTWVkHDU3VWSVQ59gLyw4TchZ0+eQ3vUfQsLt3Hkg0r7a/PmhkNr3X/mTgIxAIywIRE6vRTRs0xk6xKp8A0XwMMiIyjZlujPJfasCvFonpsvXLAqCAIYbe1J0k4Zfg==.W3sidXNlclB1YmxpY0tleSI6ICJNSG93RkFZSEtvWkl6ajBDQVFZSkt5UURBd0lJQVFFTEEySUFCREdOMU9xYWZrWFc2a0l1SEZrMVQ0TS84RVJUY3p0eWRDaGtramFROEkzNEc2Q3E1aTNJcnczVnRhQS9KTTF2a0lHOUZDVWRUaHZFUlJFUTFUdG9xemdxZW9SUzVwQW1EYUUyalEwYzdDem8rOHVUWTRIYW1weXZ1TENtenlYUXFnPT0iLCAic2lnbmF0dXJlIjogIk1HTUNMeHVjUnoyZndKZ092QkxyU1U3K1hlVTA3R0EyVXhZbDFMbEJLUnVIUS9wZlNWVHBEd0ZHSTNTb3h5ODR3NThIQWpBeGRtNEY3b3YvYUtEL0NFZi9QZlZDWHVlbE1mQys1L3pkUExXUUJEVnlGdWQrNVdYL3g4U083VXM5UGFhRW1mZz0ifSwgeyJ1c2VyUHVibGljS2V5IjogIk1Ib3dGQVlIS29aSXpqMENBUVlKS3lRREF3SUlBUUVMQTJJQUJHMWU3TDJVd1AyWWxTajB2RWViUGJpNVpLMDh5NS9UeHRWb3VrRFpIUGtSNlRtb2JoVGpyMVRVNzZpUkU4bDlWQlhuU1h1QVB6cjBuSHdKVkdVZVJMdmp4MVh0YUZReE9QNjhjNlIvRTdFWkZ2STdRUFg1N0tvRkhYdkEvVlJaNnc9PSIsICJzaWduYXR1cmUiOiAiTUdRQ01FUVdFNnk0Rm42SFg1ekFvTzNkYzl5cG1Sd2lBclplc2o5aVBROTZEaEhuNXJkRTdNaGFMdWNRZ0MvaXhjSWJsZ0l3QkN5aFBvRUg2RjFITFlwM2xqbWVncVlZQ1E5NHEyZm1kbDB6dHhrWEVTOVpPOVRNSUZQRVpKYlpmUnU5ZHcyOSJ9LCB7InVzZXJQdWJsaWNLZXkiOiAiTUhvd0ZBWUhLb1pJemowQ0FRWUpLeVFEQXdJSUFRRUxBMklBQkZRUUlDWmpWUTV4bkE0c2RMbUJzUmVaMzRJeWdkSmZhanA3SnRReFBzU2RwWTJXV0FneXp6Rm40OFFRRWhoU1BtdzhJYUU3VlJKRENBT3FYRnhGektJbFBFTDFvcFJDUmhhWmJrRzc5Y3ZrWC9HVVhlaFVYc2V2ZGhyb2VRVERFdz09IiwgInNpZ25hdHVyZSI6ICJNR1FDTUdQRndvSDJLbHhwbVZhWXRWV1ViMHpDSUJxYXFXY2F6czFqOVp4YklLUmVkR2tJY0VJdHN0UFoxdnVTanYvNDJnSXdSeGZPcTRoQTdNMHlGV2ZPSndqRTlTc2JsYXhvRDNiRTZCYzN2QjUyMmsyQ0ZJNWJqelpkeUFTVW04d2J2TW5WIn1d +``` + + +### 凭据交换协议 + +设备安全等级模块在感知到有新设备上线时,会通过[分布式软总线](https://gitee.com/openharmony/communication_dsoftbus)提供的通道向该设备请求其设备安全等级凭据。 + +凭据请求报文格式如下: + + +``` +{ + "message": 1, + "payload": { + "version": 196608, + "challenge": "0102030405060708", + "support": [ + 300 + ] + } +} +``` + +其中各个字段解释如下: + + | 字段名 | 含义解释 | +| -------- | -------- | +| message | 消息头,取值1表示设备安全等级凭据请求 | +| payload | 消息payload,具体的请求信息 | +| version | 请求端协议版本号 | +| challenge | 本次请求信息对应的挑战值 | +| support | 请求端支持的凭据格式列表 | + +对端设备在接受到凭据请求后,会按照如下格式进行回复 + + +``` +{ + "message": 2, + "payload": { + "version": 196608, + "type": 300, + "challenge": "0102030405060708", + "info": "YWJjZAEDBQcJ..." + } +} +``` + +其中各个字段解释如下: + + | | | +| -------- | -------- | +| 字段名 | 含义解释 | +| message | 消息头,取值2表示设备安全等级凭据应答 | +| payload | 消息payload,具体的应答信息 | +| version | 应答端协议版本号 | +| type | 应答端本次返回的凭据格式,用来描述如何解析info字段 | +| challenge | 本次应答信息对应的挑战值 | +| info | 签名后的凭据信息,同时还包含设备绑定关系、挑战值校验等信息 | + + +### 工具使用介绍 + +为方便开发者对于“凭据文件”的进一步理解,设备安全等级管理模块提供了[凭据工具](https://gitee.com/openharmony/security_device_security_level/blob/master/oem_property/ohos/dslm_cred_tool.py),该工具是一个python脚本,基于OPENSSL命令行的简单封装,可以便捷的提供凭据文件的签发和验证功能。其使用方法如下: + +1. 签名密钥初始化: + + ``` + ./dslm_cred_tool.py init + ``` + +2. 凭据文件的生成: + 生成一个名为cred.txt的凭据文件,并指定设备型号为rk3568、设备版本号为3.0.0、设备安全等级为SL3等payload信息。 + + ``` + ./dslm_cred_tool.py create --field-manufacture OHOS --field-brand rk3568 --field-model rk3568 --field-software-version 3.0.0 --field-security-level SL3 --cred-file cred.txt + ``` + + 上述命令可以生成一个凭据示例文件如下: + + ``` + cat cred.txt eyJ0eXAiOiAiRFNMIn0=.eyJ0eXBlIjogImRlYnVnIiwgIm1hbnVmYWN0dXJlIjogIk9IT1MiLCAiYnJhbmQiOiAicmszNTY4IiwgIm1vZGVsIjogInJrMzU2OCIsICJzb2Z0d2FyZVZlcnNpb24iOiAiMy4wLjAiLCAic2VjdXJpdHlMZXZlbCI6ICJTTDMiLCAic2lnblRpbWUiOiAiMjAyMjAyMDkxNTUzMDMiLCAidmVyc2lvbiI6ICIxLjAuMSJ9.MGQCMEqZy/snsRyjMupnEvTpQfhQn+IcdCc5Q3NGxllNQVhoZX8PNyw6ATTgyx+26ghmtQIwVH5KwQ4/VejxckeHmtkBVhofhgmRapzvyVnyiB3PdsU7nvHk8A/zC7PFy1CWBG3z.W3sidXNlclB1YmxpY0tleSI6ICJNSG93RkFZSEtvWkl6ajBDQVFZSkt5UURBd0lJQVFFTEEySUFCQzFXRUxSVlU1NGp1U1ZXWlUrT29CM3hacFd5MWg3QW5uSFdKWm5QbTB3S2l0ZlJZelJKZ3FiUGQyZ3ltVXBUWVl1cmhyRDQxbFdPbUNzcmt0VWdaNTFXdGNCTmc5SG1GODkzc2ZHVFM5eUJNS0JoMGcxSHZaSVFSN1k0S3FXaWpnPT0iLCAic2lnbmF0dXJlIjogIk1HUUNNRFVicTZ2Z2R1YVF0bFVwOTR0azd4VjRJcEx2WVZWY3Y4aFNOTkw0azdPRHhmbEVGTHJFaUdPRWhwMUcweGFGYlFJd1pUbTk1cWx4OTBFZnptV3VIOGlEY2ZWYVlQS2N5SEYwR2ZFcEUzb1NESzQwZEFOZ0FJMWVQY09rTzBPOTdnTFAifSwgeyJ1c2VyUHVibGljS2V5IjogIk1Ib3dGQVlIS29aSXpqMENBUVlKS3lRREF3SUlBUUVMQTJJQUJGKzY1a0lSYTM2dkE4QVZWNXFrcUozYXpXTkdGQy9oaVdPL0tFNHR0S1pMOUsyNlhzQ2hQbjVNc3BlT2F3b1dqSU02bTVLOFZTcU1DYlZNN0svY0VRU0tYdDJTeVJGZERVZU9TaFZmQm9YVmxqaXRUU2puN0V5Q2pERVZiWjFRNEE9PSIsICJzaWduYXR1cmUiOiAiTUdRQ01HanF2cnZ5VW1YNVZLVVc1UkFkUTNkZ2hBYmNBazBRQnppQlFWMVFZUTNQMVFPSzdMckM1b0RObXh6T2Y0QUtmd0l3SzVWU2x3ZG5JSUR6Zm9PUXBEUVAycGhTVGgxSGVjbXJRK1F4VGxWelo0aHJsdnJyd2xCNnp0T3pWRFdNblRELyJ9LCB7InVzZXJQdWJsaWNLZXkiOiAiTUhvd0ZBWUhLb1pJemowQ0FRWUpLeVFEQXdJSUFRRUxBMklBQkZCa2FDNE9mc2VTREt2cW8vbU5VaUtXQ3JtK1VDNGFQcjVsODRNM2tMVCtDdkd3OWhqOGJ6d2I1MzNtVVlFZVhWWWtUdFlRYWRURkRJZXV1dGIzNU1QZDlEKytNMFRFWnZvcTY4NFhoYTVQMzBUbVRhK0ZvOG02UWliZWc3TmFQdz09IiwgInNpZ25hdHVyZSI6ICJNR1FDTURJcmpNYzhvODVPRHFZT0R4c05PcmpYdUhvWjM5endpZlhVTkdDc0lkN2xjU2FWcnhCVlNqRjRyaWg5Y1R6T3dRSXdWQXA3RUF5c1pucEI5REJWVWczQzlMeGQ3eTQxWEMwYVVPcGZUKzI3REVvWmM1WVVldDFGa1FwdmFQckduaFhVIn1d + ``` + +3. 凭据文件的校验: + + ``` + ./dslm_cred_tool.py verify --cred-file cred.txt + ``` + + 验证回显如下: + + ``` + head: + { + "typ": "DSL" + } + payload: + { + "type": "debug", + "manufacture": "OHOS", + "brand": "rk3568", + "model": "rk3568", + "softwareVersion": "3.0.0", + "securityLevel": "SL3", + "signTime": "20220209155303", + "version": "1.0.1" + } + verify success! + ``` + + +## 常见问题 + +- Q:凭据工具如何在真实的生产环境中使用? + +A:凭据工具不可以直接用于生产环境,它仅仅是一个示例,用来演示凭据的具体格式和生成过程。在真实的生产环境中,我们建议参考凭据工具的实现,在符合相关安全要求的服务器密码机中进行凭据的生成和相关密钥的保存。 + +- Q:真实的生产环境中,如何对凭据文件进行校验? + +A:我们建议设备制造商使用妥善保管的私钥对凭据文件进行签名,同时替换OpenHarmony中对于凭据文件的默认校验流程,增加对凭据签名者的严格校验。例如仅认可信任机构签发的凭据文件、增加凭据和设备ID的一对一强绑定等校验。 + + +## 参考资料 + +无 diff --git a/zh-cn/device-dev/subsystems/subsys-security-overview.md b/zh-cn/device-dev/subsystems/subsys-security-overview.md index 1184dc532d94a6da819e827abd82ba6e0d119028..6072cca21a6ad751e5d2b059a1839d2f06e2af07 100644 --- a/zh-cn/device-dev/subsystems/subsys-security-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-security-overview.md @@ -1,64 +1,57 @@ -# 概述 +# 概述 -- [概述](#概述) - - [基本概念](#基本概念) - - [约束与限制](#约束与限制) OpenHarmony安全子系统目前提供给开发者的安全能力主要包含应用可信、权限管理、设备可信。涉及以下几个模块: -- 应用验签 - 为了确保应用内容的完整性,系统通过应用签名和Profile对应用的来源进行管控,同时对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 +- 应用验签 -- 应用权限管理 + 为了确保应用内容的完整性,系统通过应用签名和Profile对应用的来源进行管控,同时对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 - 应用权限是管理应用访问系统资源和使用系统能力的一种通用方式,应用在开发阶段需要在profile.json中指明此应用在运行过程中可能会调用哪些权限,其中静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示涉及到敏感信息,所以需要用户进行动态授权。 +- 应用权限管理 -- IPC通信鉴权 + 应用权限是管理应用访问系统资源和使用系统能力的一种通用方式,应用在开发阶段需要在profile.json中指明此应用在运行过程中可能会调用哪些权限,其中静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示涉及到敏感信息,所以需要用户进行动态授权。 - 系统服务通过IPC跨进程方式开放的接口,需要对接口调用者进行鉴权操作。在Samgr中注册的系统服务,可以通过进程间通信的方式暴露接口给其他进程访问,同时需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则访问会被拒绝。 +- IPC通信鉴权 -- 设备安全等级管理 + 系统服务通过IPC跨进程方式开放的接口,需要对接口调用者进行鉴权操作。在Samgr中注册的系统服务,可以通过进程间通信的方式暴露接口给其他进程访问,同时需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则访问会被拒绝。 - OpenHarmony设备安全等级管理(DSLM)模块,负责管理各种不同形态和种类的OpenHarmony设备的设备安全等级。对于OpenHarmony中的各类分布式业务,当其对各类用户数据进行流转或处理的时候,可以调用本模块提供的接口获取相关目标设备的安全等级,并根据获取到的等级进行相应的处理。 +- 设备安全等级管理 + OpenHarmony设备安全等级管理(DSLM)模块,负责管理各种不同形态和种类的OpenHarmony设备的设备安全等级。对于OpenHarmony中的各类分布式业务,当其对各类用户数据进行流转或处理的时候,可以调用本模块提供的接口获取相关目标设备的安全等级,并根据获取到的等级进行相应的处理。 -## 基本概念 -在进行依赖验签组件的应用开发前,开发者应了解以下基本概念: - -- Samgr - - Samgr\(System Ability Manager\)系统能力管理,在OpenHarmony上作为一个管理系统能力的模块,详见系统服务框架子系统。 +## 基本概念 +在进行依赖验签组件的应用开发前,开发者应了解以下基本概念: -- BMS - - BMS\(Bundle Manager Service\)包管理管理,在OpenHarmony上主要负责应用的安装、卸载和数据管理。 - +- Samgr -- 授权文件 + Samgr(System Ability Manager)系统能力管理,在OpenHarmony上作为一个管理系统能力的模块,详见系统服务框架子系统。 - 本文中的授权文件,指HarmonyAppProvision,简称profile。HarmonyAppProvision采用json文件格式进行描述。 +- BMS + BMS(Bundle Manager Service)包管理管理,在OpenHarmony上主要负责应用的安装、卸载和数据管理。 -- 调试应用 +- 授权文件 - 指开发者从应用市场申请调试证书与调试授权文件,并以此签名的hap包。 + 本文中的授权文件,指HarmonyAppProvision,简称profile。HarmonyAppProvision采用json文件格式进行描述。 +- 调试应用 -- 发布应用 + 指开发者从应用市场申请调试证书与调试授权文件,并以此签名的hap包。 - 指开发者从应用市场申请发布证书与发布授权文件,以此签名的hap包,上传至应用市场,并由应用市场正式发布的hap包。 +- 发布应用 + 指开发者从应用市场申请发布证书与发布授权文件,以此签名的hap包,上传至应用市场,并由应用市场正式发布的hap包。 -- OpenHarmony签名应用 +- OpenHarmony签名应用 - OpenHarmony开源了一个根CA的证书和密钥,以此根CA签发的签名证书和授权文件签名的应用。 + OpenHarmony开源了一个根CA的证书和密钥,以此根CA签发的签名证书和授权文件签名的应用。 -## 约束与限制 +## 约束与限制 -- 仅支持以下三类应用的验签:应用市场调试应用、应用市场发布应用、OpenHarmony签名应用。 -- 若对应用市场调试应用验签,则本机UDID需要在授权文件授权调试的UDID列表中。 +- 仅支持以下三类应用的验签:应用市场调试应用、应用市场发布应用、OpenHarmony签名应用。 +- 若对应用市场调试应用验签,则本机UDID需要在授权文件授权调试的UDID列表中。 diff --git a/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md b/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md index 37f3cdbbf7c82ceb3489f67358c7ac0f1b07e2bf..190c30f26b16d2e5c47442480003ad5e95d0002d 100644 --- a/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md +++ b/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md @@ -1,228 +1,122 @@ -# 应用权限管理开发指导 +# 应用权限管理开发指导 -- [运作机制](#section193961322175011) -- [场景介绍](#section18502174174019) -- [接口说明](#section1633115419401) -- [开发步骤](#section022611498210) -## 运作机制 +## 运作机制 由于OpenHarmony允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 -**表 1** OpenHarmony权限列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

OpenHarmony权限

-

授权方式

-

权限说明

-

ohos.permission.LISTEN_BUNDLE_CHANGE

-

system_grant(静态权限)

-

允许该应用获取应用变化消息。

-

ohos.permission.GET_BUNDLE_INFO

-

system_grant(静态权限)

-

允许该应用获取应用信息。

-

ohos.permission.INSTALL_BUNDLE

-

system_grant(静态权限)

-

允许该应用安装应用。

-

ohos.permission.CAMERA

-

user_grant(动态权限)

-

此应用可随时使用相机拍摄照片和录制视频。

-

ohos.permission.MODIFY_AUDIO_SETTINGS

-

system_grant(静态权限)

-

允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

-

ohos.permission.READ_MEDIA

-

user_grant(动态权限)

-

允许该应用读取您的视频收藏。

-

ohos.permission.MICROPHONE

-

user_grant(动态权限)

-

此应用可随时使用麦克风进行录音。

-

ohos.permission.WRITE_MEDIA

-

user_grant(动态权限)

-

允许该应用写入您的音乐收藏。

-

ohos.permission.DISTRIBUTED_DATASYNC

-

user_grant(动态权限)

-

管控分布式数据传输能力。

-

ohos.permission.DISTRIBUTED_VIRTUALDEVICE

-

user_grant(动态权限)

-

允许应用使用分布式虚拟能力

-
- ->![](../public_sys-resources/icon-note.gif) **说明:** ->静态权限:应用安装时由系统授予的权限,对应于权限敏感级别的system\_grant ->动态权限:应用在运行过程中需要用户授权的权限,对应于权限敏感级别的user\_grant - -## 场景介绍 + **表1** OpenHarmony权限列表 + +| OpenHarmony权限 | 授权方式 | 权限说明 | +| -------- | -------- | -------- | +| ohos.permission.LISTEN_BUNDLE_CHANGE | system_grant(静态权限) | 允许该应用获取应用变化消息。 | +| ohos.permission.GET_BUNDLE_INFO | system_grant(静态权限) | 允许该应用获取应用信息。 | +| ohos.permission.INSTALL_BUNDLE | system_grant(静态权限) | 允许该应用安装应用。 | +| ohos.permission.CAMERA | user_grant(动态权限) | 此应用可随时使用相机拍摄照片和录制视频。 | +| ohos.permission.MODIFY_AUDIO_SETTINGS | system_grant(静态权限) | 允许该应用修改全局音频设置,例如音量和用于输出的扬声器。 | +| ohos.permission.READ_MEDIA | user_grant(动态权限) | 允许该应用读取您的视频收藏。 | +| ohos.permission.MICROPHONE | user_grant(动态权限) | 此应用可随时使用麦克风进行录音。 | +| ohos.permission.WRITE_MEDIA | user_grant(动态权限) | 允许该应用写入您的音乐收藏。 | +| ohos.permission.DISTRIBUTED_DATASYNC | user_grant(动态权限) | 管控分布式数据传输能力。 | +| ohos.permission.DISTRIBUTED_VIRTUALDEVICE | user_grant(动态权限) | 允许应用使用分布式虚拟能力 | + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 静态权限:应用安装时由系统授予的权限,对应于权限敏感级别的system_grant。 +> +> 动态权限:应用在运行过程中需要用户授权的权限,对应于权限敏感级别的user_grant。 + + +## 场景介绍 应用权限是软件用来访问系统资源和使用系统能力的一种通行方式。在涉及用户隐私相关功能和数据的场景,例如:访问个人设备的硬件特性,如摄像头、麦克风,以及读写媒体文件等,OpenHarmony通过应用权限管理组件来保护这些数据以及能力。 在系统应用开发过程中,如果应用要使用敏感权限,开发者可以调用应用权限管理组件接口检查待访问权限是否被授权,如果未授权,操作不允许。 -## 接口说明 + +## 接口说明 应用权限管理提供的API接口,当前仅供系统应用和系统服务调用,具体API接口如下。 -**表 2** 应用权限管理API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int CheckPermission(int uid, const char *permissionName)

-

检查指定UID的应用进程是否具有访问系统服务API的权限

-

int CheckSelfPermission(const char *permissionName)

-

检查调用者是否具有访问系统服务API的权限

-

int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

-

查询应用申请的所有权限,并检查权限是否被授予

-

int GrantPermission(const char *identifier, const char *permName)

-

将指定权限授予应用程序

-

int RevokePermission(const char *identifier, const char *permName)

-

收回应用程序的指定权限

-

int GrantRuntimePermission(int uid, const char *permissionName)

-

应用运行时动态授予指定权限

-

int RevokeRuntimePermission(int uid, const char *permissionName)

-

应用运行时动态撤销指定权限

-
- -## 开发步骤 + **表2** 应用权限管理API接口功能介绍 -本部分以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 +| 接口名 | 描述 | +| -------- | -------- | +| int CheckPermission(int uid, const char \*permissionName) | 检查指定UID的应用进程是否具有访问系统服务API的权限 | +| int CheckSelfPermission(const char \*permissionName) | 检查调用者是否具有访问系统服务API的权限 | +| int QueryPermission(const char \*identifier, PermissionSaved \*\*permissions, int \*permNum) | 查询应用申请的所有权限,并检查权限是否被授予 | +| int GrantPermission(const char \*identifier, const char \*permName) | 将指定权限授予应用程序 | +| int RevokePermission(const char \*identifier, const char \*permName) | 收回应用程序的指定权限 | +| int GrantRuntimePermission(int uid, const char \*permissionName) | 应用运行时动态授予指定权限 | +| int RevokeRuntimePermission(int uid, const char \*permissionName) | 应用运行时动态撤销指定权限 | -1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL\_BUNDLE),并在config.json中声明该权限; - - ``` - { - ... - "module": { - "package": "com.huawei.kitframework", - "deviceType": [ - "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" - ], - "reqPermissions": [{ - // 声明需要的权限:安装应用程序的权限名 - "name": "ohos.permission.INSTALL_BUNDLE", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - }, - { - "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - }, - { - "name": "ohos.permission.GET_BUNDLE_INFO", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - } - ], - ... - } - ``` - -2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL\_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; - - ``` - constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; - - bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) - { - if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { - HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); - return false; - } - // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 - if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { - HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); - return false; // 返回安装失败 - } - // 安装流程 - ... - } - ``` +## 开发步骤 + +本部分以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 +1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL_BUNDLE),并在config.json中声明该权限; + + ``` + { + ... + "module": { + "package": "com.example.kitframework", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" + ], + "reqPermissions": [{ + // 声明需要的权限:安装应用程序的权限名 + "name": "ohos.permission.INSTALL_BUNDLE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + } + ], + ... + } + ``` + +2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; + + ``` + constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; + + bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) + { + if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); + return false; + } + // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 + if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); + return false; // 返回安装失败 + } + // 安装流程 + ... + } + ``` diff --git a/zh-cn/device-dev/subsystems/subsys-security-sigverify.md b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md index b1a14628ca79609c129d807ba52adbecfd12a9f1..b6d5cae1b9548e9c71d47c1fd46ba51cb575fe6a 100644 --- a/zh-cn/device-dev/subsystems/subsys-security-sigverify.md +++ b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md @@ -1,29 +1,24 @@ -# 应用验签开发指导 +# 应用验签开发指导 -- [场景介绍](#section18502174174019) -- [验签流程](#section554632717226) -- [接口说明](#section1633115419401) -- [开发步骤](#section4207112818418) - - [生成OpenHarmony签名应用](#section167151429133312) - -## 场景介绍 +## 场景介绍 为了确保应用的完整性和来源可靠,OpenHarmony需要对应用进行签名和验签。 -- 应用开发阶段:开发者完成开发并生成安装包后,需要开发者对安装包进行签名,以证明安装包发布到设备的过程中没有被篡改。OpenHarmony的应用完整性校验模块提供了签名工具、签名证书生成规范,以及签名所需的公钥证书等完整的机制,支撑开发者对应用安装包签名。为了方便开源社区开发者,版本中预置了公钥证书和对应的私钥,为开源社区提供离线签名和校验能力;在OpenHarmony商用版本中应替换此公钥证书和对应的私钥。 -- 应用安装阶段:OpenHarmony用户程序框架子系统负责应用的安装。在接收到应用安装包之后,应用程序框架子系统需要解析安装包的签名数据,然后使用应用完整性校验模块的API对签名进行验证,只有校验成功之后才允许安装此应用. 应用完整性校验模块在校验安装包签名数据时,会使用系统预置的公钥证书进行验签。 +- 应用开发阶段:开发者完成开发并生成安装包后,需要开发者对安装包进行签名,以证明安装包发布到设备的过程中没有被篡改。OpenHarmony的应用完整性校验模块提供了签名工具、签名证书生成规范,以及签名所需的公钥证书等完整的机制,支撑开发者对应用安装包签名。为了方便开源社区开发者,版本中预置了公钥证书和对应的私钥,为开源社区提供离线签名和校验能力;在OpenHarmony商用版本中应替换此公钥证书和对应的私钥。 -## 验签流程 +- 应用安装阶段:OpenHarmony用户程序框架子系统负责应用的安装。在接收到应用安装包之后,应用程序框架子系统需要解析安装包的签名数据,然后使用应用完整性校验模块的API对签名进行验证,只有校验成功之后才允许安装此应用. 应用完整性校验模块在校验安装包签名数据时,会使用系统预置的公钥证书进行验签。 -未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。 -经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由整包签名数据块(data sign block)、授权文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。 +## 验签流程 -**图 1** 经过签名的Hap包结构 +未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。 +经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由整包签名数据块(data sign block)、授权文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。 -![](figure/zh-cn_image_0000001181934155.png) + **图1** 经过签名的Hap包结构 + +![zh-cn_image_0000001217526184](figures/zh-cn_image_0000001217526184.png) 整个验签流程,主要分为三部分:整包验签、授权文件验签,以及授权文件内容校验。 @@ -33,64 +28,35 @@ **授权文件验签** -授权文件数据块是一个PKCS7格式的签名块(signed data),其中PKCS7签名块的内容信息\(contentinfo\)是授权文件的内容。验签过程包括:PKCS7签名验证、哈希比较、证书链验证以及签发授权文件证书的合法性校验。 +授权文件数据块是一个PKCS7格式的签名块(signed data),其中PKCS7签名块的内容信息(contentinfo)是授权文件的内容。验签过程包括:PKCS7签名验证、哈希比较、证书链验证以及签发授权文件证书的合法性校验。 **授权文件内容校验** 验签模块将对授权文件内容进行合法性检查。如果授权文件是调试类型,则会比对本机UDID是否在授权文件授权调试的UDID列表中,如果本机UDID在授权文件授权调试的UDID列表中,则会进一步比较授权文件中的调试证书和整包签名使用的证书是否相同,如果相同,则验证通过。 -## 接口说明 + +## 接口说明 验签组件当前提供innerkits接口,仅供系统应用调用,相关接口及功能描述如下: -**表 1** 轻量级系统验签组件API接口功能介绍 - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst)

-

主入口函数,输入文件路径,进行验签,并将从描述文件中获取的数据通过verifyRst返回给调用者

-

int APPVERI_SetDebugMode(bool mode)

-

设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。

-

注:当前没有基于现有测试根密钥的证书,开发者可根据自身需要,替换测试根密钥并进行相关验证。

-

void APPVERI_FreeVerifyRst(VerifyResult *verifyRst)

-

释放verifyRst中申请的内存

-
- -**表 2** 标准系统验签组件API接口功能介绍 - - - - - - - - - - -

接口名

-

描述

-

nt HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult)

-

校验应用完整性,识别应用来源。

-
- -## 开发步骤 - -### 生成OpenHarmony签名应用 - -参考文档:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/configuring-openharmony-app-signature.md + **表1** 轻量级系统验签组件API接口功能介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| int APPVERI_AppVerify(const char \*filePath, VerifyResult \*verifyRst) | 主入口函数,输入文件路径,进行验签,并将从描述文件中获取的数据通过verifyRst返回给调用者 | +| int APPVERI_SetDebugMode(bool mode) | 设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。
注:当前没有基于现有测试根密钥的证书,开发者可根据自身需要,替换测试根密钥并进行相关验证。 | +| void APPVERI_FreeVerifyRst(VerifyResult \*verifyRst) | 释放verifyRst中申请的内存 | + + **表2** 标准系统验签组件API接口功能介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| int HapVerify(const std::string& filePath, HapVerifyResult& hapVerifyResult) | 校验应用完整性,识别应用来源。 | + + +## 开发步骤 + + +### 生成OpenHarmony签名应用 +具体操作请参考:[配置OpenHarmony应用签名信息](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/configuring-openharmony-app-signature.md)。 diff --git a/zh-cn/device-dev/subsystems/subsys-security.md b/zh-cn/device-dev/subsystems/subsys-security.md index a2c018eab762142add25b25ff8f15564d8bb5e1a..cb053bdc38a9cb7ff41a6414dd903e021e8ef248 100644 --- a/zh-cn/device-dev/subsystems/subsys-security.md +++ b/zh-cn/device-dev/subsystems/subsys-security.md @@ -1,12 +1,13 @@ -# 安全 +# 安全 -- **[概述](subsys-security-overview.md)** -- **[应用验签开发指导](subsys-security-sigverify.md)** -- **[应用权限管理开发指导](subsys-security-rightmanagement.md)** +- **[概述](subsys-security-overview.md)** -- **[IPC通信鉴权开发指导](subsys-security-communicationverify.md)** +- **[应用验签开发指导](subsys-security-sigverify.md)** -- **[设备安全等级管理开发指导](subsys-security-devicesecuritylevel.md)** +- **[应用权限管理开发指导](subsys-security-rightmanagement.md)** +- **[IPC通信鉴权开发指导](subsys-security-communicationverify.md)** + +- **[设备安全等级管理开发指南](subsys-security-dslm.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-sensor-demo.md b/zh-cn/device-dev/subsystems/subsys-sensor-demo.md index 131a4b36ff7fab61de9d5016d60f3dcfebffe50d..cf17f609a380b20076ca8bf347df30edc88a5dc1 100755 --- a/zh-cn/device-dev/subsystems/subsys-sensor-demo.md +++ b/zh-cn/device-dev/subsystems/subsys-sensor-demo.md @@ -1,7 +1,8 @@ -# Sensor服务子系使用实例 +# Sensor服务使用实例 -使用实例以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 + 使用实例以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 + ``` #include "sensor_agent.h" #include "sensor_agent_type.h" @@ -58,4 +59,3 @@ static int32_t TestSensorService(void) } } ``` - diff --git a/zh-cn/device-dev/subsystems/subsys-sensor-guide.md b/zh-cn/device-dev/subsystems/subsys-sensor-guide.md index 1f6be37011d5765f1c6e41aa15e1fe0f358c4987..06ee76e24d6ecd4ee34dad27cabc9aee902dce26 100644 --- a/zh-cn/device-dev/subsystems/subsys-sensor-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-sensor-guide.md @@ -1,72 +1,86 @@ -# Sensor服务子系使用指导 +# Sensor服务使用指导 -- [使用步骤](#section18816105182315) 下面使用步骤以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 -## 使用步骤 -1. 导入需要的包 +## 使用步骤 - ``` - #include "sensor_agent.h" - #include "sensor_agent_type.h" - ``` +1. 导入需要的包 -2. 创建传感器回调函数 - - ``` - void SensorDataCallbackImpl(SensorEvent *event) - { - if(event == NULL){ - return; - } - float *sensorData=(float *)event->data; - } - ``` + +``` +#include "sensor_agent.h" +#include "sensor_agent_type.h" +``` ->![](../public_sys-resources/icon-note.gif) **说明:** ->回调函数的格式为RecordSensorCallback类型。 +2. 创建传感器回调函数 -3. 获取设备支持sensor列表 - ``` - SensorInfo *sensorInfo = (SensorInfo *)NULL; - int32_t count = 0; - int32_t ret = GetAllSensors(&sensorInfo, &count); - ``` -4. 创建的传感器用户 +``` +void SensorDataCallbackImpl(SensorEvent *event) +{ + if(event == NULL){ + return; + } + float *sensorData=(float *)event->data; +} +``` - ``` - SensorUser sensorUser; - sensorUser.callback = SensorDataCallbackImpl; //成员变量callback指向创建的回调方法 - ``` +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 回调函数的格式为RecordSensorCallback类型。 -5. 使能传感器 +3. 获取设备支持sensor列表 - ``` - int32_t ret = ActivateSensor(0, &sensorUser); - ``` -6. 订阅传感器数据 - ``` - int32_t ret = SubscribeSensor(0, &sensorUser); - ``` +``` +SensorInfo *sensorInfo = (SensorInfo *)NULL; +int32_t count = 0; +int32_t ret = GetAllSensors(&sensorInfo, &count); +``` ->![](../public_sys-resources/icon-note.gif) **说明:** ->到这步就可以在实现的回调方法中获取到传感器数据。 +4. 创建的传感器用户 -7. 取消传感器数据订阅 - ``` - int32_t ret = UnsubscribeSensor(0, &sensorUser); - ``` -8. 去使能一个传感器 +``` +SensorUser sensorUser; +sensorUser.callback = SensorDataCallbackImpl; //成员变量callback指向创建的回调方法 +``` - ``` - int32_t ret = DeactivateSensor(0, &sensorUser); - ``` +5. 使能传感器 + + +``` +int32_t ret = ActivateSensor(0, &sensorUser); +``` + +6. 订阅传感器数据 + + + +``` +int32_t ret = SubscribeSensor(0, &sensorUser); +``` + +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 到这步就可以在实现的回调方法中获取到传感器数据。 + +7. 取消传感器数据订阅 + + + +``` +int32_t ret = UnsubscribeSensor(0, &sensorUser); +``` + +8. 去使能一个传感器 + + + +``` +int32_t ret = DeactivateSensor(0, &sensorUser); +``` diff --git a/zh-cn/device-dev/subsystems/subsys-sensor-overview.md b/zh-cn/device-dev/subsystems/subsys-sensor-overview.md index caee5f57cad7a17eef842b59aba1eec3de56a1a0..65aeaffcdfa5955c364608645df0e0aa7f9f33cf 100644 --- a/zh-cn/device-dev/subsystems/subsys-sensor-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-sensor-overview.md @@ -1,99 +1,30 @@ -# Sensor服务子系概述 +# Sensor服务概述 -- [简介](#section667413271505) -- [接口说明](#section7255104114110) -## 简介 +## 简介 Sensor服务子系统提供了轻量级传感器服务基础框架,您可以使用该框架接口实现传感器列表查询、传感器控制、传感器订阅去订阅等功能。轻量级传感器服务框架如下图所示: -**图1** Sensor服务框架图 + **图1** Sensor服务框架图 + ![zh-cn_image_0000001200229829](figures/zh-cn_image_0000001200229829.png) -![](figure/zh-cn_image_0000001077724150.png) +- Sensor API:提供传感器的基础API,主要包含查询传感器的列表、订阅/取消传感器数据、执行控制命令等,简化应用开发。 -- Sensor API:提供传感器的基础API,主要包含查询传感器的列表、订阅/取消传感器数据、执行控制命令等,简化应用开发。 -- Sensor Framework:主要实现传感器的订阅管理、数据通道的创建、销毁等,实现与传感器服务层的通信。 -- Sensor Service:主要实现HDF层数据接收、解析、分发,对设备传感器的管理,数据上报管理以及传感器权限管控等。 +- Sensor Framework:主要实现传感器的订阅管理、数据通道的创建、销毁等,实现与传感器服务层的通信。 -## 接口说明 +- Sensor Service:主要实现HDF层数据接收、解析、分发,对设备传感器的管理,数据上报管理以及传感器权限管控等。 -**表 1** Sensor服务框架API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

接口说明

-

参数要求

-

int32_t GetAllSensors(SensorInfo **sensorInfo, int32_t *count)

-

作用:获取系统中所有传感器的信息。

-

返回值:0表示成功,其他返回值表示失败。

-

sensorInfo(NOT NULL):输出系统中所有传感器的信息;

-

count(NOT NULL):输出系统中所有传感器的数量。

-

int32_t SubscribeSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:订阅传感器数据,系统会将获取到的传感器数据上报给订阅者。

-

返回值: 0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t UnsubscribeSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:去订阅传感器数据,系统将取消传感器数据上报给订阅者。

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t SetBatch(int32_t sensorTypeId, SensorUser *user, int64_t samplingInterval, int64_t reportInterval)

-

作用:设置传感器的数据采样间隔和数据上报间隔

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

-

samplingInterval:传感器数据采样间隔,单位纳秒;

-

reportInterval:传感器数据上报间隔,单位纳秒。

-

int32_t ActivateSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:使能一个传感器订阅用户。

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t DeactivateSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:去使能一个传感器订阅用户

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

-

作用:设置传感器的工作模式

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

-

mode:传感器的数据上报模式。

-
+## 接口说明 + **表1** Sensor服务框架API接口功能介绍 + +| 接口名 | 接口说明 | 参数要求 | +| -------- | -------- | -------- | +| int32_t **GetAllSensors**(
SensorInfo \*\*sensorIn
fo, int32_t \*count) | **作用**:获取系统中所有传感器的信息。
**返回值**:0表示成功,其他返回值表示失败。 | **sensorInfo**(NOT NULL):输出系统中所有传感器的信息;
**count**(NOT NULL):输出系统中所有传感器的数量。 | +| int32_t **SubscribeSensor**
(int32_t sensorTypeId,
 SensorUser \*user) | **作用**:订阅传感器数据,系统会将获取到的传感器数据上报给订阅者。
**返回值**: 0为成功,其他返回值表示失败。 | **sensorTypeId**:唯一标识一个传感器类型;
**user**(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。 | +| int32_t **UnsubscribeSensor**
(int32_t sensorTypeId, SensorUser \*user) | **作用**:去订阅传感器数据,系统将取消传感器数据上报给订阅者。
**返回值**:0为成功,其他返回值表示失败。 | **sensorTypeId**:唯一标识一个传感器类型;
**user**(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。 | +| int32_t **SetBatch**(int32_t sensorTypeId, SensorUser
 \*user, int64_t samplingInterval, int64_t reportInterval) | **作用**:设置传感器的数据采样间隔和数据上报间隔
**返回值**:0为成功,其他返回值表示失败。 | **sensorTypeId**:唯一标识一个传感器类型;
**user**(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;
**samplingInterval**:传感器数据采样间隔,单位纳秒;
**reportInterval**:传感器数据上报间隔,单位纳秒。 | +| int32_t **ActivateSensor**(int32_t sensorTypeId,
 SensorUser \*user) | **作用**:使能一个传感器订阅用户。
**返回值**:0为成功,其他返回值表示失败。 | **sensorTypeId**:唯一标识一个传感器类型;
**user**(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。 | +| int32_t **DeactivateSensor**(int32_t sensor
TypeId, SensorUser \*user) | **作用**:去使能一个传感器订阅用户
**返回值**:0为成功,其他返回值表示失败。 | **sensorTypeId**:唯一标识一个传感器类型;
**user**(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。 | +| int32_t **SetMode**(int32_t sensorTypeId,
 SensorUser \*user, int32_t mode) | **作用**:设置传感器的工作模式
**返回值**:0为成功,其他返回值表示失败。 | **sensorTypeId**:唯一标识一个传感器类型;
**user**(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;
**mode**:传感器的数据上报模式。 | diff --git a/zh-cn/device-dev/subsystems/subsys-tel-guide.md b/zh-cn/device-dev/subsystems/subsys-tel-guide.md index 5718a31637056a193ee208b2d2ac9b7a0c4f36d0..d2ba054b190aa0a87dbc640156ba75df67a26a11 100644 --- a/zh-cn/device-dev/subsystems/subsys-tel-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-tel-guide.md @@ -1,583 +1,519 @@ -# 电话服务开发指导 +# 电话服务开发指导 -- [Modem厂商库初始化开发指导](#section211mcpsimp) - - [场景介绍](#section213mcpsimp) - - [接口说明](#section811343241215) - - [开发步骤](#section51031144122) - - [调测验证](#section5351151517132) -- [Modem业务请求及响应开发指导](#section295mcpsimp) - - [场景介绍](#section297mcpsimp) - - [接口说明](#section9503155219134) - - [开发步骤](#section17190412101414) - - [调测验证](#section10207938171413) +## Modem厂商库初始化开发指导 -- [Modem事件上报开发指导](#section390mcpsimp) - - [场景介绍](#section401mcpsimp) - - [接口说明](#section191193791518) - - [开发步骤](#section16394112401512) - - [调测验证](#section16999174401516) - - [开发实例](#section33444350167) -- [Modem厂商库集成指导](#section590mcpsimp) - - [编译设置](#section592mcpsimp) - - [调测验证](#section620mcpsimp) +### 场景介绍 +Modem厂商库初始化是指在厂商库里实现const HRilOps \*RilInitOps(const struct HRilReport \*reportOps)函数,在该函数里处理三个重要的功能: -## Modem厂商库初始化开发指导 +- 接收RIL Adapter事件回调的函数指针,当Modem有业务事件上报时,调用对应的函数指针,把事件上报给RIL Adapter。 -### 场景介绍 +- 创建读取Modem设备节点的线程,在该线程里会循环地读取Modem上报的事件,并把接收的Modem信息解析为具体业务相关的事件进行上报。 -Modem厂商库初始化是指在厂商库里实现const HRilOps \*RilInitOps\(const struct HRilReport \*reportOps\)函数,在该函数里处理三个重要的功能: +- 返回业务请求接口的函数指针给RIL Adapter。 -- 接收RIL Adapter事件回调的函数指针,当Modem有业务事件上报时,调用对应的函数指针,把事件上报给RIL Adapter。 -- 创建读取Modem设备节点的线程,在该线程里会循环地读取Modem上报的事件,并把接收的Modem信息解析为具体业务相关的事件进行上报。 -- 返回业务请求接口的函数指针给RIL Adapter。 -### 接口说明 +### 接口说明 Modem厂商库初始化接口。 -**表 1** Modem厂商库初始化接口功能介绍 - - - - - - - - - - -

接口名

-

描述

-

const HRilOps *RilInitOps(const struct HRilReport * reportOps)

-

接口功能:Modem厂商库运行的入口。

-

参数reportOps:RIL Adapter传入的事件回调函数指针。

-

返回值:业务请求接口的函数指针。

-
- -### 开发步骤 - -1. RilInitOps接口中设置RIL Adapter传入的事件回调函数指针。 - - ``` - // 定义Modem厂商库回调函数指针 - static struct HRilReport g_reportOps = { - OnCallReport, // 通话相关业务回调函数 - OnDataReport, // 蜂窝数据相关业务回调函数 - OnModemReport, // Modem相关业务回调函数 - OnNetworkReport, // 搜网相关业务回调函数 - OnSimReport, // SIM卡相关业务回调函数 - OnSmsReport // 短信相关业务回调函数 - }; - ``` - - -1. 创建主线程g\_reader,开启消息循环。 - - ``` - pthread_attr_t t; - pthread_attr_init(&t); - pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED); - ret = pthread_create(&g_reader, &t, ReaderLoop, &t); // 创建线程 - ``` - - -1. 在g\_eventListeners线程用open\(\)打开Modem设备节点,并创建g\_reader线程循环读取处理Modem上报的消息。 - - ``` - g_fd = open(g_devicePath, O_RDWR); // 打开设备节点,入参g_devicePath是Modem设备节点 - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - ret = pthread_create(&g_eventListeners, &attr, EventListeners, NULL); - ``` - - -1. 返回业务请求接口的函数指针。 - - ``` - // call模块业务请求接口结构体 - typedef struct { - // 获取呼叫列表 - void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); - // 拨打电话 - void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); - // 挂断电话 - void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); - // 拒接来电 - void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); - // 接听来电 - void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); - } HRilCallReq; - - // call模块回调函数指针 - static const HRilCallReq g_callReqOps = { - .GetCallList = ReqGetCallList, // 获取呼叫列表接口 - .Dial = ReqDial, // 拨打电话接口 - .Hangup = ReqHangup, // 挂断电话接口 - .Reject = ReqReject, // 拒接来电接口 - .Answer = ReqAnswer, // 接听来电接口 - }; - - // 业务请求结构体 - typedef struct { - const HRilCallReq *callOps; // 通话相关业务请求结构体指针 - const HRilSimReq *simOps; // SIM卡相关业务请求结构体指针 - const HRilSmsReq *smsOps; // 短彩信相关业务请求结构体指针 - const HRilDataReq *dataOps; // 蜂窝数据相关业务请求结构体指针 - const HRilNetworkReq *networkOps; // 搜网相关业务请求结构体指针 - const HRilModemReq *modemOps; // Modem相关业务请求结构体指针 - } HRilOps; - - // 业务请求接口定义 - HRilOps g_hrilOps = { - .callOps = &g_callReqOps, // 定义通话业务请求接口 - .simOps = &g_simReqOps, // 定义SIM卡业务请求接口 - .smsOps = &g_smsReqOps, // 定义短彩信业务请求接口 - .networkOps = &g_networkReqOps, // 定义蜂窝数据业务请求接口 - .dataOps = &g_dataReqOps, // 定义搜网业务请求接口 - .modemOps = &g_modemReqOps, // 定义Modem业务请求接口 - }; - ``` + **表1** Modem厂商库初始化接口功能介绍 + +| 接口名 | 描述 | +| -------- | -------- | +| const HRilOps \*RilInitOps(const struct HRilReport \* reportOps) | 接口功能:Modem厂商库运行的入口。
参数reportOps:RIL Adapter传入的事件回调函数指针。
返回值:业务请求接口的函数指针。 | -### 调测验证 +### 开发步骤 + + +1. RilInitOps接口中设置RIL Adapter传入的事件回调函数指针。 + + ``` + // 定义Modem厂商库回调函数指针 + static struct HRilReport g_reportOps = { + OnCallReport, // 通话相关业务回调函数 + OnDataReport, // 蜂窝数据相关业务回调函数 + OnModemReport, // Modem相关业务回调函数 + OnNetworkReport, // 搜网相关业务回调函数 + OnSimReport, // SIM卡相关业务回调函数 + OnSmsReport // 短信相关业务回调函数 + }; + ``` + + +1. 创建主线程g_reader,开启消息循环。 + + ``` + pthread_attr_t t; + pthread_attr_init(&t); + pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&g_reader, &t, ReaderLoop, &t); // 创建线程 + ``` + + +1. 在g_eventListeners线程用open()打开Modem设备节点,并创建g_reader线程循环读取处理Modem上报的消息。 + + ``` + g_fd = open(g_devicePath, O_RDWR); // 打开设备节点,入参g_devicePath是Modem设备节点 + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&g_eventListeners, &attr, EventListeners, NULL); + ``` + + +1. 返回业务请求接口的函数指针。 + + ``` + // call模块业务请求接口结构体 + typedef struct { + // 获取呼叫列表 + void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); + // 拨打电话 + void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); + // 挂断电话 + void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); + // 拒接来电 + void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); + // 接听来电 + void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); + } HRilCallReq; + + // call模块回调函数指针 + static const HRilCallReq g_callReqOps = { + .GetCallList = ReqGetCallList, // 获取呼叫列表接口 + .Dial = ReqDial, // 拨打电话接口 + .Hangup = ReqHangup, // 挂断电话接口 + .Reject = ReqReject, // 拒接来电接口 + .Answer = ReqAnswer, // 接听来电接口 + }; + + // 业务请求结构体 + typedef struct { + const HRilCallReq *callOps; // 通话相关业务请求结构体指针 + const HRilSimReq *simOps; // SIM卡相关业务请求结构体指针 + const HRilSmsReq *smsOps; // 短彩信相关业务请求结构体指针 + const HRilDataReq *dataOps; // 蜂窝数据相关业务请求结构体指针 + const HRilNetworkReq *networkOps; // 搜网相关业务请求结构体指针 + const HRilModemReq *modemOps; // Modem相关业务请求结构体指针 + } HRilOps; + + // 业务请求接口定义 + HRilOps g_hrilOps = { + .callOps = &g_callReqOps, // 定义通话业务请求接口 + .simOps = &g_simReqOps, // 定义SIM卡业务请求接口 + .smsOps = &g_smsReqOps, // 定义短彩信业务请求接口 + .networkOps = &g_networkReqOps, // 定义蜂窝数据业务请求接口 + .dataOps = &g_dataReqOps, // 定义搜网业务请求接口 + .modemOps = &g_modemReqOps, // 定义Modem业务请求接口 + }; + ``` -1. 用[hdc\_std工具](subsys-toolchain-hdc-guide.md#section05992022154916)连接调试设备,把编译生成的libril\_vendor.z.so库文件(参见[Modem厂商库集成指导](#section590mcpsimp))通过以下命令推到/system/lib/目录下。 - ``` - hdc_std file send libril_vendor.z.so /system/lib/ - ``` +### 调测验证 -2. 执行hdc\_std shell sync,hdc\_std shell reboot重启设备。 +1. 用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md#环境准备)连接调试设备,把编译生成的libril_vendor.z.so库文件(参见[Modem厂商库集成指导](#modem厂商库集成指导))通过以下命令推到/system/lib/目录下。 + + ``` + hdc_std file send libril_vendor.z.so /system/lib/ + ``` - ``` - hdc_std shell sync - hdc_std shell reboot - ``` +2. 执行hdc_std shell sync,hdc_std shell reboot重启设备。 + + ``` + hdc_std shell sync + hdc_std shell reboot + ``` -3. 执行hdc\_std shell hilog,根据日志查看函数RilInitOps\(\)是否正确执行完成。如下调测验证日志供参考: +3. 执行hdc_std shell hilog,根据日志查看函数RilInitOps()是否正确执行完成。如下调测验证日志供参考: + + ``` + 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [RilAdapterDispatch-(hril_hdf.c:55)] sbuf IPC obtain test success! + 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [LoadVendor-(hril_hdf.c:33)] RilInit rilInit start + 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [LoadVendor -(hril_hdf.c:45)] RilInit rilInit completed + ``` - ``` - 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [RilAdapterDispatch-(hril_hdf.c:55)] sbuf IPC obtain test success! - 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [LoadVendor-(hril_hdf.c:33)] RilInit rilInit start - 01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [LoadVendor -(hril_hdf.c:45)] RilInit rilInit completed - ``` +## Modem业务请求及响应开发指导 -## Modem业务请求及响应开发指导 -### 场景介绍 +### 场景介绍 Modem业务请求及响应是指RIL Adapter收到电话服务具体业务请求后,调用Modem厂商库初始化获得的函数指针,把具体业务请求发送给厂商库,厂商库根据业务请求ID做相应的业务处理。 -### 接口说明 + +### 接口说明 Modem业务请求及响应接口。 -**表 2** Modem业务请求及响应接口功能介绍(以拨号功能模块为例) - - - - - - - - - - - - - -

接口名

-

描述

-

void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen);

-

接口功能:对拨号请求进行处理。

-

参数requestInfo:请求类型信息。

-

参数data:被叫号码信息。

-

参数dataLen:数据长度。

-

返回值:无。

-

void (*OnCallReport)(struct ReportInfo reportInfo, const void *data, size_t dataLen);

-

接口功能:对通话业务执行结果进行响应,即当请求业务执行完成后,Modem将该请求执行的结果上报给RIL Adapter。

-

参数reportInfo:返回类型信息。

-

参数data:返回数据。

-

参数dataLen:数据长度。

-

返回值:无。

-
- -### 开发步骤 - -1. 在ReqDial\(\)接口中对拨号请求进行处理。 - - ``` - // 拨号请求接口实现 - void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen) - { - HRilDial *pDial = NULL; - char cmd[MAX_BUFF_SIZE] = {0}; - const char *clir = NULL; - int ret; - int err = HRIL_ERR_SUCCESS; - struct ReportInfo reportInfo = {}; - ResponseInfo *pResponse = NULL; - if (data == NULL) { - TELEPHONY_LOGE("data is null!!!"); - err = HRIL_ERR_INVALID_PARAMETER; - reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); - OnCallReport(reportInfo, NULL, 0); - return; - } - pDial = (HRilDial *)data; - switch (pDial->clir) { - case CALL_CLIR_INVOCATION: - clir = "I"; - break; /* invocation */ - case CALL_CLIR_SUPPRESSION: - clir = "i"; - break; /* suppression */ - case CALL_CLIR_SUBSCRIPTION_DEFUALT: - default: - clir = ""; - break; /* subscription default */ - } - (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir); - ret = SendCommandLock(cmd, NULL, 0, &pResponse); // 发送AT指令 - ...... - } - ``` - -2. 在Modem执行完拨号命令后,调用OnCallReport\(\)回调函数,把该请求执行的结果上报给RIL Adapter。 - - ``` - ret = SendCommandLock(cmd, NULL, 0, &pResponse); - if (ret != 0 || (pResponse != NULL && pResponse->success == 0)) { - TELEPHONY_LOGE("ATD send failed"); - err = HRIL_ERR_GENERIC_FAILURE; - } - reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); - OnCallReport(reportInfo, NULL, 0); // 调用通话相关回调函数 - ``` - - -### 调测验证 - -1. 用[hdc\_std工具](subsys-toolchain-hdc-guide.md#section05992022154916)工具连接调试设备,把编译生成的libril\_vendor.z.so库文件通过以下命令推到/system/lib/目录下。 - - ``` - hdc_std file send libril_vendor.z.so /system/lib/ - ``` - -2. 执行hdc\_std shell sync,hdc\_std shell reboot重启设备。 - - ``` - hdc_std shell sync - hdc_std shell reboot - ``` - -3. hdc\_std shell后执行./system/bin/ril\_adapter\_test,输入编号1,根据提示输入电话号码,测试拨打电话功能。 - - ``` - hdc_std shell - # ./system/bin/ril_adapter_test - ----> Test Enter --------->Call--------------------- + **表2** Modem业务请求及响应接口功能介绍(以拨号功能模块为例) + +| 接口名 | 描述 | +| -------- | -------- | +| void ReqDial(ReqDataInfo \*requestInfo, const void \*data, size_t dataLen); | 接口功能:对拨号请求进行处理。
参数requestInfo:请求类型信息。
参数data:被叫号码信息。
参数dataLen:数据长度。
返回值:无。 | +| void (\*OnCallReport)(struct ReportInfo reportInfo, const void \*data, size_t dataLen); | 接口功能:对通话业务执行结果进行响应,即当请求业务执行完成后,Modem将该请求执行的结果上报给RIL Adapter。
参数reportInfo:返回类型信息。
参数data:返回数据。
参数dataLen:数据长度。
返回值:无。 | + + +### 开发步骤 + +1. 在ReqDial()接口中对拨号请求进行处理。 + + ``` + // 拨号请求接口实现 + void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen) + { + HRilDial *pDial = NULL; + char cmd[MAX_BUFF_SIZE] = {0}; + const char *clir = NULL; + int ret; + int err = HRIL_ERR_SUCCESS; + struct ReportInfo reportInfo = {}; + ResponseInfo *pResponse = NULL; + if (data == NULL) { + TELEPHONY_LOGE("data is null!!!"); + err = HRIL_ERR_INVALID_PARAMETER; + reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); + OnCallReport(reportInfo, NULL, 0); + return; + } + pDial = (HRilDial *)data; + switch (pDial->clir) { + case CALL_CLIR_INVOCATION: + clir = "I"; + break; /* invocation */ + case CALL_CLIR_SUPPRESSION: + clir = "i"; + break; /* suppression */ + case CALL_CLIR_SUBSCRIPTION_DEFUALT: + default: + clir = ""; + break; /* subscription default */ + } + (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir); + ret = SendCommandLock(cmd, NULL, 0, &pResponse); // 发送AT指令 + ...... + } + ``` + +2. 在Modem执行完拨号命令后,调用OnCallReport()回调函数,把该请求执行的结果上报给RIL Adapter。 + + ``` + ret = SendCommandLock(cmd, NULL, 0, &pResponse); + if (ret != 0 || (pResponse != NULL && pResponse->success == 0)) { + TELEPHONY_LOGE("ATD send failed"); + err = HRIL_ERR_GENERIC_FAILURE; + } + reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); + OnCallReport(reportInfo, NULL, 0); // 调用通话相关回调函数 + ``` + + +### 调测验证 + +1. 用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md#环境准备)工具连接调试设备,把编译生成的libril_vendor.z.so库文件通过以下命令推到/system/lib/目录下。 + + ``` + hdc_std file send libril_vendor.z.so /system/lib/ + ``` + +2. 执行hdc_std shell sync,hdc_std shell reboot重启设备。 - 1----> RilUnitTest::OnRequestCallDialTest - 2----> RilUnitTest:: OnRequestCallHangupTest - 3----> RilUnitTest:: OnRequestCallAnswerTest - 4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest - 5----> RilUnitTest::OnRequestRefusedCallTest - - 1 - ``` - -4. 另开一个终端窗口,执行hdc\_std shell hilog,通过日志查看函数ReqDial\(\)是否正确执行完成。如下调测验证日志供参考: - - ``` - 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:210)] SendCommandLock enter, cmd: ATD17620373527 - 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:231)] SendCommandLock() command ATD17620373527 - 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [WriteATCommand-(channel.c:115)] WriteATCommand enter, cmd:ATD17620373527 - 01-01 05:27:27.421 136 187 D 02b01/Rilvendor: [ReadResponse-(channel.c:94)] g_bufferCur : - 01-01 05:27:27.421 136 187 D 02b01/Rilvendor: OK - 01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:144)] processLine line = OK - 01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ReadResponse-(channel.c:81)] ReadResponse enter - 01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur: - 01-01 05:27:27.422 136 187 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null - 01-01 05:27:27.422 136 187 E 02b01/Rilvendor:^ORIG:1,0 - 01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:234)] processLine line = ^ORIG:1,0 - 01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(vendor_report.c:234)] enter to [^ORIG:1,0]:(null) - 01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:264)] err = 0, cmd:ADT17620373527 - ``` - - -## Modem事件上报开发指导 - -### 场景介绍 + ``` + hdc_std shell sync + hdc_std shell reboot + ``` + +3. hdc_std shell后执行./system/bin/ril_adapter_test,输入编号1,根据提示输入电话号码,测试拨打电话功能。 + + ``` + hdc_std shell + # ./system/bin/ril_adapter_test + ----> Test Enter --------->Call--------------------- + + 1----> RilUnitTest::OnRequestCallDialTest + 2----> RilUnitTest:: OnRequestCallHangupTest + 3----> RilUnitTest:: OnRequestCallAnswerTest + 4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest + 5----> RilUnitTest::OnRequestRefusedCallTest + + 1 + ``` + +4. 另开一个终端窗口,执行hdc_std shell hilog,通过日志查看函数ReqDial()是否正确执行完成。如下调测验证日志供参考: + + ``` + 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:210)] SendCommandLock enter, cmd: ATD17620373527 + 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:231)] SendCommandLock() command ATD17620373527 + 01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [WriteATCommand-(channel.c:115)] WriteATCommand enter, cmd:ATD17620373527 + 01-01 05:27:27.421 136 187 D 02b01/Rilvendor: [ReadResponse-(channel.c:94)] g_bufferCur : + 01-01 05:27:27.421 136 187 D 02b01/Rilvendor: OK + 01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:144)] processLine line = OK + 01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ReadResponse-(channel.c:81)] ReadResponse enter + 01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur: + 01-01 05:27:27.422 136 187 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null + 01-01 05:27:27.422 136 187 E 02b01/Rilvendor:^ORIG:1,0 + 01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:234)] processLine line = ^ORIG:1,0 + 01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(vendor_report.c:234)] enter to [^ORIG:1,0]:(null) + 01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:264)] err = 0, cmd:ADT17620373527 + ``` + + +## Modem事件上报开发指导 + + +### 场景介绍 Modem事件上报是指在厂商库的Modem设备节点读取线程,循环读取到Modem主动上报的消息后,对Modem上报事件进行解析,然后上报给RIL Adapter。 -### 接口说明 + +### 接口说明 Modem事件上报接口。 -**表 3** Modem事件上报接口功能介绍 - - - - - - - - - - -

接口名

-

描述

-

void OnNotifyOps(const char *s, const char *smsPdu)

-

接口功能:对Modem上报的事件进行分发处理。

-

参数s:AT指令前缀。

-

参数smsPdu:短信PDU信息。

-

返回值:无。

-
- -### 开发步骤 - -1. 在Modem设备节点读取线程g\_reader里调用OnNotifyOps\(\)解析具体的Modem上报事件,判断命令类型,并调用OnXxxReport\(\)把解析得到的各模块事件上报给hril业务层。 - - ``` - // 将Modem上报数据解析为对应模块的主动上报事件 - void OnNotifyOps(const char *s, const char *smsPdu) - { - int ret = 0; - struct ReportInfo reportInfo = {0}; - reportInfo.error = HRIL_ERR_SUCCESS; - reportInfo.type = HRIL_NOTIFICATION; - if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) { - return; - } - TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu); - // 通过AT指令判断主动上报命令类型 - if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") || - ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") || - ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) { - reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED; - OnCallReport(reportInfo, NULL, 0); - } else if (ReportStrWith(s, "+CMT:")) { - reportInfo.notifyId = HNOTI_SMS_NEW_SMS; - OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu)); - } - // 将各模块事件上报给hril业务层 - ...... - } - ``` - - -1. hril业务层将上报事件分发给Telephony Service。 - - ``` - // 呼叫状态主动上报 - int32_t HRilCall::CallStateUpdated( - int32_t slotId, int32_t notifyType, const HRilErrno e, const void *response, size_t responseLen) - { - struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC); - if (serviceCallbackNotify_ == nullptr) { - TELEPHONY_LOGE("RilAdapter serviceCallbackNotify_ is null"); - HdfSBufRecycle(dataSbuf); - return HDF_FAILURE; - } - // 分发处理 - int32_t ret = serviceCallbackNotify_->dispatcher->Dispatch( - serviceCallbackNotify_, HNOTI_CALL_STATE_UPDATED, dataSbuf, nullptr); - if (ret != HDF_SUCCESS) { - HdfSBufRecycle(dataSbuf); - return HDF_FAILURE; - } - HdfSBufRecycle(dataSbuf); - return HDF_SUCCESS; - } - ``` - - -### 调测验证 - -1. 用[hdc\_std工具](subsys-toolchain-hdc-guide.md#section05992022154916)工具连接调试设备,把编译生成的libril\_vendor.z.so库文件通过以下命令推到/system/lib/目录下。 - - ``` - hdc_std file send libril_vendor.z.so /system/lib/ - ``` - -2. 执行hdc\_std shell sync,hdc\_std shell reboot重启设备。 - - ``` - hdc_std shell sync - hdc_std shell reboot - ``` - -3. hdc\_std shell后执行./system/bin/ril\_adapter\_test,输入编号1,根据提示输入电话号码,测试拨打电话功能。 - - ``` - hdc_std shell - # ./system/bin/ril_adapter_test - ----> Test Enter --------->Call--------------------- - - 1----> RilUnitTest::OnRequestCallDialTest - 2----> RilUnitTest:: OnRequestCallHangupTest - 3----> RilUnitTest:: OnRequestCallAnswerTest - 4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest - 5----> RilUnitTest::OnRequestRefusedCallTest - - 1 - ``` - -4. 另开一个终端窗口,执行hdc\_std shell hilog,通过日志查看函数OnNotifyOps\(\)是否正确执行完成。如下调测验证日志供参考: - - ``` - 01-01 00:08:01.334 546 551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0 - 01-01 00:08:01.334 546 557 D 02b01/TelRilTest: [ProcessEvent-(tel_ril_test.cpp:1262)] TelRilTest::DemoHandler::ProcessEvent --> eventId:101 - 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur : - 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: ^ORIG:1,0 - 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^ORIG:1,0 - 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^ORIG:1,0 - 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^ORIG:1,0]:(null) - 01-01 00:08:01.335 143 512 W 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:167)] enter to is unrecognized command: ^ORIG:1,0 - 01-01 00:08:01.335 143 512 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur: - 01-01 00:08:01.335 143 512 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null - 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur : - 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: ^CCALLSTATE: 1,0,1 - 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^CCALLSTATE: 1,0,1 - 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^CCALLSTATE: 1,0,1 - 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^CCALLSTATE: 1,0,1]:(null) - 01-01 00:08:01.336 546 551 D 02b01/CoreService: [OnRemoteRequest-(tel_ril_manager.cpp:80)] RilManager OnRemoteRequest code:1001 - 01-01 00:08:01.336 546 551 D 02b01/CoreService: [NotifyObserver-(observer_handler.cpp:76)] handler->SendEvent:8 - ``` - - -### 开发实例 - -- **去电开发实例** + **表3** Modem事件上报接口功能介绍 - 去电的调用流程示例如下图所示: +| 接口名 | 描述 | +| -------- | -------- | +| void OnNotifyOps(const char \*s, const char \*smsPdu) | 接口功能:对Modem上报的事件进行分发处理。
参数s:AT指令前缀。
参数smsPdu:短信PDU信息。
返回值:无。 | - **图 1** 去电调用时序图 - ![](figure/去电调用时序图.png "去电调用时序图") - 当应用触发去电动作时,RIL Adapter会接收到拨打电话的请求,hril调用对应的拨打电话的接口ReqDial\(\)。在该接口里会把电话服务传过来的数据封装为对应的AT指令发送到Modem,Modem执行完拨号命令后通过OnCallReport\(\)接口把响应结果上报给RIL Adapter。 +### 开发步骤 - ``` - // call模块回调函数指针 - static const HRilCallReq g_callReqOps = { - .GetCallList = ReqGetCallList, // 获取呼叫列表接口 - .Dial = ReqDial, // 拨打电话接口 - .Hangup = ReqHangup, // 挂断电话接口 - .Reject = ReqReject, // 拒接来电接口 - .Answer = ReqAnswer, // 接听来电接口 - }; - - // 系统业务请求接口定义 - HRilOps g_hrilOps = { - .callOps = &g_callReqOps, // 定义通话业务请求接口 - .simOps = &g_simReqOps, // 定义SIM卡业务请求接口 - .smsOps = &g_smsReqOps, // 定义短彩信业务请求接口 - .networkOps = &g_networkReqOps, // 定义蜂窝数据业务请求接口 - .dataOps = &g_dataReqOps, // 定义搜网业务请求接口 - .modemOps = &g_modemReqOps, // 定义Modem业务请求接口 - }; +1. 在Modem设备节点读取线程g_reader里调用OnNotifyOps()解析具体的Modem上报事件,判断命令类型,并调用OnXxxReport()把解析得到的各模块事件上报给hril业务层。 + + ``` + // 将Modem上报数据解析为对应模块的主动上报事件 + void OnNotifyOps(const char *s, const char *smsPdu) + { + int ret = 0; + struct ReportInfo reportInfo = {0}; + reportInfo.error = HRIL_ERR_SUCCESS; + reportInfo.type = HRIL_NOTIFICATION; + if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) { + return; + } + TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu); + // 通过AT指令判断主动上报命令类型 + if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") || + ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") || + ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) { + reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED; + OnCallReport(reportInfo, NULL, 0); + } else if (ReportStrWith(s, "+CMT:")) { + reportInfo.notifyId = HNOTI_SMS_NEW_SMS; + OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu)); + } + // 将各模块事件上报给hril业务层 + ...... + } + ``` + +1. hril业务层将上报事件分发给Telephony Service。 + + ``` + // 呼叫状态主动上报 + int32_t HRilCall::CallStateUpdated( + int32_t slotId, int32_t notifyType, const HRilErrno e, const void *response, size_t responseLen) + { + struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC); + if (serviceCallbackNotify_ == nullptr) { + TELEPHONY_LOGE("RilAdapter serviceCallbackNotify_ is null"); + HdfSBufRecycle(dataSbuf); + return HDF_FAILURE; + } + // 分发处理 + int32_t ret = serviceCallbackNotify_->dispatcher->Dispatch( + serviceCallbackNotify_, HNOTI_CALL_STATE_UPDATED, dataSbuf, nullptr); + if (ret != HDF_SUCCESS) { + HdfSBufRecycle(dataSbuf); + return HDF_FAILURE; + } + HdfSBufRecycle(dataSbuf); + return HDF_SUCCESS; + } + ``` + + +### 调测验证 + +1. 用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md#环境准备)工具连接调试设备,把编译生成的libril_vendor.z.so库文件通过以下命令推到/system/lib/目录下。 + + ``` + hdc_std file send libril_vendor.z.so /system/lib/ + ``` + +2. 执行hdc_std shell sync,hdc_std shell reboot重启设备。 + + ``` + hdc_std shell sync + hdc_std shell reboot + ``` + +3. hdc_std shell后执行./system/bin/ril_adapter_test,输入编号1,根据提示输入电话号码,测试拨打电话功能。 + + ``` + hdc_std shell + # ./system/bin/ril_adapter_test + ----> Test Enter --------->Call--------------------- - // 拨号请求接口实现 - void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen) - { - HRilDial *pDial = NULL; - char cmd[MAX_BUFF_SIZE] = {0}; - const char *clir = NULL; - int ret; - int err = HRIL_ERR_SUCCESS; - struct ReportInfo reportInfo = {}; - ResponseInfo *pResponse = NULL; - if (data == NULL) { - TELEPHONY_LOGE("data is null!!!"); - err = HRIL_ERR_INVALID_PARAMETER; - reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); - OnCallReport(reportInfo, NULL, 0); - return; - } - pDial = (HRilDial *)data; - switch (pDial->clir) { - case CALL_CLIR_INVOCATION: - clir = "I"; - break; /* invocation */ - case CALL_CLIR_SUPPRESSION: - clir = "i"; - break; /* suppression */ - case CALL_CLIR_SUBSCRIPTION_DEFUALT: - default: - clir = ""; - break; /* subscription default */ - } - (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir); - ret = SendCommandLock(cmd, NULL, 0, &pResponse); // 发送AT命令 - if (ret != 0) { - err = HRIL_ERR_CMD_SEND_FAILURE; - TELEPHONY_LOGE("ATD send failed"); - } else { - if (pResponse != NULL && pResponse->success == 0) { - TELEPHONY_LOGE("ReqDial return ERROR"); - err = HRIL_ERR_CMD_NO_CARRIER; - } - } - reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); - OnCallReport(reportInfo, NULL, 0); // 调用通话相关业务回调函数 - FreeResponseInfo(pResponse); - } - ``` - - -- **来电开发实例** + 1----> RilUnitTest::OnRequestCallDialTest + 2----> RilUnitTest:: OnRequestCallHangupTest + 3----> RilUnitTest:: OnRequestCallAnswerTest + 4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest + 5----> RilUnitTest::OnRequestRefusedCallTest + + 1 + ``` - 来电的调用流程示例如下图所示: +4. 另开一个终端窗口,执行hdc_std shell hilog,通过日志查看函数OnNotifyOps()是否正确执行完成。如下调测验证日志供参考: + + ``` + 01-01 00:08:01.334 546 551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0 + 01-01 00:08:01.334 546 557 D 02b01/TelRilTest: [ProcessEvent-(tel_ril_test.cpp:1262)] TelRilTest::DemoHandler::ProcessEvent --> eventId:101 + 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur : + 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: ^ORIG:1,0 + 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^ORIG:1,0 + 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^ORIG:1,0 + 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^ORIG:1,0]:(null) + 01-01 00:08:01.335 143 512 W 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:167)] enter to is unrecognized command: ^ORIG:1,0 + 01-01 00:08:01.335 143 512 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur: + 01-01 00:08:01.335 143 512 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null + 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur : + 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: ^CCALLSTATE: 1,0,1 + 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^CCALLSTATE: 1,0,1 + 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^CCALLSTATE: 1,0,1 + 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^CCALLSTATE: 1,0,1]:(null) + 01-01 00:08:01.336 546 551 D 02b01/CoreService: [OnRemoteRequest-(tel_ril_manager.cpp:80)] RilManager OnRemoteRequest code:1001 + 01-01 00:08:01.336 546 551 D 02b01/CoreService: [NotifyObserver-(observer_handler.cpp:76)] handler->SendEvent:8 + ``` + + +### 开发实例 + +- **去电开发实例** + 去电的调用流程示例如下图所示: + **图1** 去电调用时序图 - **图 2** 来电调用时序图 + ![zh-cn_image_0000001171507146](figures/zh-cn_image_0000001171507146.png) + + 当应用触发去电动作时,RIL Adapter会接收到拨打电话的请求,hril调用对应的拨打电话的接口ReqDial()。在该接口里会把电话服务传过来的数据封装为对应的AT指令发送到Modem,Modem执行完拨号命令后通过OnCallReport()接口把响应结果上报给RIL Adapter。 + ``` + // call模块回调函数指针 + static const HRilCallReq g_callReqOps = { + .GetCallList = ReqGetCallList, // 获取呼叫列表接口 + .Dial = ReqDial, // 拨打电话接口 + .Hangup = ReqHangup, // 挂断电话接口 + .Reject = ReqReject, // 拒接来电接口 + .Answer = ReqAnswer, // 接听来电接口 + }; + + // 系统业务请求接口定义 + HRilOps g_hrilOps = { + .callOps = &g_callReqOps, // 定义通话业务请求接口 + .simOps = &g_simReqOps, // 定义SIM卡业务请求接口 + .smsOps = &g_smsReqOps, // 定义短彩信业务请求接口 + .networkOps = &g_networkReqOps, // 定义蜂窝数据业务请求接口 + .dataOps = &g_dataReqOps, // 定义搜网业务请求接口 + .modemOps = &g_modemReqOps, // 定义Modem业务请求接口 + }; + + // 拨号请求接口实现 + void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen) + { + HRilDial *pDial = NULL; + char cmd[MAX_BUFF_SIZE] = {0}; + const char *clir = NULL; + int ret; + int err = HRIL_ERR_SUCCESS; + struct ReportInfo reportInfo = {}; + ResponseInfo *pResponse = NULL; + if (data == NULL) { + TELEPHONY_LOGE("data is null!!!"); + err = HRIL_ERR_INVALID_PARAMETER; + reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); + OnCallReport(reportInfo, NULL, 0); + return; + } + pDial = (HRilDial *)data; + switch (pDial->clir) { + case CALL_CLIR_INVOCATION: + clir = "I"; + break; /* invocation */ + case CALL_CLIR_SUPPRESSION: + clir = "i"; + break; /* suppression */ + case CALL_CLIR_SUBSCRIPTION_DEFUALT: + default: + clir = ""; + break; /* subscription default */ + } + (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir); + ret = SendCommandLock(cmd, NULL, 0, &pResponse); // 发送AT命令 + if (ret != 0) { + err = HRIL_ERR_CMD_SEND_FAILURE; + TELEPHONY_LOGE("ATD send failed"); + } else { + if (pResponse != NULL && pResponse->success == 0) { + TELEPHONY_LOGE("ReqDial return ERROR"); + err = HRIL_ERR_CMD_NO_CARRIER; + } + } + reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); + OnCallReport(reportInfo, NULL, 0); // 调用通话相关业务回调函数 + FreeResponseInfo(pResponse); + } + ``` + + +- **来电开发实例** + 来电的调用流程示例如下图所示: + **图2** 来电调用时序图 - ![](figure/zh-cn_image_0000001214727595.png) - - Modem设备节点读取线程g\_reader会循环读取Modem上报的消息,当Modem接收到来电时会主动上报来电相关的信息; - - 当该线程通过调用OnNotifyOps\(\)解析到Modem上报的数据是以"+CRING"、"RING"等字符开头时,表示有来电事件,然后通过OnCallReport\(reportInfo, NULL, 0\)上报给RIL Adapter完成来电事件上报。 - - ``` - // 将Modem上报数据解析为对应模块的主动上报事件 - void OnNotifyOps(const char *s, const char *smsPdu) - { - int ret = 0; - struct ReportInfo reportInfo = {0}; - reportInfo.error = HRIL_ERR_SUCCESS; - reportInfo.type = HRIL_NOTIFICATION; - if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) { - return; - } - TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu); - // 通过AT指令判断主动上报命令类型 - if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") || - ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") || - ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) { - reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED; - OnCallReport(reportInfo, NULL, 0); // 调用通话相关业务回调函数 - } else if (ReportStrWith(s, "+CMT:")) { - reportInfo.notifyId = HNOTI_SMS_NEW_SMS; - OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu)); - } - // add your codes - ...... - } - ``` - - -## Modem厂商库集成指导 - -### 编译设置 - -Modem厂商库可通过BUILD.gn编译为一个动态库,在RIL Adapter启动时用dlopen方式加载到系统中,然后执行厂商库的初始化操作(参见[Modem厂商库初始化开发指导](#section211mcpsimp)),BUILD.gn编写示例如下: + ![zh-cn_image_0000001214727595](figures/zh-cn_image_0000001214727595.png) + Modem设备节点读取线程g_reader会循环读取Modem上报的消息,当Modem接收到来电时会主动上报来电相关的信息; + + 当该线程通过调用OnNotifyOps()解析到Modem上报的数据是以"+CRING"、"RING"等字符开头时,表示有来电事件,然后通过OnCallReport(reportInfo, NULL, 0)上报给RIL Adapter完成来电事件上报。 + + ``` + // 将Modem上报数据解析为对应模块的主动上报事件 + void OnNotifyOps(const char *s, const char *smsPdu) + { + int ret = 0; + struct ReportInfo reportInfo = {0}; + reportInfo.error = HRIL_ERR_SUCCESS; + reportInfo.type = HRIL_NOTIFICATION; + if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) { + return; + } + TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu); + // 通过AT指令判断主动上报命令类型 + if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") || + ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") || + ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) { + reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED; + OnCallReport(reportInfo, NULL, 0); // 调用通话相关业务回调函数 + } else if (ReportStrWith(s, "+CMT:")) { + reportInfo.notifyId = HNOTI_SMS_NEW_SMS; + OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu)); + } + // add your codes + ...... + } + ``` + + +## Modem厂商库集成指导 + + +### 编译设置 + +Modem厂商库可通过BUILD.gn编译为一个动态库,在RIL Adapter启动时用dlopen方式加载到系统中,然后执行厂商库的初始化操作(参见[Modem厂商库初始化开发指导](#modem厂商库初始化开发指导)),BUILD.gn编写示例如下: + + ``` import("//build/ohos.gni") RIL_ADAPTER = "//base/telephony" @@ -603,8 +539,9 @@ ohos_shared_library("ril_vendor") { // Modem厂商库名称 } ``` -### 调测验证 -1. 编译代码。 -2. 查看/out/{device_name}/telephony/ril\_adapter目录是否存在libril\_vendor.z.so,存在证明集成成功。否则检查代码,重新编译验证。 +### 调测验证 + +1. 编译代码。 +2. 查看/out/{device_name}/telephony/ril_adapter目录是否存在libril_vendor.z.so,存在证明集成成功。否则检查代码,重新编译验证。 diff --git a/zh-cn/device-dev/subsystems/subsys-tel-overview.md b/zh-cn/device-dev/subsystems/subsys-tel-overview.md index 596f0cc00906fd0b5004144acb7d7612aefb7fc7..0c0f850fa040c2f8185c27ef924e20055c204b2f 100644 --- a/zh-cn/device-dev/subsystems/subsys-tel-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-tel-overview.md @@ -1,42 +1,42 @@ -# 电话服务概述 +# 电话服务概述 -- [概述](#section184mcpsimp) -- [基本概念](#section187mcpsimp) -- [运作机制](#section194mcpsimp) -- [约束与限制](#section205mcpsimp) -## 概述 +## 概述 本指南简要介绍了Modem厂商库的集成、初始化、业务请求响应和事件上报的方法,并通过通话业务的具体开发实例呈现厂商库的适配开发过程,供不同Modem芯片的开发者参考,从而帮助其高效地实现电话相关业务功能的开发。 -## 基本概念 -- Telephony Service:电话服务子系统核心服务层。主要功能是初始化RIL管理类、SIM卡和搜网模块;获取RIL Adapter服务,通过注册回调服务,实现与RIL Adapter的通信功能;通过发布订阅,来实现与通话、短信等功能模块之间的通信。 -- RIL Adapter:电话服务子系统RIL适配层。该层主要包括厂商库加载,业务接口实现。用于屏蔽不同Modem厂商的硬件差异,为上层提供统一的接口,通过注册HDF服务与上层接口通信。 -- HDF:硬件驱动框架(Hardware Driver Foundation)。用于提供统一外设访问能力和驱动开发、管理框架。 -- hdc\_std:OpenHarmony设备连接器(OpenHarmony Device Connector)。是OpenHarmony为开发人员提供的用于设备连接调试的命令行工具。 +## 基本概念 -## 运作机制 +- Telephony Service:电话服务子系统核心服务层。主要功能是初始化RIL管理类、SIM卡和搜网模块;获取RIL Adapter服务,通过注册回调服务,实现与RIL Adapter的通信功能;通过发布订阅,来实现与通话、短信等功能模块之间的通信。 -**图 1** RIL Adapter模块架构图 +- RIL Adapter:电话服务子系统RIL适配层。该层主要包括厂商库加载,业务接口实现。用于屏蔽不同Modem厂商的硬件差异,为上层提供统一的接口,通过注册HDF服务与上层接口通信。 +- HDF:硬件驱动框架(Hardware Driver Foundation)。用于提供统一外设访问能力和驱动开发、管理框架。 -![](figure/ril-adapter模块架构图.png) +- hdc_std:OpenHarmony设备连接器(OpenHarmony Device Connector)。是OpenHarmony为开发人员提供的用于设备连接调试的命令行工具。 -RIL Adapter模块架构如图1所示,内部主要分为hril\_hdf、hril和vendorlib三层。 -- hril\_hdf:RIL Adapter的唯一入口,主要负责Modem厂商库的加载。其中,modem\_adapter实现了单一固件对不同Modem的适配。 +## 运作机制 - 其实现机制为:在加载Modem厂商库之前,从kernel获取Modem的设备型号,根据此型号加载对应的Modem厂商库。 + **图1** RIL Adapter模块架构图 -- hril:OpenHarmony无线接口层(OpenHarmony Radio Interface Layer)。与Telephony Service交互的接口实现部分,实现了Telephony Service和vendorlib通信的功能,包括SIM卡、搜网、蜂窝数据、蜂窝通话和短彩信等。 -- vendorlib:Modem厂商库文件。不同的Modem厂商根据RIL Adapter提供的标准化接口或ID,进行Modem厂商库的开发(vendorlib由Modem厂商提供)。 +![zh-cn_image_0000001210683929](figures/zh-cn_image_0000001210683929.png) -hril\_hdf执行后,将动态加载vendorlib,vendorlib可以从hril\_hdf中获取处理响应和上报的函数指针,该过程结束后,hril\_hdf才可通过vendorlib与Modem通信。 +RIL Adapter模块架构如图1所示,内部主要分为hril_hdf、hril和vendorlib三层。 -## 约束与限制 +- hril_hdf:RIL Adapter的唯一入口,主要负责Modem厂商库的加载。其中,modem_adapter实现了单一固件对不同Modem的适配。 + 其实现机制为:在加载Modem厂商库之前,从kernel获取Modem的设备型号,根据此型号加载对应的Modem厂商库。 + +- hril:OpenHarmony无线接口层(OpenHarmony Radio Interface Layer)。与Telephony Service交互的接口实现部分,实现了Telephony Service和vendorlib通信的功能,包括SIM卡、搜网、蜂窝数据、蜂窝通话和短彩信等。 + +- vendorlib:Modem厂商库文件。不同的Modem厂商根据RIL Adapter提供的标准化接口或ID,进行Modem厂商库的开发(vendorlib由Modem厂商提供)。 + +hril_hdf执行后,将动态加载vendorlib,vendorlib可以从hril_hdf中获取处理响应和上报的函数指针,该过程结束后,hril_hdf才可通过vendorlib与Modem通信。 + + +## 约束与限制 **规格限制:** 需要设备厂商至少支持一个Modem,如果不支持任何Modem,无需实现厂商库接口。 - diff --git a/zh-cn/device-dev/subsystems/subsys-tel.md b/zh-cn/device-dev/subsystems/subsys-tel.md index 850029b583cd695cce8f07dcabd7c550e6f163f7..18fb1c222599057d529dbf0547723e8cc8b270e6 100644 --- a/zh-cn/device-dev/subsystems/subsys-tel.md +++ b/zh-cn/device-dev/subsystems/subsys-tel.md @@ -1,7 +1,7 @@ -# 电话服务 +# 电话服务 -- **[电话服务概述](subsys-tel-overview.md)** -- **[电话服务开发指导](subsys-tel-guide.md)** +- **[电话服务概述](subsys-tel-overview.md)** +- **[电话服务开发指导](subsys-tel-guide.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md b/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md index 2c443396aca58e31aa099a8de06db028781c7fdd..ab872f2a178102a222ac5680f8949f5808c5ccac 100644 --- a/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md @@ -1,89 +1,44 @@ -# bytrace使用指导 +# bytrace使用指导 -- [简介](#section11388623181619) -- [开发指导](#section1595564317164) -- [使用实例](#section667273201818) -## 简介 +## 简介 bytrace是开发人员用于追踪进程轨迹、分析性能的一种工具,主要对内核ftrace进行了封装和扩展,来支持用户态的打点。通过该工具可以打开想要查看的用户态和内核label(通过下面命令行bytrace -l,查看支持的所有label),然后通过命令行进行抓取trace信息到指定文件中。 -## 开发指导 + +## 参数说明 bytrace当前支持以下命令: -**表 1** 命令行列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Option

-

Description

-

-h,--help

-

查看option帮助

-

-b n,--buffer_size n

-

指定n(KB)内存大小用于存取trace日志,默认2048KB

-

-t n,--time n

-

用来指定trace运行的时间(单位:s),取决于需要分析过程的时间

-

--trace_clock clock

-

trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot

-

--trace_begin

-

启动抓trace

-

--trace_dump

-

将数据输出到指定位置(默认控制台)

-

--trace_finish

-

停止抓trace,并将数据输出到指定位置(默认控制台)

-

-l,--list_categories

-

输出手机能支持的trace模块

-

--overwrite

-

当缓冲区满的时候,将丢弃最新的信息。(默认丢弃最老的日志)

-

-o filename,--output filename

-

指定输出的目标文件名称

-

-z

-

抓取trace后进行压缩

-
- -## 使用实例 + **表1** 命令行列表 + +| Option | Description | +| -------- | -------- | +| -h,--help | 查看option帮助 | +| -b _n_,--buffer_size _n_ | 指定_n_(KB)内存大小用于存取trace日志,默认2048KB | +| -t _n_,--time _n_ | 用来指定trace运行的时间(单位:s),取决于需要分析过程的时间 | +| --trace_clock _clock_ | trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot | +| --trace_begin | 启动抓trace | +| --trace_dump | 将数据输出到指定位置(默认控制台) | +| --trace_finish | 停止抓trace,并将数据输出到指定位置(默认控制台) | +| -l,--list_categories | 输出手机能支持的trace模块 | +| --overwrite | 当缓冲区满的时候,将丢弃最新的信息。(默认丢弃最老的日志) | +| -o _filename_,--output _filename_ | 指定输出的目标文件名称 | +| -z | 抓取trace后进行压缩 | + + +## 使用实例 + +准备工作,使用bytrace工具需要先进入shell命令行: + + +``` +hdc shell +``` 以下是常用bytrace命令示例,供开发者参考: -- 查询支持的label。 +- 查询支持的label。 ``` bytrace -l @@ -91,25 +46,25 @@ bytrace -l 或者 + ``` bytrace --list_categories ``` -- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 +- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 ``` bytrace -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace ``` -- 设置trace的输出时钟为mono。 +- 设置trace的输出时钟为mono。 ``` bytrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace ``` -- 抓取trace后进行压缩。 +- 抓取trace后进行压缩。 ``` bytrace -z -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace ``` - diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md b/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md index 1f9071970764cb505a7f30d28a62b6cfd23df3c4..64c3cb7dde1ee4280c8036f4392afe7232c5e53f 100644 --- a/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md @@ -1,26 +1,15 @@ -# hdc\_std 使用指导 +# hdc_std使用指导 -- [环境准备](#section05992022154916) -- [注意事项](#section19543134915210) -- [option相关的命令](#section618522925119) -- [查询设备列表的命令](#section174891132104218) -- [服务进程相关命令](#section680531510497) -- [网络相关的命令](#section71176123212) -- [文件相关的命令](#section173133523013) -- [应用相关的命令](#section2072647133819) -- [调试相关的命令](#section112861250195015) -- [常见问题](#section592920255582) - - [hdc\_std连接不到设备](#section74019384588) - - [hdc\_std运行不了](#section63291491267) +hdc_std(OpenHarmony Device Connector)是 OpenHarmony 为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux/MacOS等系统上与开发机或者模拟器进行交互。 -hdc\_std(OpenHarmony Device Connector)是OpenHarmony为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux等系统上与开发机或者模拟器进行交互。 -下文将介绍hdc\_std的环境准备和常用命令及使用举例。 +下文将介绍hdc_std的环境准备和常用命令及使用举例。 -## 环境准备 -**hdc\_std 工具获取方式:** +## 环境准备 + +**hdc_std 工具获取方式:** 通过OpenHarmony sdk获取,hdc_std在sdk的toolchains目录下。 @@ -30,663 +19,413 @@ hdc\_std(OpenHarmony Device Connector)是OpenHarmony为开发人员提供的 获取windows的sdk,将hdc_std.exe放到磁盘某个位置即可使用。 -## 注意事项 -- 使用hdc\_std,如果出现异常,可以尝试通过hdc\_std kill命令杀掉hdc\_std服务,或者通过hdc\_std start -r命令重启服务进程进行解决。 -- 如果出现hdc\_std list targets获取不到设备信息,通过任务管理器查看是否有hdc.exe进程存在,如果进程存在,可以通过杀掉该进程进行解决。 +## 注意事项 + +- 使用hdc_std,如果出现异常,可以尝试通过hdc_std kill命令杀掉hdc_std服务,或者通过hdc_std start -r命令重启服务进程进行解决。 + +- 如果出现hdc_std list targets获取不到设备信息,通过任务管理器查看是否有hdc_std进程存在,如果进程存在,可以通过杀掉该进程进行解决。 + -## option相关的命令 +## option相关的命令 option涉及以下命令: -**-h/help -v/version** -用于显示hdc相关的帮助、版本信息。 +- **-h/help -v/version** + 用于显示hdc相关的帮助、版本信息。 -**表 1** 命令说明 + **表1** 命令说明 + + | | | + | -------- | -------- | + | **返回值** | **返回值说明** | + | 返回对应信息 | 帮助或者版本信息 | - - - - - - - - -

返回值

-

返回值说明

-

返回对应信息

-

帮助或者版本信息

-
+ 使用方法: -使用方法: + + ``` + hdc_std -h / hdc_std help + ``` -hdc\_std -h / hdc\_std help - -hdc\_std -v / hdc\_std version - -**-t key** - -用于连接指定设备标识为key的设备。 - -**表 2** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

key

-

为tcp:port格式,或者USB序列号

-

返回值

-

返回值说明

-

①error: device '***' not found

-

②Nothing to do...

-

①设备不存在

-

②附加的命令不存在

-
+ + ``` + hdc_std -v / hdc_std version + ``` -使用方法: +- **-t key** + 用于连接指定设备标识为key的设备。 + + **表2** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | key | 为 IP地址:port 格式,或者USB序列号 | + | **返回值** | **返回值说明** | + | ①error: device '\*\*\*' not found
②Nothing to do... | ①设备不存在
②附加的命令不存在 | + + 使用方法: -该option需要与具体的操作命令搭配使用,下面以shell命令举例: + 该option需要与具体的操作命令搭配使用,下面以shell命令举例: -hdc\_std list targets (获取设备信息) + hdc_std list targets (获取设备信息) -hdc\_std -t _key_ shell (-t后面添加的_key_ 需要替换为上面查询的设备信息) + hdc_std -t _key_ shell (-t后面添加的_key_ 需要替换为上面查询的设备信息) ->![](../public_sys-resources/icon-note.gif) **说明:** ->一台开发机可支持多个设备连接,每个设备有其唯一的设备标识,如果通过网络与设备连接,其标识为tcp:port格式,如果通过usb连接则标识为设备sn号。该命令需要跟随具体操作命令。 + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 一台开发机可支持多个设备连接,每个设备有其唯一的设备标识,如果通过网络与设备连接,其标识为IP地址:port格式,如果通过usb连接则标识为设备sn号。该命令需要跟随具体操作命令。 -## 查询设备列表的命令 + +## 查询设备列表的命令 查询设备列表涉及以下命令: -**list targets\[-v\]** + +``` +list targets[-v] +``` + 显示所有已经连接的目标设备列表 -**表 3** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-v

-

添加-v选项,则会打印设备详细信息

-

返回值

-

返回值说明

-

①返回设备信息

-

②[Empty]

-

①已经连接的设备列表信息

-

②没有查询到设备信息

-
+ + **表3** 命令说明 + +| | | +| -------- | -------- | +| **参数** | **参数说明** | +| -v | 添加-v选项,则会打印设备详细信息 | +| **返回值** | **返回值说明** | +| ①返回设备信息
②[Empty] | ①已经连接的设备列表信息
②没有查询到设备信息 | + 使用方法: -hdc\_std list targets -hdc\_std list targets -v + +``` +hdc_std list targets +``` + + + +``` +hdc_std list targets -v +``` -## 服务进程相关命令 + +## 服务进程相关命令 服务进程涉及以下命令: -**target mount** - -以读写模式挂载/system等分区。 - -**表 4** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-

-

返回值

-

返回值说明

-

①Mount finish

-

②返回具体信息

-

①成功情况下返回的信息

-

②失败情况下的具体信息

-
-使用方法: +- **target mount** + 以读写模式挂载系统分区。 -hdc\_std target mount + **表4** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | 无 | 无 | + | **返回值** | **返回值说明** | + | ①Mount finish
②返回具体信息 | ①成功情况下返回的信息
②失败情况下的具体信息 | -**smode \[off\]** + 使用方法: -授予后台服务进程root权限, 使用off参数取消授权。 + + ``` + hdc_std target mount + ``` -使用方法: +- **smode [off]** + 授予后台服务进程root权限, 使用off参数取消授权。 -hdc\_std smode - -hdc\_std smode off - -**kill \[-r\]** - -终止服务进程。 - -**表 5** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-r

-

触发服务重启

-

返回值

-

返回值说明

-

①Kill server finish

-

②返回具体信息

-

①成功情况下返回的信息

-

②失败情况下的具体信息

-
+ 使用方法: -使用方法: + + ``` + hdc_std smode + ``` -hdc\_std kill - -**start \[-r\]** - -启动服务进程。 - -**表 6** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-r

-

如果服务进程已经启动,-r选项会触发服务进程重新启动

-

返回值

-

返回值说明

-

-

-
+ + ``` + hdc_std smode off + ``` -使用方法: +- **kill [-r]** + 终止服务进程。 + + **表5** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | -r | 触发服务重启 | + | **返回值** | **返回值说明** | + | ①Kill server finish
②返回具体信息 | ①成功情况下返回的信息
②失败情况下的具体信息 | + + 使用方法: + + ``` + hdc_std kill + ``` -hdc\_std start +- **start [-r]** + 启动服务进程。 -## 网络相关的命令 + **表6** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | -r | 如果服务进程已经启动,-r选项会触发服务进程重新启动 | + | **返回值** | **返回值说明** | + | 无 | 无 | + + 使用方法: + + ``` + hdc_std start + ``` + + +## 网络相关的命令 网络部分涉及以下命令: -**tconn host\[:port\]\[-remove\]** - -通过【ip地址:端口号】来指定连接的设备 - -**表 7** 命令说明 - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

host[:port]

-

为tcp:port格式

-

-remove

-

表示断开与指定设备的连接

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std tconn 192.168.0.100:8710 - -**tmode usb** - -执行后设备端对应daemon进程重启,并首先选用usb连接方式。 - -**表 8** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
-使用方法: +- **tconn host[:port][-remove]** + 通过【ip地址:端口号】来指定连接的设备 -hdc\_std tmode usb - -**tmode port port-number** - -执行后设备端对应daemon进程重启,并优先使用网络方式连接设备,如果连接设备再选择usb连接。 - -**表 9** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

port-number

-

listen连接的网络端口

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
+ **表7** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | host[:port] | 为IP地址:port格式 | + | -remove | 表示断开与指定设备的连接 | + | **返回值** | **返回值说明** | + | ①返回具体信息
②无 | ①失败情况下的具体信息
②成功情况下无返回值 | -使用方法: + 使用方法(举例): + + + ``` + hdc_std tconn 192.168.0.100:8710 + ``` + +- **tmode usb** + 执行后设备端对应daemon进程重启,并首先选用usb连接方式。 -hdc\_std tmode port 8710 + **表8** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | 无 | 无 | + | **返回值** | **返回值说明** | + | ①返回具体信息
②无 | ①失败情况下的具体信息
②成功情况下无返回值 | ->![](../public_sys-resources/icon-note.gif) **说明:** ->执行完毕后,远端daemon将会退出并重启,默认启用TCP连接,如果不加上listen端口则listen随机端口。 + 使用方法: -## 文件相关的命令 + + ``` + hdc_std tmode usb + ``` + +- **tmode port port-number** + 执行后设备端对应daemon进程重启,并优先使用网络方式连接设备,如果连接设备失败,再选择usb连接。 + + **表9** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | port-number | listen连接的网络端口号 | + | **返回值** | **返回值说明** | + | ①返回具体信息
②无 | ①失败情况下的具体信息
②成功情况下无返回值 | + + 使用方法: + + + ``` + hdc_std tmode port 8710 + ``` + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 执行完毕后,远端daemon将会退出并重启,默认启用TCP连接,如果不加上listen端口则listen随机端口。 + + +## 文件相关的命令 文件部分涉及以下命令: -**file send local remote** - -发送文件至远端设备。 - -**表 10** 命令说明 - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

local

-

本地待发送文件路径

-

remote

-

远程待接收文件路径

-

返回值

-

返回值说明

-

①返回具体信息

-

②返回传输结果

-

①失败情况下的具体信息

-

②成功传输的结果信息

-
- -使用方法(举例): - -hdc\_std file send E:\\a.txt /data/local/tmp/a.txt - -**file recv \[-a\] remote local** - -从远端设备接收文件至本地。 - -**表 11** 命令说明 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-a

-

文件保留时间戳模式

-

local

-

本地待接收文件路径

-

remote

-

远程待发送文件路径

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std file recv /data/local/tmp/a.txt ./a.txt - -## 应用相关的命令 + +- **file send local remote** + 发送文件至远端设备。 + + **表10** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | local | 本地待发送文件路径 | + | remote | 远程待接收文件路径 | + | **返回值** | **返回值说明** | + | ①返回具体信息
②返回传输结果 | ①失败情况下的具体信息
②成功传输的结果信息 | + + 使用方法(举例): + + + ``` + hdc_std file send E:\a.txt /data/local/tmp/a.txt + ``` + +- **file recv [-a] remote local** + 从远端设备接收文件至本地。 + + **表11** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | -a | 文件保留时间戳模式 | + | local | 本地待接收文件路径 | + | remote | 远程待发送文件路径 | + | **返回值** | **返回值说明** | + | ①返回具体信息
②无 | ①失败情况下的具体信息
②成功情况下无返回值 | + + 使用方法(举例): + + + ``` + hdc_std file recv /data/local/tmp/a.txt ./a.txt + ``` + + +## 应用相关的命令 应用部分涉及以下命令: -**install \[-r/-d/-g\] _package_** - -安装OpenHarmony package。 - -**表 12** 命令说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

package

-

OpenHarmony应用安装包

-

-r

-

替换已存在应用

-

-d

-

允许降级安装

-

-g

-

动态授权

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std install _hwadmin.hap_ - -**uninstall \[-k\] package** - -卸载OpenHarmony应用。 - -**表 13** 命令说明 - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

package

-

OpenHarmony应用安装包

-

-k

-

保留/data/cache

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std uninstall _package_ - -## 调试相关的命令 -调试涉及以下命令: +- **install [-r/-d/-g] _package_** + 安装OpenHarmony APP package。 -**hilog** - -支持抓取log信息。 - -**表 14** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-

-

返回值

-

返回值说明

-

返回具体信息

-

抓取的日志信息

-
- -抓取hilog日志: - -hdc\_std hilog - -清理hilog缓存日志: - -hdc_std shell "hilog -r" - ->![](../public_sys-resources/icon-note.gif) **说明:** ->更多hilog操作命令请参考[hilog组件使用说明](https://gitee.com/openharmony/hiviewdfx_hilog/blob/master/README_zh.md#%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E)。 - -**shell \[_command_\]** - -远程执行命令或进入交互命令环境。 - -**表 15** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

command

-

需要执行的单次命令

-

返回值

-

返回值说明

-

返回具体信息

-

shell后面执行命令的结果信息

-
+ **表12** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | package | OpenHarmony应用安装包文件名 | + | -r | 替换已存在应用 | + | -d | 允许降级安装 | + | -g | 应用动态授权 | + | **返回值** | **返回值说明** | + | ①返回具体信息
②无 | ①失败情况下的具体信息
②成功情况下无返回值 | + + 使用方法(举例): + + + ``` + hdc_std install hwadmin.hap + ``` + +- **uninstall [-k] package** + 卸载OpenHarmony应用。 + + **表13** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | package | OpenHarmony应用安装包 | + | -k | 保留/data/cache | + | **返回值** | **返回值说明** | + | ①返回具体信息
②无 | ①失败情况下的具体信息
②成功情况下无返回值 | + + 使用方法(举例): + + + ``` + hdc_std uninstall package + ``` + + +## 调试相关的命令 + +调试涉及以下命令: -使用方法: -hdc\_std shell +- **hilog** + 支持抓取log信息。 -## 常见问题 + **表14** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | 无 | 无 | + | **返回值** | **返回值说明** | + | 返回具体信息 | 抓取的日志信息 | -### hdc\_std连接不到设备 + 抓取hilog日志: -- **现象描述** + + ``` + hdc_std hilog + ``` - 执行 "hdc\_std list targets"命令后结果为:\[Empty\] + 清理hilog缓存日志: -- **解决方法** - 1. 设备没有被识别: + + ``` + hdc_std shell "hilog -r" + ``` - 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 +- **shell [_command_]** + 远程执行命令或进入交互命令环境。 - 2. hdc\_std工作异常: + **表15** 命令说明 + + | | | + | -------- | -------- | + | **参数** | **参数说明** | + | command | 需要执行的单次命令 | + | **返回值** | **返回值说明** | + | 返回具体信息 | shell后面执行命令的结果信息 | - 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 + 使用方法: - 3. hdc\_std与设备不匹配: + + ``` + hdc_std shell + ``` - 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 +## 常见问题 -### hdc\_std运行不了 +### hdc_std连接不到设备 -- **现象描述** +- **现象描述** + 执行 "hdc_std list targets"命令后结果为:[Empty] - 点击hdc\_std.exe文件无法运行。 +- **解决方法** + 1. 设备没有被识别: + 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要断开并重联PC和OpenHarmony设备之间的USB连接,或者烧写最新的镜像。 + 2. hdc_std工作异常: + 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 + 3. hdc_std与设备不匹配: + 如果设备烧写的是最新镜像,hdc_std也需要使用最新版本。 -- **解决方法** - hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 +### hdc_std运行不了 +- **现象描述** + 点击hdc_std.exe文件无法运行。 +- **解决方法** + hdc_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc_std命令直接使用。 diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-hiperf.md b/zh-cn/device-dev/subsystems/subsys-toolchain-hiperf.md index 8a5476185d5eed517aeff04f49d4efc3e4f3f710..b6c2765d8206ab2cc2f6779ff2d4288f9ba873e0 100644 --- a/zh-cn/device-dev/subsystems/subsys-toolchain-hiperf.md +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-hiperf.md @@ -1,5 +1,4 @@ -# hiperf 使用指南 - +# hiperf使用指导 hiperf是为开发人员提供性能采样分析的工具,基于内核perf机制进行的用户态能力的扩展,可以对指定的程序或者整个系统进行性能采样。 @@ -18,23 +17,25 @@ hiperf支持的命令有:list、stat、record、report等,可以通过hiperf 列出设备上支持的所有perf事件名称,事件名称用于 stat 和 record命令的 -e 和 -g 参数。 + ``` Usage: hiperf list [event type] ``` -| 参数 | 功能说明 | + | 参数 | 功能说明 | | -------- | -------- | -| hw | 列出支持的 hardware 事件(PMU支持) | -| sw | 列出支持的 software 事件 | -| tp | 列出支持 tracepotint 事件 | -| cache | 列出支持的 cache 事件(PMU支持) | -| raw | 列出支持的原始PMU事件 | +| hw | 列出支持的 hardware 事件(PMU支持) | +| sw | 列出支持的 software 事件 | +| tp | 列出支持 tracepotint 事件 | +| cache | 列出支持的 cache 事件(PMU支持) | +| raw | 列出支持的原始PMU事件 | ### 使用示例 -下面列出了设备支持的 HW 事件,并且会提示哪些事件此设备不支持。 +下面列出了设备支持的hardware事件,并且会提示哪些事件此设备不支持。 + ``` hiperf list hw event not support hw-stalled-cycles-backend @@ -57,31 +58,33 @@ Supported events for hardware: ### 参数说明 -监听指定目标程序,周期性打印性能计数器的值。 + 监听指定目标程序,周期性打印性能计数器的值。 + ``` Usage: hiperf stat [options] Collect performance counter information. ``` -| 参数 | 功能说明 | + | 参数 | 功能说明 | | -------- | -------- | -| -a | 采集监听整个系统的所有线程和默认的性能计数器的值。 | -| -c | 指定cpu id,可以是0,1,2用逗号分隔。 | -| -d <_sec_> | 指定监听的时间,单位为秒。 | -| -i <_ms_> | 指定监听事件的间隔打印时间,单位毫秒。 | -| -e | 指定监听的事件,可以通过list命令查看支持的所有事件,其中event:u 或者 :k 表示限制事件为用户空间或者内核空间。 | -| -g | 指定需要在同一组监听的事件,同一组事件会被放入同一个PMU监听。 | -| --no-inherit | 不监听目标线程/进程启动的子线程。 | -| -p | 指定需要监听的进程pid。 | -| -t | 指定需要监听的线程tid。 | -| --verbose | 显示详细的报告内容,包括一些原始的时间数据等等。 | +| -a | 采集监听整个系统的所有线程和默认的性能计数器的值。 | +| -c | 指定cpu id,可以是0,1,2用逗号分隔。 | +| -d <_sec_> | 指定监听的时间,单位为秒。 | +| -i <_ms_> | 指定监听事件的间隔打印时间,单位毫秒。 | +| -e | 指定监听的事件,可以通过list命令查看支持的所有事件,其中event:u 或者 :k 表示限制事件为用户空间或者内核空间。 | +| -g | 指定需要在同一组监听的事件,同一组事件会被放入同一个PMU监听。 | +| --no-inherit | 不监听目标线程/进程启动的子线程。 | +| -p | 指定需要监听的进程pid。 | +| -t | 指定需要监听的线程tid。 | +| --verbose | 显示详细的报告内容,包括一些原始的时间数据等等。 | ### 使用示例 下面是通过 stat 监听整个系统3秒的示例: + ``` hiperf stat -d 3 -a this is root mode, perfEventParanoid assume as -1 @@ -100,12 +103,12 @@ Timeout exit (total 3009 ms) ### 字段说明 -| 字段名 | 含义 | + | 字段名 | 含义 | | -------- | -------- | -| count | 表示事件发生的次数 | -| name | 事件的名称,在 list 命令中可以看到所有支持的命令,hw 和 sw 的前缀分别代表是hardware事件还是software事件。 | -| comment | 一些经过计算的方便用户阅读的值。例如 CPU 的相对主频,千位进制换算等等。 | -| coverage | 该事件在PMU中的 enable 百分比,受限于PMU数量,每次装载的PMU监听事件是有限的。 | +| count | 表示事件发生的次数。 | +| name | 事件的名称,在 list 命令中可以看到所有支持的命令,hw 和 sw 的前缀分别代表是hardware事件还是software事件。 | +| comment | 一些经过计算的方便用户阅读的值。例如 CPU 的相对主频,千位进制换算等等。 | +| coverage | 该事件在PMU中的 enable 百分比,受限于PMU数量,每次装载的PMU监听事件是有限的。 | ## record 命令 @@ -115,79 +118,88 @@ Timeout exit (total 3009 ms) 采样指定目标程序,并且将采样数据保存到指定的文件中(默认为perf.data) + ``` Usage: hiperf record [options] Collect performance sampling information. ``` -| 参数 | 功能说明 | + | 参数 | 功能说明 | | -------- | -------- | -| -a | 对整个系统的所有进程和线程进行采样。 | -| --exclude-hiperf | 不采样hiperf自身进程。 | -| -c | 指定采样的cpu id。 | -| --cpu-limit <_percent_> | 限定采样过程占用的CPU最大百分比。 | -| -d <sec> | 指定采样时长,单位秒。 | -| -f <freq> | 设置采样事件的触发频率,默认为4000。
说明:该频率越高cpu负载会越高,但是数据采样会越多。 | -| --period <_num_> | 设置采样事件触发周期,以次数为单位,即发生指定的次数后采样一次。 | -| -e | 指定监听的事件,可以通过list命令查看支持的所有事件,其中event:u 或者 :k 可以表示限制事件为用户空间或者内核空间。 | -| -g | 指定需要在同一组监听的事件,同一组事件会被放入同一个PMU监听。 | -| --no-inherit | 不监听目标线程或者进程启动的子线程。 | -| -p | 指定需要监听的进程。 | -| -t | 指定需要监听的线程。 | -| --offcpu | 监听cpu调度事件,它等价于 --period 1 -e sched:sched_switch 事件。 | -| -j <_branch_filter1_>[,_branch_filter2_]... | 监听分支预测事件。分支预测就是指令存在多个if else判定的情况下,cpu去预测下一步即将执行哪一条指令。 | -| -s / --call-stack <_fp \\| dwarf[,size]_> | 设置用户栈的回栈方式,支持fp和dwarf两种方式。dwarf 后面可以指定采样的用户堆栈大小,默认是 65528。 | -| --delay-unwind | 延迟回栈,等到采样结束再进行回栈。 | -| --disable-unwind | 不进行回栈,用户的寄存器和堆栈数据会保存在perf.data中,供离线回栈使用。 | -| --disable-callstack-expend | 默认会对回栈的调用栈信息进行合并扩展,此选项会关闭该功能。 | -| --clockid <_clock type_> | 设置采样数据的时钟源,支持monotonic、boottime、realtime等。 | -| --symbol-dir <_dir_> | 指定符号表路径,如果指定了回栈时会优先使用该路径下的符号表。 | -| -m <_mmap pages_> | 指定缓存的大小,默认值为1024,以页为单位。参数需要为2的幂,范围为 [2 - 1024]。
说明:该值越高,事件丢失率会越低,但是内存占用会增大。 | -| --app <_package name_> | 指定采样的目标应用的包名,默认超时等待时间为10秒。 | -| --data-limit <_SIZE[K\|M|G]_> | 指定采样结果的最大容量,支持K/M/G(B)为单位,默认无大小限制。 | -| -o <_output file name_> | 指定采样数据结果文件名,默认为/data/local/tmp/perf.data。 | -| -z | 启动压缩模式,在保存到文件的时候,会用gzip进行压缩。 | -| --verbose | 采样的时候显示更详细的日志信息。 | +| -a | 对整个系统的所有进程和线程进行采样。 | +| --exclude-hiperf | 不采样hiperf自身进程。 | +| -c | 指定采样的cpu id。 | +| --cpu-limit <_percent_> | 限定采样过程占用的CPU最大百分比。 | +| -d <sec> | 指定采样时长,单位秒。 | +| -f <freq> | 设置采样事件的触发频率,默认为4000。
说明:该频率越高cpu负载会越高,但是数据采样会越多。 | +| --period <_num_> | 设置采样事件触发周期,以次数为单位,即发生指定的次数后采样一次。 | +| -e | 指定监听的事件,可以通过list命令查看支持的所有事件,其中event:u 或者 :k 可以表示限制事件为用户空间或者内核空间。 | +| -g | 指定需要在同一组监听的事件,同一组事件会被放入同一个PMU监听。 | +| --no-inherit | 不监听目标线程或者进程启动的子线程。 | +| -p | 指定需要监听的进程。 | +| -t | 指定需要监听的线程。 | +| --offcpu | 监听cpu调度事件,它等价于 --period 1 -e sched:sched_switch 事件。 | +| -j <_branch_filter1_>[,_branch_filter2_]... | 监听分支预测事件。分支预测就是指令存在多个if else判定的情况下,cpu去预测下一步即将执行哪一条指令。 | +| -s / --call-stack <_fp \\| dwarf[,size]_> | 设置用户栈的回栈方式,支持fp和dwarf两种方式。dwarf 后面可以指定采样的用户堆栈大小,默认是 65528。 | +| --delay-unwind | 延迟回栈,等到采样结束再进行回栈。 | +| --disable-unwind | 不进行回栈,用户的寄存器和堆栈数据会保存在perf.data中,供离线回栈使用。 | +| --disable-callstack-expend | 默认会对回栈的调用栈信息进行合并扩展,此选项会关闭该功能。 | +| --clockid <_clock type_> | 设置采样数据的时钟源,支持monotonic、boottime、realtime等。 | +| --symbol-dir <_dir_> | 指定符号表路径,如果指定了回栈时会优先使用该路径下的符号表。 | +| -m <_mmap pages_> | 指定缓存的大小,默认值为1024,以页为单位。参数需要为2的幂,范围为 [2 - 1024]。
说明:该值越高,事件丢失率会越低,但是内存占用会增大。 | +| --app <_package name_> | 指定采样的目标应用的包名,默认超时等待时间为10秒。 | +| --data-limit <_SIZE[K\|M\|G]_> | 指定采样结果的最大容量,支持K/M/G(B)为单位,默认无大小限制。 | +| -o <_output file name_> | 指定采样数据结果文件名,默认为/data/local/tmp/perf.data。 | +| -z | 启动压缩模式,在保存到文件的时候,会用gzip进行压缩。 | +| --verbose | 采样的时候显示更详细的日志信息。 | ### 使用示例 - 对全系统所有进程采样3秒,并且显示详细的日志信息 + ``` hiperf record -d 3 -a --verbose ``` - 指定使用fp方式进行回栈 + ``` hiperf record -s fp -d 3 -a ``` - 指定使用dwarf方式进行回栈 + ``` hiperf record -s dwarf -d 3 -a ``` - 指定采样offcpu事件 + ``` hiperf record --offcpu -s dwarf -d 3 -a ``` - 指定延迟回栈 + ``` hiperf record -d 3 -s dwarf --delay-unwind -a ``` - 禁止回栈,此时会保存堆栈数据到perf.data文件 + ``` hiperf record -d 3 -s dwarf --disable-unwind -a ``` - 指定追踪的包名,如果指定的包名对应的进程不存在则会延时等待10秒,超时后进程退出 + ``` hiperf record -d 3 -s dwarf --app com.ohos.launch ``` - 指定对采样结果数据进行压缩保存 + ``` hiperf record -z -s dwarf -d 3 -a ``` @@ -197,35 +209,38 @@ Usage: hiperf record [options] 此命令主要用于展示record中抓取的采样数据 + ``` Usage: hiperf report [option] Report sampling information from perf.data. ``` -| 参数 | 功能说明 | + | 参数 | 功能说明 | | -------- | -------- | -| --symbol-dir <_dir_> | 指定符号表路径。 | -| --limit-percent <_number_> | 指定展示结果的最低百分比(低于的不显示)。 | -| -s / --call-stack | 指定该选项后结果数据中会包含详细的调用栈信息。 | -| --call-stack-limit-percent <_number_> | 调用栈的百分比最小值(低于的不显示)。 | -| --proto | 将输入的 perf.data 文件转换为 proto 格式,默认文件名为 perf.proto。 | -| --json | 将输入的 perf.data 文件转换为 json 格式,默认文件名为 perf.json。 | -| --branch | 按分支预测的结果地址来展示报告,而不是调用栈的IP地址。 | -| --<_keys_> <_keyname1_>[,_keyname2_][,...] | 按给出的关键字来过滤展示报告,keys支持:comms、pids、tids等 例如 --comms hiperf,hilog 表示仅显示进程/线程名称为 hiperf或者hilog的记录条目。 | -| --sort <_key1_>[,_key2_][,...] | 按照给出的关键字来排序和显示,支持:pid、tid、comm等,可以指定多个关键字。 | -| -i <_filename_> | 指定输入的采样数据(默认为perf.data)。 | -| -o <_filename_> | 指定输出的报告文件名。 | +| --symbol-dir <_dir_> | 指定符号表路径。 | +| --limit-percent <_number_> | 指定展示结果的最低百分比(低于的不显示)。 | +| -s / --call-stack | 指定该选项后结果数据中会包含详细的调用栈信息。 | +| --call-stack-limit-percent <_number_> | 调用栈的百分比最小值(低于的不显示)。 | +| --proto | 将输入的 perf.data 文件转换为 proto 格式,默认文件名为 perf.proto。 | +| --json | 将输入的 perf.data 文件转换为 json 格式,默认文件名为 perf.json。 | +| --branch | 按分支预测的结果地址来展示报告,而不是调用栈的IP地址。 | +| --<_keys_> <_keyname1_>[,_keyname2_][,...] | 按给出的关键字来过滤展示报告,keys支持:comms、pids、tids等 例如 --comms hiperf,hilog 表示仅显示进程/线程名称为 hiperf或者hilog的记录条目。 | +| --sort <_key1_>[,_key2_][,...] | 按照给出的关键字来排序和显示,支持:pid、tid、comm等,可以指定多个关键字。 | +| -i <_filename_> | 指定输入的采样数据(默认为perf.data)。 | +| -o <_filename_> | 指定输出的报告文件名。 | ## 使用示例 - 输出采样数据的报告,默认读取perf.data文件 + ``` hiperf report ``` 输出结果举例: + ``` Heating count comm pid tid dso func 5.68% 15073949 hiperf_example_ 1085 1091 /system/lib/ld-musl-arm.so.1 malloc @@ -237,22 +252,25 @@ Usage: hiperf report [option] ``` - 输出采集数据的调用栈报告 + ``` hiperf report -s ``` - 指定符号表路径 + ``` hiperf report -s --symbol-dir /data/local/tmp ``` - 指定结果过滤的关键字,指定后会只显示包含该关键字的信息。比如过滤libutils.z.so则命令如下: + ``` hiperf report --dsos libuitls.z.so ``` - 指定按照特定的关键字进行排序展示,比如按照dso进行排序: + ``` hiperf report --sort dso ``` - diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain.md b/zh-cn/device-dev/subsystems/subsys-toolchain.md index 7e9fb5eb91ec6285a6656c57e243c6e3c1ba0177..95ca46093b747b95083d2d67c39e73010936d990 100644 --- a/zh-cn/device-dev/subsystems/subsys-toolchain.md +++ b/zh-cn/device-dev/subsystems/subsys-toolchain.md @@ -1,9 +1,9 @@ -# 研发工具链 +# 调测工具 -- **[bytrace使用指导](subsys-toolchain-bytrace-guide.md)** -- **[hdc\_std 使用指导](subsys-toolchain-hdc-guide.md)** -- **[hiperf 使用指南](subsys-toolchain-hiperf.md)** +- **[bytrace使用指导](subsys-toolchain-bytrace-guide.md)** +- **[hdc_std 使用指导](subsys-toolchain-hdc-guide.md)** +- **[hiperf 使用指导](subsys-toolchain-hiperf.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-usbservice-guide.md b/zh-cn/device-dev/subsystems/subsys-usbservice-guide.md index 011335204c6f52019e296409c4e6d16137aa72f3..b62be12bf360bdcce24ef621ca349d4d629dad90 100644 --- a/zh-cn/device-dev/subsystems/subsys-usbservice-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-usbservice-guide.md @@ -1,6 +1,5 @@ # USB服务子系统使用指导 -- [使用步骤](#section18816105182315) 下面使用步骤以bulktransfer为例。 diff --git a/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md b/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md index 9475d486a900b330dc65b4da1098146bcee85cb9..25a056b047cdeaca766e365bd6bbc3886281e11d 100644 --- a/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-usbservice-overview.md @@ -1,221 +1,62 @@ -# USB服务子系统概述 +# USB服务概述 -- [概述](#section175431838101617) -- [接口说明](#section83365421647) - - [Host部分](#section83365421658) - - [Device部分](#section83365421669) - - [Port部分](#section83365421670) -## 概述 +## 概述 - USB设备分为Host设备(主机设备)和Device设备(从设备)。用户可通过Port Service来根据实际业务把运行OpenHarmony的设备切换为Host设备或者Device设备。目前在Host模式下,支持获取USB设备列表,USB设备权限管理,控制传输、批量传输的同异步数据传输等,在Device模式下,支持HDC(调试)、ACM(串口)、ECM(网口)等功能的切换。 +USB设备分为Host设备(主机设备)和Device设备(从设备)。用户可通过Port Service来根据实际业务把运行OpenHarmony的设备切换为Host设备或者Device设备。目前在Host模式下,支持获取USB设备列表,USB设备权限管理,控制传输、批量传输的同异步数据传输等,在Device模式下,支持HDC(调试)、ACM(串口)、ECM(网口)等功能的切换。 -**图1** USB服务架构图 + **图1** USB服务架构图 + ![zh-cn_image_0000001267088285](figures/zh-cn_image_0000001267088285.png) -![](figure/USB服务架构图.png) +- USB FWK/API:基于USB Service服务,使用NAPI技术,向上提供JS接口。 -- USB FWK/API:基于USB Service服务,使用NAPI技术,向上提供JS接口。 -- USB Service:使用C++代码实现,包含Host、Device、Port三个模块。基于HDI的接口,主要实现USB设备的列表管理、Function 管理、Port管理、USB设备权限管理等功能。 -- USB HAL:使用C代码实现,基于Host SDK和Device SDK,封装了对USB设备的基本操作,向上提供C++接口,同时通过HDF框架接收内核上报的信息。 +- USB Service:使用C++代码实现,包含Host、Device、Port三个模块。基于HDI的接口,主要实现USB设备的列表管理、Function 管理、Port管理、USB设备权限管理等功能。 -## 接口说明 +- USB HAL:使用C代码实现,基于Host SDK和Device SDK,封装了对USB设备的基本操作,向上提供C++接口,同时通过HDF框架接收内核上报的信息。 -- ### Host部分 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

usb_srv_client.h

-

-

-

int32_t OpenDevice(const UsbDevice &device, USBDevicePipe &pip);

-

打开USB设备,建立连接

-

int32_t HasRight(std::string deviceName);

-

判断是否有权访问设备

-

int32_t RequestRight(std::string deviceName);

-

请求给定软件包的临时权限以访问设备

-

int32_t GetDevices(std::vector &deviceList);

-

获取USB设备列表

-

int32_t ClaimInterface(USBDevicePipe &pip, const UsbInterface &interface, bool force);

-

打开接口,并申明独占接口,必须在数据传输前执行

-

int32_t ReleaseInterface(USBDevicePipe &pip, const UsbInterface &interface);

-

关闭接口,释放接口的占用,在停止数据传输后执行

-

int32_t BulkTransfer(USBDevicePipe &pip, const USBEndpoint &endpoint, std::vector &vdata, int32_t timeout);

-

在给定端点上执行批量数据传输, 返回读取或发送的数据长度,通过端点方向确定读取或发送数据

-

int32_t ControlTransfer(USBDevicePipe &pip, const UsbCtrlTransfer &ctrl, std::vector &vdata);

-

对此设备执行端点零的控制事务,传输方向由请求类型决定

-

int32_t SetConfiguration(USBDevicePipe &pip, const USBConfig &config);

-

设置设备当前使用的配置,通过配置值进行指定

-

int32_t SetInterface(USBDevicePipe &pipe, const UsbInterface &interface);

-

设置指定接口的备选设置,用于在具有相同ID但不同备用设置的两个接口之间进行选择

-

int32_t GetRawDescriptors(std::vector &vdata);

-

获取原始的USB描述符

-

int32_t GetFileDescriptor();

-

获取文件描述符

-

bool Close(const USBDevicePipe &pip);

-

关闭设备,释放与设备相关的所有系统资源

-

int32_t PipeRequestWait(USBDevicePipe &pip, int64_t timeout, UsbRequest &req);

-

获取异步传输结果

-

int32_t RequestInitialize(UsbRequest &request);

-

初始化异步数据传输request

-

int32_t RequestFree(UsbRequest &request);

-

释放异步数据传输request

-
-

int32_t RequestAbort(UsbRequest &request);

-

取消待处理的数据请求

-

int32_t RequestQueue(UsbRequest &request);

-

将指定的端点进行异步数据发送或者接收请求,数据传输方向由端点方向决定

-

int32_t BulkRequstDataSize(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length);

-

异步批量读取数据,传输大量数据时使用

-

int32_t BulkReadData(const UsbDev &dev, const UsbPipe &pipe, std::vector &data);

-

与BulkReadData配合使用,获取读取结果

-

int32_t BulkWriteData(const UsbDev &dev, const UsbPipe &pipe, const std::vector &data);

-

异步批量写数据,传输大量数据时使用

-

int32_t BulkGetWriteCompleteLength(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length);

-

与BulkWriteData配合使用,获取写入状态,由length描述

-
+## 接口说明 -- ### Device部分 +- Host部分 - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

usb_srv_client.h

-

-

-

int32_t GetCurrentFunctions(int32_t &funcs);

-

获取设备模式下的当前USB功能列表的数字组合掩码

-

int32_t SetCurrentFunctions(int32_t funcs);

-

在设备模式下设置当前的USB功能列表

-

int32_t UsbFunctionsFromString(std::string funcs);

-

将给定的功能列表描述字符串转换为功能列表的数字组合掩码

-

std::string UsbFunctionsToString(int32_t funcs);

-

将给定的功能列表的数字组合掩码转换为功能列表描述字符串

-
+ | 头文件 | 接口名称 | 功能描述 | +| -------- | -------- | -------- | +| usb_srv_client.h | int32_t OpenDevice(const UsbDevice &device, USBDevicePipe &pip); | 打开USB设备,建立连接 | +| | int32_t HasRight(std::string deviceName); | 判断是否有权访问设备 | +| | int32_t RequestRight(std::string deviceName); | 请求给定软件包的临时权限以访问设备 | +| | int32_t GetDevices(std::vector &deviceList); | 获取USB设备列表 | +| | int32_t ClaimInterface(USBDevicePipe &pip, const UsbInterface &interface, bool force); | 打开接口,并申明独占接口,必须在数据传输前执行 | +| | int32_t ReleaseInterface(USBDevicePipe &pip, const UsbInterface &interface); | 关闭接口,释放接口的占用,在停止数据传输后执行 | +| | int32_t BulkTransfer(USBDevicePipe &pip, const USBEndpoint &endpoint, std::vector &vdata, int32_t timeout); | 在给定端点上执行批量数据传输, 返回读取或发送的数据长度,通过端点方向确定读取或发送数据 | +| | int32_t ControlTransfer(USBDevicePipe &pip, const UsbCtrlTransfer &ctrl, std::vector &vdata); | 对此设备执行端点零的控制事务,传输方向由请求类型决定 | +| | int32_t SetConfiguration(USBDevicePipe &pip, const USBConfig &config); | 设置设备当前使用的配置,通过配置值进行指定 | +| | int32_t SetInterface(USBDevicePipe &pipe, const UsbInterface &interface); | 设置指定接口的备选设置,用于在具有相同ID但不同备用设置的两个接口之间进行选择 | +| | int32_t GetRawDescriptors(std::vector &vdata); | 获取原始的USB描述符 | +| | int32_t GetFileDescriptor(); | 获取文件描述符 | +| | bool Close(const USBDevicePipe &pip); | 关闭设备,释放与设备相关的所有系统资源 | +| | int32_t PipeRequestWait(USBDevicePipe &pip, int64_t timeout, UsbRequest &req); | 获取异步传输结果 | +| | int32_t RequestInitialize(UsbRequest &request); | 初始化异步数据传输request | +| | int32_t RequestFree(UsbRequest &request); | 释放异步数据传输request | +| | int32_t RequestAbort(UsbRequest &request); | 取消待处理的数据请求 | +| | int32_t RequestQueue(UsbRequest &request); | 将指定的端点进行异步数据发送或者接收请求,数据传输方向由端点方向决定 | +| | int32_t BulkRequstDataSize(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length); | 异步批量读取数据,传输大量数据时使用 | +| | int32_t BulkReadData(const UsbDev &dev, const UsbPipe &pipe, std::vector &data); | 与BulkReadData配合使用,获取读取结果 | +| | int32_t BulkWriteData(const UsbDev &dev, const UsbPipe &pipe, const std::vector &data); | 异步批量写数据,传输大量数据时使用 | +| | int32_t BulkGetWriteCompleteLength(const UsbDev &dev, const UsbPipe &pipe, uint32_t &length); | 与BulkWriteData配合使用,获取写入状态,由length描述 | -- ### Port部分 +- Device部分 - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

usb_srv_client.h

-

-

-

int32_t GetSupportedModes(int32_t portId, int32_t &supportedModes);

-

获取指定的端口支持的模式列表的组合掩码

-

int32_t SetPortRole(int32_t portId, int32_t powerRole, int32_t dataRole);

-

设置指定的端口支持的角色模式,包含充电角色、数据传输角色

-

int32_t GetPorts(std::vector &usbPorts);

-

获取物理USB端口描述信息列表

-
+ | 头文件 | 接口名称 | 功能描述 | +| -------- | -------- | -------- | +| usb_srv_client.h | int32_t GetCurrentFunctions(int32_t &funcs); | 获取设备模式下的当前USB功能列表的数字组合掩码 | +| | int32_t SetCurrentFunctions(int32_t funcs); | 在设备模式下设置当前的USB功能列表 | +| | int32_t UsbFunctionsFromString(std::string funcs); | 将给定的功能列表描述字符串转换为功能列表的数字组合掩码 | +| | std::string UsbFunctionsToString(int32_t funcs); | 将给定的功能列表的数字组合掩码转换为功能列表描述字符串 | + +- Port部分 + + | 头文件 | 接口名称 | 功能描述 | +| -------- | -------- | -------- | +| usb_srv_client.h | int32_t GetSupportedModes(int32_t portId, int32_t &supportedModes); | 获取指定的端口支持的模式列表的组合掩码 | +| | int32_t SetPortRole(int32_t portId, int32_t powerRole, int32_t dataRole); | 设置指定的端口支持的角色模式,包含充电角色、数据传输角色 | +| | int32_t GetPorts(std::vector &usbPorts); | 获取物理USB端口描述信息列表 | diff --git a/zh-cn/device-dev/subsystems/subsys-utils-faqs.md b/zh-cn/device-dev/subsystems/subsys-utils-faqs.md index c3f3e2da63e5426589b7ddafcb5d88921af19ade..1475bd2d1b3dd0a87237b388d4a9fb613ccf6a43 100755 --- a/zh-cn/device-dev/subsystems/subsys-utils-faqs.md +++ b/zh-cn/device-dev/subsystems/subsys-utils-faqs.md @@ -1,12 +1,11 @@ -# 公共基础库常见问题 +# 公共基础库常见问题 -- [1.LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储路径设置错误,导致KV存储运行失败](#section2041345718513) -## 1.LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储路径设置错误,导致KV存储运行失败 +## 1.LiteOS-A内核(Hi3516、Hi3518平台)KV存储路径设置错误,导致KV存储运行失败 **现象描述** -LiteOS-A内核\(Hi3516、Hi3518平台\)直接调用KV存储提供的接口,各参数正常的情况下,编译可执行程序运行失败。 +LiteOS-A内核(Hi3516、Hi3518平台)直接调用KV存储提供的接口,各参数正常的情况下,编译可执行程序运行失败。 **可能原因** @@ -16,7 +15,7 @@ LiteOS-A内核\(Hi3516、Hi3518平台\)直接调用KV存储提供的接口,各 显示调用KV存储的UtilsSetEnv接口,设置数据存储路径。 + ``` UtilsSetEnv("/storage/com.example.kv"); ``` - diff --git a/zh-cn/device-dev/subsystems/subsys-utils-guide.md b/zh-cn/device-dev/subsystems/subsys-utils-guide.md index 0986cbb6a11294806309e5143b68013f5369949e..360e10817e2543713710a2be009d87ee99a296af 100644 --- a/zh-cn/device-dev/subsystems/subsys-utils-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-utils-guide.md @@ -1,73 +1,25 @@ -# 公共基础库开发指导 - -- [接口说明](#section1633115419401) -- [开发步骤](#section17450172710292) - - [LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤:](#section258354119295) - - [Dump系统属性在LiteOS-M内核平台使用指南:](#section9179161863014) - - [Dump系统属性在LiteOS-A内核平台使用指南:](#section3179121853017) - - -## 接口说明 - -**表 1** 文件操作接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int UtilsFileOpen(const char* path, int oflag, int mode)

-

打开或创建文件

-

int UtilsFileClose(int fd)

-

关闭文件

-

int UtilsFileRead(int fd, char *buf, unsigned int len)

-

读取特定长度的文件数据

-

int UtilsFileWrite(int fd, const char *buf, unsigned int len)

-

向文件写入特定大小的数据

-

int UtilsFileDelete(const char *path)

-

删除指定文件

-

int UtilsFileStat(const char *path, unsigned int *fileSize)

-

获取文件大小

-

int UtilsFileSeek(int fd, int offset, unsigned int whence)

-

重新定位文件读/写偏移量

-

int UtilsFileCopy(const char* src, const char* dest)

-

将源文件复制一份并存储到目标文件

-

int UtilsFileMove(const char* src, const char* dest)

-

将源文件移动到指定目标文件

-
+# 公共基础库开发指导 + + +## 接口说明 + + **表1** 文件操作接口说明 + +| 接口名 | 描述 | +| -------- | -------- | +| int UtilsFileOpen(const char\* path, int oflag, int mode) | 打开或创建文件 | +| int UtilsFileClose(int fd) | 关闭文件 | +| int UtilsFileRead(int fd, char \*buf, unsigned int len) | 读取特定长度的文件数据 | +| int UtilsFileWrite(int fd, const char \*buf, unsigned int len) | 向文件写入特定大小的数据 | +| int UtilsFileDelete(const char \*path) | 删除指定文件 | +| int UtilsFileStat(const char \*path, unsigned int \*fileSize) | 获取文件大小 | +| int UtilsFileSeek(int fd, int offset, unsigned int whence) | 重新定位文件读/写偏移量 | +| int UtilsFileCopy(const char\* src, const char\* dest) | 将源文件复制一份并存储到目标文件 | +| int UtilsFileMove(const char\* src, const char\* dest) | 将源文件移动到指定目标文件 | 文件操作使用示例: + ``` // open && write char fileName[] = "testfile"; @@ -97,35 +49,17 @@ ret = UtilsFileDelete(fileName); printf("delete ret = %d\n", ret); ``` -**表 2** KV存储接口说明 - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int UtilsGetValue(const char* key, char* value, unsigned int len)

-

提供给上层应用根据key获取对应数据项

-

int UtilsSetValue(const char* key, const char* value)

-

提供给上层应用用于存储/更新key对应数据项

-

int UtilsDeleteValue(const char* key)

-

提供给上层应用删除key对应数据项

-
+ **表2** KV存储接口说明 + +| 接口名 | 描述 | +| -------- | -------- | +| int UtilsGetValue(const char\* key, char\* value, unsigned int len) | 提供给上层应用根据key获取对应数据项 | +| int UtilsSetValue(const char\* key, const char\* value) | 提供给上层应用用于存储/更新key对应数据项 | +| int UtilsDeleteValue(const char\* key) | 提供给上层应用删除key对应数据项 | KV存储使用示例: + ``` // set char key[] = "rw.sys.version_100"; @@ -143,154 +77,153 @@ ret = UtilsDeleteValue(key); printf("UtilsDeleteValue delete ret = %d\n", ret); ``` - - - -
-## 开发步骤 -### LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤: +## 开发步骤 -1. 基于AbilityKit开发KV存储的native应用。 - - 基于KV存储提供的接口编写用户程序,并编译出so(libLauncher.so)文件。 - ``` - // set - char key[] = "rw.sys.version_100"; - char value[] = "Hello kv operation implement!"; - int ret = UtilsSetValue(key, value); - printf("UtilsSetValue set ret = %d\n", ret); - - // get - char temp[128] = {0}; - ret = UtilsGetValue(key, temp, 128); - printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); - - // delete - ret = UtilsDeleteValue(key); - printf("UtilsDeleteValue delete ret = %d\n", ret); - ``` - - - 编写config.json文件,内容如下: - - ``` - { - "app": { - "bundleName": "com.example.launcher", - "vendor": "example", - "version": { - "code": 1, - "name": "1.0" - } - }, - "deviceConfig": { - "default": { - "reqSdk": { - "compatible": "zsdk 1.0.0", - "target": "zsdk 1.0.1" - }, - "keepAlive": false - }, - "smartCamera": { - "reqSdk": { - "compatible": "zsdk 1.0.0", - "target": "zsdk 1.0.1" - }, - "keepAlive": false - } - }, - "module": { - "package": "com.example.launcher", - "name": ".MyHarmonyAbilityPackage", - "deviceType": [ - "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera" - ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "Launcher", - "moduleType": "entry" - }, - "abilities": [{ - "name": "MainAbility", - "icon": "res/drawable/phone.png", - "label": "test app 1", - "launchType": "standard", - "type": "page" - }, - { - "name": "SecondAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "page" - }, - { - "name": "ServiceAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "service" - } - ] - } - } - ``` - - - 生成hap包。 - - - 按照如下目录结构存放文件,res/drawable下面放置资源文件: - - ![](figure/unnaming.png) - - - 将上述文件打包生成zip包,修改后缀为.hap,例如Launcher.hap - -2. 连接单板,通过串口向单板发送安装KV存储native应用的命令。 - - ``` - ./nfs/dev_tools/bin/bm install -p /nfs/Launcher.hap - ``` - -3. 通过串口向单板发送运行KV存储native应用的命令。 - - ``` - ./nfs/dev_tools/bin/aa start -p com.example.launcher -n ServiceAbility - ``` - - -### Dump系统属性在LiteOS-M内核平台使用指南: - -1. 连接单板,通过串口向单板发送AT+SYSPARA命令。 - - ``` - AT+SYSPARA - ``` - - **图 1** LiteOS-M平台dump系统属性输出 - ![](figure/LiteOS-M平台dump系统属性输出.png "LiteOS-M平台dump系统属性输出") - - -### Dump系统属性在LiteOS-A内核平台使用指南: - -1. 连接单板,运行bin路径下的os\_dump加参数--help,查看os\_dump使用指导。 - - ``` - ./bin/os_dump --help - ``` - -2. os\_dump加参数-l,查看当前系统有哪些模块支持获取属性。 - - ``` - ./bin/os_dump -l - ``` - -3. os\_dump加参数syspara,查看当前系统属性 - - ``` - ./bin/os_dump syspara - ``` - - **图 2** LiteOS-A平台dump系统属性输出 - ![](figure/LiteOS-A平台dump系统属性输出.png "LiteOS-A平台dump系统属性输出") +### LiteOS-A内核(Hi3516、Hi3518平台)KV存储的native应用开发: +1. 基于AbilityKit开发KV存储的native应用。 + - 基于KV存储提供的接口编写用户程序,并编译出so(libLauncher.so)文件。 + + ``` + // set + char key[] = "rw.sys.version_100"; + char value[] = "Hello kv operation implement!"; + int ret = UtilsSetValue(key, value); + printf("UtilsSetValue set ret = %d\n", ret); + + // get + char temp[128] = {0}; + ret = UtilsGetValue(key, temp, 128); + printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); + + // delete + ret = UtilsDeleteValue(key); + printf("UtilsDeleteValue delete ret = %d\n", ret); + ``` + - 编写config.json文件,内容如下: + + ``` + { + "app": { + "bundleName": "com.example.launcher", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + } + }, + "deviceConfig": { + "default": { + "reqSdk": { + "compatible": "zsdk 1.0.0", + "target": "zsdk 1.0.1" + }, + "keepAlive": false + }, + "smartCamera": { + "reqSdk": { + "compatible": "zsdk 1.0.0", + "target": "zsdk 1.0.1" + }, + "keepAlive": false + } + }, + "module": { + "package": "com.example.launcher", + "name": ".MyOpenHarmonyAbilityPackage", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "Launcher", + "moduleType": "entry" + }, + "abilities": [{ + "name": "MainAbility", + "icon": "res/drawable/phone.png", + "label": "test app 1", + "launchType": "standard", + "type": "page" + }, + { + "name": "SecondAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "page" + }, + { + "name": "ServiceAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "service" + } + ] + } + } + ``` + + - 生成hap包。 + - 按照如下目录结构存放文件,res/drawable下面放置资源文件: + + **图1** 资源文件路径图 + + ![zh-cn_image_0000001154153558](figures/zh-cn_image_0000001154153558.png) + + - 将上述文件打包生成zip包,修改后缀为.hap,例如Launcher.hap + +2. 连接单板,通过串口向单板发送安装KV存储native应用的命令。 + + ``` + ./nfs/dev_tools/bin/bm install -p /nfs/Launcher.hap + ``` + +3. 通过串口向单板发送运行KV存储native应用的命令。 + + ``` + ./nfs/dev_tools/bin/aa start -p com.example.launcher -n ServiceAbility + ``` + + +### Dump系统属性在LiteOS-M内核平台使用: + +1. 连接单板,通过串口向单板发送AT+SYSPARA命令。 + + ``` + AT+SYSPARA + ``` + + **图2** LiteOS-M平台dump系统属性输出 + + ![zh-cn_image_0000001115123966](figures/zh-cn_image_0000001115123966.png) + + +### Dump系统属性在LiteOS-A内核平台使用: + +1. 连接单板,运行bin路径下的os_dump加参数--help,查看os_dump使用指导。 + + ``` + ./bin/os_dump --help + ``` + +2. os_dump加参数-l,查看当前系统有哪些模块支持获取属性。 + + ``` + ./bin/os_dump -l + ``` + +3. os_dump加参数syspara,查看当前系统属性。 + + ``` + ./bin/os_dump syspara + ``` + + **图3** LiteOS-A平台dump系统属性输出 + + ![zh-cn_image_0000001197369959](figures/zh-cn_image_0000001197369959.png) diff --git a/zh-cn/device-dev/subsystems/subsys-utils-overview.md b/zh-cn/device-dev/subsystems/subsys-utils-overview.md index 9627ac392e4a5bdd3271116b8bbb01e53587d903..19b55ac3013f9da04b7cd1079e6060e9ab6fc8de 100755 --- a/zh-cn/device-dev/subsystems/subsys-utils-overview.md +++ b/zh-cn/device-dev/subsystems/subsys-utils-overview.md @@ -1,10 +1,13 @@ -# 公共基础库概述 +# 公共基础库概述 + 公共基础库存放OpenHarmony通用的基础组件。这些基础组件可被OpenHarmony各业务子系统及上层应用所使用。 + 公共基础库在不同平台上提供的能力: -LiteOS-M内核\(Hi3861平台\):KV存储、文件操作、IoT外设控制、Dump系统属性。 -LiteOS-A内核\(Hi3516、Hi3518平台\):KV存储、定时器、数据和文件存储的JS API、Dump系统属性。 +LiteOS-M内核(Hi3861平台):KV存储、文件操作、IoT外设控制、Dump系统属性。 + +LiteOS-A内核(Hi3516、Hi3518平台):KV存储、定时器、数据和文件存储的JS API、Dump系统属性。 diff --git a/zh-cn/device-dev/subsystems/subsys-utils.md b/zh-cn/device-dev/subsystems/subsys-utils.md index 28a5d910c2862796d71aba1463dda945b1a5e64f..9477b181eecf59e5f773e9726f42e46faeca1987 100644 --- a/zh-cn/device-dev/subsystems/subsys-utils.md +++ b/zh-cn/device-dev/subsystems/subsys-utils.md @@ -1,9 +1,9 @@ -# 公共基础 +# 公共基础 -- **[公共基础库概述](subsys-utils-overview.md)** -- **[公共基础库开发指导](subsys-utils-guide.md)** -- **[公共基础库常见问题](subsys-utils-faqs.md)** +- **[公共基础库概述](subsys-utils-overview.md)** +- **[公共基础库开发指导](subsys-utils-guide.md)** +- **[公共基础库常见问题](subsys-utils-faqs.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-xts-guide.md b/zh-cn/device-dev/subsystems/subsys-xts-guide.md index 98e6b2275f30e2ae523b847411beb5ec9017ab42..c2af0f4bc85c4c86c693a02006f7b952d69f6b19 100644 --- a/zh-cn/device-dev/subsystems/subsys-xts-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-xts-guide.md @@ -1,33 +1,34 @@ -# XTS测评用例开发指导 +# XTS测评用例开发指导 -## 简介 + +## 简介 XTS子系统是OpenHarmony兼容性测评套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套件,后续会拓展dcts(device compatibility test suite)设备兼容性测试套件等。 XTS子系统当前包括acts与tools软件包: -- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -- tools,存放acts相关测试用例开发框架。 - -## 系统类型 +- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -OpenHarmony支持如下几种系统类型: +- tools,存放acts相关测试用例开发框架。 -- 轻量系统(mini system) - 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,支持的设备最小内存为128KiB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 +## 系统类型 -- 小型系统(small system) +支持如下几种系统类型: - 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为1MiB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 +- 轻量系统(mini system) + 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,支持的设备最小内存为128KiB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 -- 标准系统(standard system) +- 小型系统(small system) + 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为1MiB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 - 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为128MiB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 +- 标准系统(standard system) + 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为128MiB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 -## 目录 +## 目录 + ``` /test/xts ├── acts # 测试代码存放目录 @@ -39,304 +40,164 @@ OpenHarmony支持如下几种系统类型: └── tools # 测试工具代码存放目录 ``` -## 约束 - -轻量系统用例开发语言是C,小型系统用例开发语言是C++。 - -## 使用说明 - -**表 1** 用例级别说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

级别名称

-

基本定义

-

测试范围

-

Level0

-

冒烟

-

验证关键功能点基本功能/最基本DFX属性在最常见输入下的表现,通过表示功能基本可运行。

-

Level1

-

基本

-

验证各功能点基本功能/基本DFX属性在常见输入下的表现,通过表示功能基本可测试。

-

Level2

-

重要

-

验证各功能点的基本功能/基本DFX属性在常规输入/常见异常情况下的表现,通过表示功能基本正常可用,可开展Beta。

-

Level3

-

一般

-

验证各功能点的全部功能/全部DFX属性在各种常规/非常规输入组合下,或各种正常/异常预置条件组合下的表现。

-

Level4

-

生僻

-

验证关键功能点在极端异常预置条件下、用户难以触及的异常输入组合下的表现。

-
- -**表 2** 用例粒度说明 - - - - - - - - - - - - - - - - - - - - -

用例规模

-

被测试对象

-

测试环境

-

LargeTest

-

业务功能/全场景特性/整机及场景级DFX

-

尽量使用贴近真实的环境设备

-

MediumTest

-

模块/子系统集成至设备后的功能/DFX

-

使用真实的单设备进行验证,可进行消息模拟,尽量不对函数进行MOCK

-

SmallTest

-

模块/类/函数

-

在开发者个人环境进行测试,尽量不依赖其他模块,存在大量的MOCK

-
- -**表 3** 测试类型说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

测试类型名称

-

测试类型定义

-

Function

-

验证被测对象提供给用户的业务功能实现正确性的测试项,这里的“用户”可以是终端用户或开发者,功能包括业务功能及平台功能

-

Performance

-

验证被测对象在特定预置条件/负载模型下的处理能力的测试项,“处理能力”一般以单位时间内可处理的业务量来衡量,如呼叫/秒,帧率/秒,事件处理量/秒等

-

Power

-

验证被测对象在特定预置条件/负载模型下在一定时间内能源消耗量的测试项

-

Reliability

-

验证被测对象在正常/异常输入情况下,或业务量压力和长时间连续运行压力情况下业务表现的测试项,含稳定性、压力、故障注入、Monkey测试项

-

Security

-

验证系统对恶意威胁的防护能力,威胁包括但不限于未授权访问、使用、泄露、破坏、修改、毁灭,以保障信息的机密性、完整性和可用性; 验证系统对用户隐私的保护能力,保障用户的隐私数据被收集、使用、保有、披露和处置符合法律规范,保障用户的隐私权; 验证对各类安全规范的遵从情况,如安全设计规范、安全红线、工信部安全认证规范等,保障安全相关法律法规的合规。

-

Global

-

验证被测对象在是否具有国际化数据支持和本地化能力的测试项,包括语言显示、输入/输出习惯、时间显示、区域特性如货币时间禁忌等等

-

Compatibility

-

当被测对象为应用时,包括被测对象对于自身数据的后向兼容性、对于系统的前后向兼容性、对于不同用户数据(如播放器之音频文件格式/智能短信之用户短信内容)的兼容性测试项; 当被测对象为系统时,包括被测系统对于系统自身数据的后向兼容性、以及对于生态中常用应用的兼容性测试项;当被测对象为软件时,包括被测系统对于相关的硬件的兼容性;

-

User

-

验证被测对象在真实用户场景下的用户体验感受的测试项,注意此种情况下没有客观的“正确”与“失败”,所有的结论及评价都应该来自于用户

-

Standard

-

验证被测对象对于行业及公司内标准/协议/规范的遵从情况的测试项,注意此处的“标准”不包含任何安全标准,针对安全标准的测试项划归为“安全测试”类型

-

Safety

-

验证被测对象的Safety属性,避免产品可能对人身安全、健康以及产品本身带来的危害。

-

Resilience

-

验证被测对象的韧性属性,确保系统受攻击时承受并保持在有定义的运行状态(包括降级)、恢复并适应攻击以保障Mission达成。

-
- -## 用例开发指导 - -根据测试系统选择测试框架和对应测试用例语言。 - -**表 4** 系统和测试框架、开发语言对应关系 - - - - - - - - - - - - - - - - - - - - -

系统

-

测试框架

-

语言

-

轻量系统

-

hctest

-

c

-

小型系统

-

hcpptest

-

c++

-

标准系统

-

HJSUnit、hcpptest

-

js、c++

-
- -### C语言用例开发编译指导(适用于轻量系统产品用例开发) - -**示例:轻量系统测试用例开发** - -当前使用的测试框架是hctest,hctest测试框架支持使用C语言编写测试用例,是在开源测试框架unity的基础上进行增强和适配。 - -1. 用例目录规范:测试用例存储到test/xts/acts仓中 - - ``` - ├── acts - │ └──subsystem_lite - │ │ └── module_hal - │ │ │ └── BUILD.gn - │ │ │ └── src - │ └──build_lite - │ │ └── BUILD.gn - ``` - -2. src目录下用例编写样例。 - - 1.引用测试框架 - - ``` - #include "hctest.h" - ``` - - 2. 使用宏定义LITE\_TEST\_SUIT定义子系统、模块、测试套件名称 - - ``` - /** - * @brief register a test suit named "IntTestSuite" - * @param test subsystem name - * @param example module name - * @param IntTestSuite test suit name - */ - LITE_TEST_SUIT(test, example, IntTestSuite); - ``` - 3. 定义Setup与TearDown +## 约束 - 命名方式:测试套件名称+Setup,测试套件名称+TearDown。 +轻量系统用例开发语言是C,小型系统用例开发语言是C++。 - Setup与TearDown必须存在,可以为空函数。 - 4. 使用宏定义LITE\_TEST\_CASE写测试用例 +## 使用说明 - 包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + **表1** 用例级别说明 - ``` - LITE_TEST_CASE(IntTestSuite, TestCase001, Function | MediumTest | Level1) - { - //do something - }; - ``` +| 级别名称 | 基本定义 | 测试范围 | +| -------- | -------- | -------- | +| Level0 | 冒烟 | 验证关键功能点基本功能/最基本DFX属性在最常见输入下的表现,通过表示功能基本可运行。 | +| Level1 | 基本 | 验证各功能点基本功能/基本DFX属性在常见输入下的表现,通过表示功能基本可测试。 | +| Level2 | 重要 | 验证各功能点的基本功能/基本DFX属性在常规输入/常见异常情况下的表现,通过表示功能基本正常可用,可开展Beta。 | +| Level3 | 一般 | 验证各功能点的全部功能/全部DFX属性在各种常规/非常规输入组合下,或各种正常/异常预置条件组合下的表现。 | +| Level4 | 生僻 | 验证关键功能点在极端异常预置条件下、用户难以触及的异常输入组合下的表现。 | - 5. 使用宏定义 RUN\_TEST\_SUITE注册测试套件 + **表2** 用例粒度说明 - ``` - RUN_TEST_SUITE(IntTestSuite); - ``` +| 用例规模 | 被测试对象 | 测试环境 | +| -------- | -------- | -------- | +| LargeTest | 业务功能/全场景特性/整机及场景级DFX | 尽量使用贴近真实的环境设备 | +| MediumTest | 模块/子系统集成至设备后的功能/DFX | 使用真实的单设备进行验证,可进行消息模拟,尽量不对函数进行MOCK | +| SmallTest | 模块/类/函数 | 在开发者个人环境进行测试,尽量不依赖其他模块,存在大量的MOCK | -3. 测试模块的配置文件(BUILD.gn)样例: + **表3** 测试类型说明 - 在每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后静态库的名称、依赖的头文件、依赖的库等;具体写法如下: +| 测试类型名称 | 测试类型定义 | +| -------- | -------- | +| Function | 验证被测对象提供给用户的业务功能实现正确性的测试项,这里的“用户”可以是终端用户或开发者,功能包括业务功能及平台功能 | +| Performance | 验证被测对象在特定预置条件/负载模型下的处理能力的测试项,“处理能力”一般以单位时间内可处理的业务量来衡量,如呼叫/秒,帧率/秒,事件处理量/秒等 | +| Power | 验证被测对象在特定预置条件/负载模型下在一定时间内能源消耗量的测试项 | +| Reliability | 验证被测对象在正常/异常输入情况下,或业务量压力和长时间连续运行压力情况下业务表现的测试项,含稳定性、压力、故障注入、Monkey测试项 | +| Security | 验证系统对恶意威胁的防护能力,威胁包括但不限于未授权访问、使用、泄露、破坏、修改、毁灭,以保障信息的机密性、完整性和可用性; 验证系统对用户隐私的保护能力,保障用户的隐私数据被收集、使用、保有、披露和处置符合法律规范,保障用户的隐私权; 验证对各类安全规范的遵从情况,如安全设计规范、安全红线、工信部安全认证规范等,保障安全相关法律法规的合规。 | +| Global | 验证被测对象在是否具有国际化数据支持和本地化能力的测试项,包括语言显示、输入/输出习惯、时间显示、区域特性如货币时间禁忌等等 | +| Compatibility | 当被测对象为应用时,包括被测对象对于自身数据的后向兼容性、对于系统的前后向兼容性、对于不同用户数据(如播放器之音频文件格式/智能短信之用户短信内容)的兼容性测试项; 当被测对象为系统时,包括被测系统对于系统自身数据的后向兼容性、以及对于生态中常用应用的兼容性测试项;当被测对象为软件时,包括被测系统对于相关的硬件的兼容性; | +| User | 验证被测对象在真实用户场景下的用户体验感受的测试项,注意此种情况下没有客观的“正确”与“失败”,所有的结论及评价都应该来自于用户 | +| Standard | 验证被测对象对于行业及公司内标准/协议/规范的遵从情况的测试项,注意此处的“标准”不包含任何安全标准,针对安全标准的测试项划归为“安全测试”类型 | +| Safety | 验证被测对象的Safety属性,避免产品可能对人身安全、健康以及产品本身带来的危害。 | +| Resilience | 验证被测对象的韧性属性,确保系统受攻击时承受并保持在有定义的运行状态(包括降级)、恢复并适应攻击以保障Mission达成。 | - ``` - import("//test/xts/tools/lite/build/suite_lite.gni") - hctest_suite("ActsDemoTest") { - suite_name = "acts" - sources = [ - "src/test_demo.c", - ] - include_dirs = [ ] - cflags = [ "-Wno-error" ] - } - ``` -4. acts下BUILD.gn增加编译选项。 +## 用例开发指导 - 需要将测试模块加入到acts目录下的编译脚本中,编译脚本路径:test/xts/acts/build\_lite/BUILD.gn。 +根据测试系统选择测试框架和对应测试用例语言。 - ``` - lite_component("acts") { - ... - if(board_name == "liteos_m") { - features += [ - ... - "//xts/acts/subsystem_lite/module_hal:ActsDemoTest" - ] - } - } - ``` + **表4** 系统和测试框架、开发语言对应关系 -5. 测试套件编译命令。 +| 系统 | 测试框架 | 语言 | +| -------- | -------- | -------- | +| 轻量系统 | hctest | c | +| 小型系统 | hcpptest | c++ | +| 标准系统 | HJSUnit、hcpptest | js、c++ | - 随版本编译,debug版本编译时会同步编译acts测试套件 +### C语言用例开发编译指导(适用于轻量系统产品用例开发) - >![](../public_sys-resources/icon-note.gif) **说明:** - >acts测试套件编译中间件为静态库,最终链接到版本镜像中 。 +**示例:轻量系统测试用例开发** +当前使用的测试框架是hctest,hctest测试框架支持使用C语言编写测试用例,是在开源测试框架unity的基础上进行增强和适配。 -### C语言用例执行指导(适用于轻量系统产品用例开发) +1. 用例目录规范:测试用例存储到test/xts/acts仓中 + + ``` + ├── acts + │ └──subsystem_lite + │ │ └── module_hal + │ │ │ └── BUILD.gn + │ │ │ └── src + │ └──build_lite + │ │ └── BUILD.gn + ``` + +2. src目录下用例编写样例。 + 1.引用测试框架 + + + ``` + #include "hctest.h" + ``` + + 2. 使用宏定义LITE_TEST_SUIT定义子系统、模块、测试套件名称 + + + ``` + /** + * @brief register a test suite named "IntTestSuite" + * @param test subsystem name + * @param example module name + * @param IntTestSuite test suite name + */ + LITE_TEST_SUIT(test, example, IntTestSuite); + ``` + + 3. 定义Setup与TearDown + + 命名方式:测试套件名称+Setup,测试套件名称+TearDown。 + + Setup与TearDown必须存在,可以为空函数。 + + 4. 使用宏定义LITE_TEST_CASE写测试用例 + + 包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + + + ``` + LITE_TEST_CASE(IntTestSuite, TestCase001, Function | MediumTest | Level1) + { + //do something + }; + ``` + + 5. 使用宏定义 RUN_TEST_SUITE注册测试套件 + + + ``` + RUN_TEST_SUITE(IntTestSuite); + ``` + +3. 测试模块的配置文件(BUILD.gn)样例: + 在每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后静态库的名称、依赖的头文件、依赖的库等;具体写法如下: + + + ``` + import("//test/xts/tools/lite/build/suite_lite.gni") + hctest_suite("ActsDemoTest") { + suite_name = "acts" + sources = [ + "src/test_demo.c", + ] + include_dirs = [ ] + cflags = [ "-Wno-error" ] + } + ``` + +4. acts下BUILD.gn增加编译选项。 + 需要将测试模块加入到acts目录下的编译脚本中,编译脚本路径:test/xts/acts/build_lite/BUILD.gn。 + + + ``` + lite_component("acts") { + ... + if(board_name == "liteos_m") { + features += [ + ... + "//xts/acts/subsystem_lite/module_hal:ActsDemoTest" + ] + } + } + ``` + +5. 测试套件编译命令。 + 随版本编译,debug版本编译时会同步编译acts测试套件。 + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > acts测试套件编译中间件为静态库,最终链接到版本镜像中 。 + +### C语言用例执行指导(适用于轻量系统产品用例开发) **示例:轻量系统测试用例执行** @@ -344,8 +205,9 @@ OpenHarmony支持如下几种系统类型: **测试步骤** -1. 使用串口工具登录开发板,并保存串口打印信息。 -2. 重启设备,查看串口日志。 +1. 使用串口工具登录开发板,并保存串口打印信息。 + +2. 重启设备,查看串口日志。 **测试结果分析指导** @@ -353,123 +215,124 @@ OpenHarmony支持如下几种系统类型: 每个测试套件执行以Start to run test suite开始,以xx Tests xx Failures xx Ignored结束。 -### C++语言用例开发编译指导(适用于小型系统、标准系统用例开发) -**示例:小型系统测试用例开发**(标准参考具体样例目录:global/i18n\_standard) +### C++语言用例开发编译指导(适用于小型系统、标准系统用例开发) + +**示例:小型系统测试用例开发**(标准参考具体样例目录:global/i18n_standard) 当前使用的测试框架是hcpptest,hcpptest测试框架是在开源的googletest测试框架的基础上进行的增强和适配。 -1. 规范用例目录:测试用例存储到test/xts/acts仓中。 - - ``` - ├── acts - │ └──subsystem_lite - │ │ └── module_posix - │ │ │ └── BUILD.gn - │ │ │ └── src - │ └──build_lite - │ │ └── BUILD.gn - ``` - -2. 测试模块src下用例编写样例: - - 1. 引用测试框架: - - 需要引用gtest.h 如:\#include "gtest/gtest.h" - - ``` - #include "gtest/gtest.h" - ``` - - 2. 定义Setup与TearDown - - ``` - using namespace std; - using namespace testing::ext; - class TestSuite: public testing::Test { - protected: - // Preset action of the test suite, which is executed before the first test case - static void SetUpTestCase(void){ - } - // Test suite cleanup action, which is executed after the last test case - static void TearDownTestCase(void){ - } - // Preset action of the test case - virtual void SetUp() - { - } - // Cleanup action of the test case - virtual void TearDown() - { - } - }; - ``` - - 3. 使用宏定义HWTEST或HWTEST\_F写测试用例 - - 普通测试用例的定义:HWTEST(测试套名称, 测试用例名称, 用例标注)。 - - 包含SetUp和TearDown的测试用例的定义 :HWTEST\_F(测试套名称, 测试用例名称,用例标注)。 - - 宏定义包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 - - ``` - HWTEST_F(TestSuite, TestCase_0001, Function | MediumTest | Level1) { - // do something - } - ``` - -3. 测试模块下用例配置文件(BUILD.gn)样例: - - 每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后可执行文件的名称、依赖的头文件、依赖的库等;具体写法如下。每个测试模块将独立编译成.bin可执行文件, 该文件可直接push到单板上进行测试。 - - 举例: - - ``` - import("//test/xts/tools/lite/build/suite_lite.gni") - hcpptest_suite("ActsDemoTest") { - suite_name = "acts" - sources = [ - "src/TestDemo.cpp" - ] - - include_dirs = [ - "src", - ... - ] - deps = [ - ... - ] - cflags = [ "-Wno-error" ] - } - - ``` - -4. acts目录下增加编译选项(BUILD.gn)样例: - - 将测试模块加入到acts目录下的编译脚本中,编译脚本为:test/xts/acts/build\_lite/BUILD.gn。 - - ``` - lite_component("acts") { - ... - else if(board_name == "liteos_a") { - features += [ - ... - "//xts/acts/subsystem_lite/module_posix:ActsDemoTest" - ] - } - } - ``` - -5. 测试套件编译命令。 - - 随版本编译,debug版本编译时会同步编译acts测试套件 - - >![](../public_sys-resources/icon-note.gif) **说明:** - >小型系统acts独立编译成可执行文件(bin格式), 在编译产物的suites\\acts目录下归档。 - - -### C++语言用例执行指导(适用于小型系统、标准系统用例开发) +1. 规范用例目录:测试用例存储到test/xts/acts仓中。 + + ``` + ├── acts + │ └──subsystem_lite + │ │ └── module_posix + │ │ │ └── BUILD.gn + │ │ │ └── src + │ └──build_lite + │ │ └── BUILD.gn + ``` + +2. 测试模块src下用例编写样例: + 1. 引用测试框架: + + 需要引用gtest.h 如:\#include "gtest/gtest.h" + + + ``` + #include "gtest/gtest.h" + ``` + + 2. 定义Setup与TearDown + + + ``` + using namespace std; + using namespace testing::ext; + class TestSuite: public testing::Test { + protected: + // Preset action of the test suite, which is executed before the first test case + static void SetUpTestCase(void){ + } + // Test suite cleanup action, which is executed after the last test case + static void TearDownTestCase(void){ + } + // Preset action of the test case + virtual void SetUp() + { + } + // Cleanup action of the test case + virtual void TearDown() + { + } + }; + ``` + + 3. 使用宏定义HWTEST或HWTEST_F写测试用例 + + 普通测试用例的定义:HWTEST(测试套名称, 测试用例名称, 用例标注)。 + + 包含SetUp和TearDown的测试用例的定义 :HWTEST_F(测试套名称, 测试用例名称,用例标注)。 + + 宏定义包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + + + ``` + HWTEST_F(TestSuite, TestCase_0001, Function | MediumTest | Level1) { + // do something + } + ``` + +3. 测试模块下用例配置文件(BUILD.gn)样例: + 每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后可执行文件的名称、依赖的头文件、依赖的库等;具体写法如下。每个测试模块将独立编译成.bin可执行文件, 该文件可直接push到单板上进行测试。 + + 举例: + + + ``` + import("//test/xts/tools/lite/build/suite_lite.gni") + hcpptest_suite("ActsDemoTest") { + suite_name = "acts" + sources = [ + "src/TestDemo.cpp" + ] + + include_dirs = [ + "src", + ... + ] + deps = [ + ... + ] + cflags = [ "-Wno-error" ] + } + + ``` + +4. acts目录下增加编译选项(BUILD.gn)样例: + 将测试模块加入到acts目录下的编译脚本中,编译脚本为:test/xts/acts/build_lite/BUILD.gn。 + + + ``` + lite_component("acts") { + ... + else if(board_name == "liteos_a") { + features += [ + ... + "//xts/acts/subsystem_lite/module_posix:ActsDemoTest" + ] + } + } + ``` + +5. 测试套件编译命令。 + 随版本编译,debug版本编译时会同步编译acts测试套件 + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > 小型系统acts独立编译成可执行文件(bin格式), 在编译产物的suites\acts目录下归档。 + + +### C++语言用例执行指导(适用于小型系统、标准系统用例开发) **示例:小型系统测试用例执行** @@ -477,25 +340,26 @@ OpenHarmony支持如下几种系统类型: **环境搭建** -1. 使用有限网线或无线将开发板与PC进行连接。 -2. 开发板配置IP、子网掩码、网关,确保开发板与PC处于同一个网段。 -3. PC安装nfs服务器并完成注册,启动nfs服务。 -4. 开发板配置mount命令,确保开发板可以访问PC端的nfs共享文件。 +1. 使用有限网线或无线将开发板与PC进行连接。 - 格式:mount \[nfs服务器IP\]:\[/nfs共享目录\] \[/开发板目录\] nfs +2. 开发板配置IP、子网掩码、网关,确保开发板与PC处于同一个网段。 - 举例: +3. PC安装nfs服务器并完成注册,启动nfs服务。 - ``` - mount 192.168.1.10:/nfs /nfs nfs - ``` +4. 开发板配置mount命令,确保开发板可以访问PC端的nfs共享文件。 + 格式:mount [nfs服务器IP]:[/nfs共享目录] [/开发板目录] nfs + 举例: + + ``` + mount 192.168.1.10:/nfs /nfs nfs + ``` **用例执行** 测试套件执行 ActsDemoTest.bin 触发用例执行,基于串口打印日志进行分析。 -### JS语言用例开发指导(适用于标准系统) +### JS语言用例开发指导(适用于标准系统) 当前使用的测试框架是HJSUnit,用于支撑OpenHarmony application测试(特指基于JS应用框架使用 Javascript 语言开发的 APP)进行自动化测试。 @@ -503,158 +367,108 @@ OpenHarmony支持如下几种系统类型: 测试用例为 js 语言,必须满足 JavaScript 语言编程规范: -**表 5** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

用例语法

-

描述

-

要求

-

beforeAll

-

测试套级别的预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数

-

可选

-

afterAll

-

测试套级别的清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数

-

可选

-

beforeEach

-

测试用例级别的预置条件,在每条测试用例开始前执行,执行次数与 it 定义的测试用例数一致,支持一个参数:预置动作函数

-

可选

-

afterEach

-

测试用例级别的清理条件,在每条测试用例结束后执行,执行次数与 it 定义的测试用例数一致,支持一个参数:清理动作函数

-

可选

-

describe

-

定义一个测试套,支持两个参数:测试套名称和测试套函数; describe 支持嵌套,每个 describe 内均可以定义 beforeAll 、beforeEach 、afterEach 和 afterAll

-

必选

-

it

-

定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数

-

备注:

-

过滤参数:过滤参数为一个 32 位的 Int 类型参数,0 位 置1表示不筛选、默认执行;0-10 位 置1表示测试用例类型;16-18 位 置1表示测试用例规模;24-28 位 置1表示测试层级

-

测试用例类型。置位0-10分别表示:FUNCTION 方法类测试、PERFORMANCE 性能类测试、POWER 功耗类测试、RELIABILITY 可靠性测试、SECURITY 安全合规测试、GLOBAL 整体性测试、COMPATIBILITY 兼容性测试、USER 用户测试、STANDARD 标准测试、SAFETY 安全特性测试,RESILIENCE 压力测试。

-

测试用例规模。置位16-18分别表示:SMALL 小型测试、MEDIUM 中型测试、LARGE 大型测试。

-

测试层级。置位24-28分别表示:LEVEL0-0 级测试、LEVEL1-1 级测试、LEVEL2-2 级测试、LEVEL3-3 级测试、LEVEL4-4 级测试。

-

必选

-
+ **表7** 用例编写基础语法 + +| 用例语法 | 描述 | 要求 | +| -------- | -------- | -------- | +| beforeAll | 测试套级别的预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 | 可选 | +| afterAll | 测试套级别的清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 | 可选 | +| beforeEach | 测试用例级别的预置条件,在每条测试用例开始前执行,执行次数与 it 定义的测试用例数一致,支持一个参数:预置动作函数 | 可选 | +| afterEach | 测试用例级别的清理条件,在每条测试用例结束后执行,执行次数与 it 定义的测试用例数一致,支持一个参数:清理动作函数 | 可选 | +| describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数; describe 支持嵌套,每个 describe 内均可以定义 beforeAll 、beforeEach 、afterEach 和 afterAll | 必选 | +| it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数
备注:
**过滤参数**:过滤参数为一个 32 位的 Int 类型参数,0 位 置1表示不筛选、默认执行;0-10 位 置1表示测试用例类型;16-18 位 置1表示测试用例规模;24-28 位 置1表示测试层级。
**测试用例类型**:置位0-10分别表示:FUNCTION 方法类测试、PERFORMANCE 性能类测试、POWER 功耗类测试、RELIABILITY 可靠性测试、SECURITY 安全合规测试、GLOBAL 整体性测试、COMPATIBILITY 兼容性测试、USER 用户测试、STANDARD 标准测试、SAFETY 安全特性测试,RESILIENCE 压力测试。
**测试用例规模**:置位16-18分别表示:SMALL 小型测试、MEDIUM 中型测试、LARGE 大型测试。
**测试层级**:置位24-28分别表示:LEVEL0-0 级测试、LEVEL1-1 级测试、LEVEL2-2 级测试、LEVEL3-3 级测试、LEVEL4-4 级测试。 | 必选 | 用例编写语法采用 jasmine 的标准语法,格式支持ES6格式。 -1. 规范用例目录:测试用例存储到entry/src/main/js/test目录。 - - ``` - ├── BUILD.gn - │ └──entry - │ │ └──src - │ │ │ └──main - │ │ │ │ └──js - │ │ │ │ │ └──default - │ │ │ │ │ │ └──pages - │ │ │ │ │ │ │ └──index - │ │ │ │ │ │ │ │ └──index.js # 入口文件 - │ │ │ │ │ └──test # 测试代码存放目录 - │ │ │ └── resources # hap资源存放目录 - │ │ │ └── config.json # hap配置文件 - ``` - -2. index.js示例 - - ``` - // 拉起js测试框架,加载测试用例 - import {Core, ExpectExtend} from 'deccjsunit/index' - - export default { - data: { - title: "" - }, - onInit() { - this.title = this.$t('strings.world'); - }, - onShow() { - console.info('onShow finish') - const core = Core.getInstance() - const expectExtend = new ExpectExtend({ - 'id': 'extend' - }) - core.addService('expect', expectExtend) - core.init() - const configService = core.getDefaultService('config') - configService.setConfig(this) - require('../../../test/List.test') - core.execute() - }, - onReady() { - }, - } - ``` - -3. 单元测试用例示例 - - ``` - // Example1: 使用HJSUnit进行单元测试 - describe('appInfoTest', function () { - it('app_info_test_001', 0, function () { - var info = app.getInfo() - expect(info.versionName).assertEqual('1.0') - expect(info.versionCode).assertEqual('3') - }) - }) - ``` - - -### JS语言用例编译打包指导(适用于标准系统) +1. 规范用例目录:测试用例存储到entry/src/main/js/test目录。 + + ``` + ├── BUILD.gn + │ └──entry + │ │ └──src + │ │ │ └──main + │ │ │ │ └──js + │ │ │ │ │ └──default + │ │ │ │ │ │ └──pages + │ │ │ │ │ │ │ └──index + │ │ │ │ │ │ │ │ └──index.js # 入口文件 + │ │ │ │ │ └──test # 测试代码存放目录 + │ │ │ └── resources # hap资源存放目录 + │ │ │ └── config.json # hap配置文件 + ``` + +2. index.js示例 + + ``` + // 拉起js测试框架,加载测试用例 + import {Core, ExpectExtend} from 'deccjsunit/index' + + export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + }, + onShow() { + console.info('onShow finish') + const core = Core.getInstance() + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }) + core.addService('expect', expectExtend) + core.init() + const configService = core.getDefaultService('config') + configService.setConfig(this) + require('../../../test/List.test') + core.execute() + }, + onReady() { + }, + } + ``` + +3. 单元测试用例示例 + + ``` + // Example1: 使用HJSUnit进行单元测试 + describe('appInfoTest', function () { + it('app_info_test_001', 0, function () { + var info = app.getInfo() + expect(info.versionName).assertEqual('1.0') + expect(info.versionCode).assertEqual('3') + }) + }) + ``` + +### JS语言用例编译打包指导(适用于标准系统) hap包编译请参考[标准系统js应用开发指导](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)。 -## 全量编译指导(适用于标准系统) -1. 全量编译 +## 全量编译指导(适用于标准系统) - **命令**: +1. 全量编译 + **命令**: - ``` - ./build.sh suite=acts system_size=standard - ``` + + ``` + ./build.sh suite=acts system_size=standard + ``` - **测试用例输出目录**:out/release/suites/acts/testcases + **测试用例输出目录**:out/release/suites/acts/testcases - **测试框架&用例整体输出目录**:out/release/suites/acts(编译用例时会同步编译测试套执行框架) + **测试框架&用例整体输出目录**:out/release/suites/acts(编译用例时会同步编译测试套执行框架) -## 全量用例执行指导(适用于小型系统、标准系统) +## 全量用例执行指导(适用于小型系统、标准系统) **搭建测试环境** Windows工作台下安装python3.7及以上版本,确保工作台和测试设备正常连接。 -**测试执行目录**(对应编译生成的out/release/suites/acts目录) - + **测试执行目录**(对应编译生成的out/release/suites/acts目录) + ``` ├── testcase # 测试套文件存放目录 │ └──xxx.hap # 测试套可执行hap文件 @@ -666,31 +480,30 @@ Windows工作台下安装python3.7及以上版本,确保工作台和测试设 **用例执行** -1. 在Windows工作台上,找到从Linux服务器上拷贝下来的测试套件用例目录\(对应编译生成的out/release/suites/acts目录\),在Windows命令窗口进入对应目录,直接执行acts\\run.bat。 - -1. 界面启动后,输入用例执行指令。 - - - 全量执行 - - ``` - run acts - ``` - - ![](figure/zh-cn_image_0000001119924146.gif) - - - 模块执行\(具体模块可以查看\\acts\\testcases\\\) +1. 在Windows工作台上,找到从Linux服务器上拷贝下来的测试套件用例目录(对应编译生成的out/release/suites/acts目录),在Windows命令窗口进入对应目录,直接执行acts\run.bat。 - ``` - run –l ActsSamgrTest - ``` +1. 界面启动后,输入用例执行指令。 + - 全量执行 + + ``` + run acts + ``` - ![](figure/zh-cn_image_0000001166643927.jpg) + **图1** 运行进程 - 等待执行完成。 + ![zh-cn_image_0000001200230833](figures/zh-cn_image_0000001200230833.gif) + - 模块执行(具体模块可以查看\acts\testcases\) + + ``` + run –l ActsSamgrTest + ``` -1. 查看测试报告。 + **图2** 查看运行命令 - 进入acts\\reports\\,获取当前的执行记录,打开“summary\_report.html”可以获取到测试报告。 + ![zh-cn_image_0000001154351160](figures/zh-cn_image_0000001154351160.jpg) + 等待执行完成。 +1. 查看测试报告。 + 进入acts\reports\,获取当前的执行记录,打开“summary_report.html”可以获取到测试报告。 diff --git a/zh-cn/device-dev/subsystems/subsys.md b/zh-cn/device-dev/subsystems/subsys.md index 5c874980f028f17e2375a31fd3bc4f8faccd2b16..c7332d5a16c97ce33a768f6e57ddf0f33da0e1ef 100755 --- a/zh-cn/device-dev/subsystems/subsys.md +++ b/zh-cn/device-dev/subsystems/subsys.md @@ -1,21 +1,35 @@ -# 子系统 - -- **[编译构建](subsys-build.md)** -- **[分布式远程启动](subsys-remote-start.md)** -- **[图形图像](subsys-graphics.md)** -- **[媒体](subsys-multimedia.md)** -- **[数据管理](subsys-data.md)** -- **[公共基础](subsys-utils.md)** -- **[AI框架](subsys-aiframework.md)** -- **[Sensor服务](subsys-sensor.md)** -- **[用户程序框架](subsys-application-framework.md)** -- **[OTA升级](subsys-ota-guide.md)** -- **[电话服务](subsys-tel.md)** -- **[安全](subsys-security.md)** -- **[启动恢复](subsys-boot.md)** -- **[测试用例开发指导](subsys-testguide-test.md)** -- **[DFX](subsys-dfx.md)** -- **[研发工具链](subsys-toolchain.md)** -- **[XTS认证用例开发指导](subsys-xts-guide.md)** +# 子系统 + +- **[编译构建](subsys-build.md)** + +- **[分布式远程启动](subsys-remote-start.md)** + +- **[测试用例开发指导](subsys-testguide-test.md)** + +- **[XTS认证用例开发指导](subsys-xts-guide.md)** + +- **[图形图像](subsys-graphics.md)** + +- **[媒体](subsys-multimedia.md)** + +- **[公共基础](subsys-utils.md)** + +- **[AI框架](subsys-aiframework.md)** + +- **[Sensor服务](subsys-sensor.md)** + +- **[用户程序框架](subsys-application-framework.md)** + +- **[升级服务](subsys-ota.md)** + +- **[电话服务](subsys-tel.md)** + +- **[安全](subsys-security.md)** + +- **[启动恢复](subsys-boot.md)** + +- **[DFX](subsys-dfx.md)** + +- **[调测工具](subsys-toolchain.md)** \ No newline at end of file diff --git a/zh-cn/device-dev/website.md b/zh-cn/device-dev/website.md index b25be9c0450d0546369d1f305d717aca5dcd7211..1210fb07c77f047a4def76315e24282d39c0e519 100644 --- a/zh-cn/device-dev/website.md +++ b/zh-cn/device-dev/website.md @@ -4,52 +4,53 @@ - 快速开始 - 轻量和小型系统快速入门(IDE方式) - - [轻量与小型系统入门概述](quickstart-ide-lite-overview.md) + - [轻量与小型系统入门概述](quick-start/quickstart-ide-lite-overview.md) - 准备轻量与小型系统环境 - - [搭建系统环境](quickstart-ide-lite-env-system.md) - - [获取源码](quickstart-ide-lite-sourcecode-acquire.md) - - [创建源码工程](quickstart-ide-lite-create-project.md) + - [搭建Windows+Ubuntu混合开发环境](quick-start/quickstart-ide-lite-env-setup-win-ubuntu.md) + - [获取源码](quick-start/quickstart-ide-lite-sourcecode-acquire.md) + - [创建源码工程](quick-start/quickstart-ide-lite-create-project.md) - 运行“Hello World” - Hi3861开发板 - - [编写“Hello World”程序](quickstart-ide-lite-steps-hi3861-application-framework.md) - - [编译](quickstart-ide-lite-steps-hi3861-building.md) - - [烧录](quickstart-ide-lite-steps-hi3861-burn.md) - - [联网](quickstart-ide-lite-steps-hi3861-netconfig.md) - - [调试验证](quickstart-ide-lite-steps-hi3861-debug.md) - - [运行](quickstart-ide-lite-steps-hi3816-running.md) + - [编写“Hello World”程序](quick-start/quickstart-ide-lite-steps-hi3861-application-framework.md) + - [编译](quick-start/quickstart-ide-lite-steps-hi3861-building.md) + - [烧录](quick-start/quickstart-ide-lite-steps-hi3861-burn.md) + - [联网](quick-start/quickstart-ide-lite-steps-hi3861-netconfig.md) + - [调试验证](quick-start/quickstart-ide-lite-steps-hi3861-debug.md) + - [运行](quick-start/quickstart-ide-lite-steps-hi3816-running.md) - Hi3516开发板 - - [编写“Hello World”程序](quickstart-ide-lite-steps-hi3516-application-framework.md) - - [编译](quickstart-ide-lite-steps-hi3516-building.md) - - [烧录](quickstart-ide-lite-steps-hi3516-burn.md) - - [运行](quickstart-ide-lite-steps-hi3516-running.md) + - [编写“Hello World”程序](quick-start/quickstart-ide-lite-steps-hi3516-application-framework.md) + - [编译](quick-start/quickstart-ide-lite-steps-hi3516-building.md) + - [烧录](quick-start/quickstart-ide-lite-steps-hi3516-burn.md) + - [运行](quick-start/quickstart-ide-lite-steps-hi3516-running.md) - 附录 - 开发板介绍 - - [Hi3861开发板介绍](quickstart-ide-lite-introduction-hi3861.md) - - [Hi3516开发板介绍](quickstart-ide-lite-introduction-hi3516.md) + - [Hi3861开发板介绍](quick-start/quickstart-ide-lite-introduction-hi3861.md) + - [Hi3516开发板介绍](quick-start/quickstart-ide-lite-introduction-hi3516.md) - 标准系统快速入门(IDE方式) - - [标准系统入门概述](quickstart-ide-standard-overview.md) + - [标准系统入门概述](quick-start/quickstart-ide-standard-overview.md) - 准备标准系统环境 - - [搭建系统环境](quickstart-ide-standard-env-system.md) - - [获取源码](quickstart-ide-standard-sourcecode-acquire.md) - - [创建源码工程](quickstart-ide-standard-create-project.md) + - [搭建Windows+Ubuntu混合开发环境](quick-start/quickstart-ide-standard-env-setup-win-ubuntu.md) + - [获取源码](quick-start/quickstart-ide-standard-sourcecode-acquire.md) + - [创建源码工程](quick-start/quickstart-ide-standard-create-project.md) - 运行“Hello World” - Hi3516开发板 - - [编写“Hello World”程序](quickstart-ide-standard-running-hi3516-create.md) - - [编译](quickstart-ide-standard-running-hi3516-build.md) - - [烧录](quickstart-ide-standard-running-hi3516-burning.md) - - [运行](quickstart-ide-standard-running-hi3516-running.md) + - [编写“Hello World”程序](quick-start/quickstart-ide-standard-running-hi3516-create.md) + - [编译](quick-start/quickstart-ide-standard-running-hi3516-build.md) + - [烧录](quick-start/quickstart-ide-standard-running-hi3516-burning.md) + - [运行](quick-start/quickstart-ide-standard-running-hi3516-running.md) - RK3568开发板 - - [编写“Hello World”程序](quickstart-ide-standard-running-rk3568-create.md) - - [编译](quickstart-ide-standard-running-rk3568-build.md) - - [烧录](quickstart-ide-standard-running-rk3568-burning.md) - - [运行](quickstart-ide-standard-running-rk3568-running.md) + - [编写“Hello World”程序](quick-start/quickstart-ide-standard-running-rk3568-create.md) + - [编译](quick-start/quickstart-ide-standard-running-rk3568-build.md) + - [烧录](quick-start/quickstart-ide-standard-running-rk3568-burning.md) + - [运行](quick-start/quickstart-ide-standard-running-rk3568-running.md) - 附录 - 开发板介绍 - - [Hi3516开发板介绍](quickstart-ide-standard-board-introduction-hi3516.md) - - [RK3568开发板介绍](quickstart-ide-standard-board-introduction-rk3568.md) + - [Hi3516开发板介绍](quick-start/quickstart-ide-standard-board-introduction-hi3516.md) + - [RK3568开发板介绍](quick-start/quickstart-ide-standard-board-introduction-rk3568.md) - [获取源码](get-code/sourcecode-acquire.md) + - 兼容性与安全 - [隐私保护](security/security-privacy-protection.md) @@ -60,7 +61,7 @@ - 轻量系统芯片移植指导 - 移植准备 - - [移植须知](porting/oem_transplant_chip_prepare_knows.md) + - [移植须知](porting/porting-chip-prepare-knows.md) - [编译构建适配流程](porting/porting-chip-prepare-process.md) - 内核移植 - [移植概述](porting/porting-chip-kernel-overview.md) @@ -99,9 +100,7 @@ - [CMake方式组织编译的库移植](porting/porting-thirdparty-cmake.md) - [Makefile方式组织编译的库移植](porting/porting-thirdparty-makefile.md) - - 轻量系统芯片移植案例 - - - [带屏解决方案之恒玄芯片移植案例](porting/porting-bes2600w-on-minisystem-display-demo.md) + - [轻量系统芯片移植案例](porting/porting-bes2600w-on-minisystem-display-demo.md) - 子系统开发 @@ -388,7 +387,7 @@ - [Sensor服务概述](subsystems/subsys-sensor-overview.md) - [Sensor服务使用指导](subsystems/subsys-sensor-guide.md) - [Sensor服务使用实例](subsystems/subsys-sensor-demo.md) - - USB服务 + - USB服务子系统 - [USB服务概述](subsystems/subsys-usbservice-overview.md) - [USB服务使用指导](subsystems/subsys-usbservice-guide.md) - [USB服务使用实例](subsystems/subsys-usbservice-demo.md) diff --git "a/\357\274\201" "b/\357\274\201" deleted file mode 100644 index 145356f1c64caf99afd1b38bdd6c23ebaf6fe268..0000000000000000000000000000000000000000 --- "a/\357\274\201" +++ /dev/null @@ -1,7 +0,0 @@ -Signed-off-by: duangavin123 -Merge branch 'master' of https://gitee.com/duangavin123_admin/docs_1 -# Please enter a commit message to explain why this merge is necessary, -# especially if it merges an updated upstream into a topic branch. -# -# Lines starting with '#' will be ignored, and an empty message aborts -# the commit.