diff --git a/zh-cn/device-dev/kernel/Readme-CN.md b/zh-cn/device-dev/kernel/Readme-CN.md old mode 100755 new mode 100644 index d2f636772b96b25854cf596fcb122bc9c08a561b..6830f1c25d24f603a0a5d78a2123bca96ea98c9d --- a/zh-cn/device-dev/kernel/Readme-CN.md +++ b/zh-cn/device-dev/kernel/Readme-CN.md @@ -26,6 +26,7 @@ - [异常调测](kernel-mini-memory-exception.md) - [Trace调测](kernel-mini-memory-trace.md) - [LMS调测](kernel-mini-memory-lms.md) + - [SHELL](kernel-mini-debug-shell.md) - 附录 - [内核编码规范](kernel-mini-appx-code.md) - [标准库支持](kernel-mini-appx-lib.md) @@ -135,7 +136,7 @@ - [魔法键使用方法](kernel-small-debug-shell-magickey.md) - [用户态异常信息说明](kernel-small-debug-shell-error.md) - [Trace调测](kernel-small-debug-trace.md) - - [Perf调测](kernel-mini-memory-perf.md) + - [Perf调测](kernel-small-debug-perf.md) - [LMS调测](kernel-small-memory-lms.md) - [进程调测](kernel-small-debug-process-cpu.md) - 内核态内存调测 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 3c92cc74ce65af388c8dd4295ff6850518028238..341817ed342487fe2caba82e1dc00453138ef8a3 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-code.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-code.md @@ -58,7 +58,7 @@ OsMuxInit ## 注释 -一般的,尽量通过清晰的软件架构,良好的符号命名来提高代码可读性;然后在需要的时候,才辅以注释说明。 +一般的,尽量通过清晰的软件架构,良好的符号命名来提高代码可读性;在需要的时候,辅以注释说明。 注释是为了帮助阅读者快速读懂代码,所以要从读者的角度出发,按需注释。 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 82f007c8c3d6ed95d8be4f0a4a119ca54398aecb..ccccedceef75b44bed6736db12fc3ca601822c18 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-appx-lib.md +++ b/zh-cn/device-dev/kernel/kernel-mini-appx-lib.md @@ -459,6 +459,8 @@ demo功能: 创建一个线程并将父线程中的信息传递给子线程,在子线程中打印传递过来的信息和自身线程id值。 +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数DemoForTest。 + ``` #include 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 ef398c91849fcae751bcb1c848424acaa609772d..9a7c3c83e48325e39b2cf98a09be1132e6a14c5d 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 @@ -84,7 +84,7 @@ typedef struct tagEvent { > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> - 进行事件读写操作时,事件的第25位为保留位,不可以进行位设置。 +> - 进行事件读写操作时,事件的第25bit(`0x02U << 24`)为保留bit位,不可以进行位设置。 > > - 对同一事件反复写入,算作一次写入。 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 f2e60ebd8b30ea049f5238dbd1ae52bc17e40ec9..1bafb4de87da9338e67b4331b760078c8667f402 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 @@ -7,7 +7,7 @@ 任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 -可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 +可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将读队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: diff --git a/zh-cn/device-dev/kernel/kernel-mini-debug-shell.md b/zh-cn/device-dev/kernel/kernel-mini-debug-shell.md new file mode 100644 index 0000000000000000000000000000000000000000..c16cede98ce7cd840b5a56a334acdde04142bbf1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-mini-debug-shell.md @@ -0,0 +1,241 @@ +# SHELL + +OpenHarmony内核提供的Shell支持调试常用的基本功能,包含系统、文件、网络相关命令。同时OpenHarmony内核的Shell支持添加新的命令,可以根据需求来进行定制。 + +Shell功能仅供调试使用,暂不支持tab按键补全,按键回退等功能。 + +部分命令需要通过make menuconfig开启对应选项才可使用。 + +## 常用命令介绍 + +### cat + +用于显示文本文件的内容。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +cat [FILE] + +###### 参数说明 + +| 参数 | 参数说明 | 取值范围 | +| ---- | ---------- | -------------- | +| FILE | 文件路径。 | 已存在的文件。 | + +### cd + +用来改变当前目录。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +cd [path] + +###### 参数说明 + +| 参数 | 参数说明 | 取值范围 | +| ---- | ---------- | -------------- | +| path | 文件路径。 | 已存在的路径。 | + +### cp + +拷贝文件,创建一份副本。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +cp [SOURCEFILE] [DESTFILE] + +###### 参数说明 + +| 参数 | 参数说明 | 取值范围 | +| ---------- | ---------------------- | ----------------------------------------- | +| SOURCEFILE | 源文件路径。文件路径。 | 目前只支持文件,不支持目录;文件不可为空。 | +| DESTFILE | 目的文件路径。 | 支持目录以及文件名;目录需有效。 | + +### date + +用于查询系统日期和时间。 + +###### 命令格式 + +date + +###### 参数说明 + +无 + +### free + +显示系统内存的使用情况。 + +###### 命令格式 + +free [ -k | -m ] + +###### 参数说明 + +| 参数 | 参数说明 | 取值范围 | +| ---- | ----------------- | -------- | +| -k | 以KiB为单位显示。 | N/A | +| -m | 以MiB为单位显示。 | N/A | + +### help + +显示当前操作系统内所有操作指令。 + +###### 命令格式 + +help + +###### 参数说明 + +无 + +### ifconfig + +用来查询网卡的IP地址、网络掩码、网关、硬件mac地址等参数。需开启LWIP_SHELLCMD_ENABLE。 + +###### 命令格式 + +ifconfig + +###### 参数说明 + +无 + +### ls + +用来显示当前目录的内容。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +###### ls [DIRECTORY] + +| 参数 | 参数说明 | 取值范围 | +| --------- | ---------- | ------------------------------------------------------------ | +| DIRECTORY | 文件路径。 | DIRECTORY为空时,显示当前目录的内容。
DIRECTORY为有效目录路径时,会显示对应目录下的内容。
当前LiteOS-M不支持根目录 "/"。 | + +### memusage + +用来显示内存使用水线。 + +###### 命令格式 + +###### memusage [-k/-m] + +| 参数 | 参数说明 | 取值范围 | +| ---- | ----------------- | -------- | +| -k | 以KiB为单位显示。 | N/A | +| -m | 以MiB为单位显示。 | N/A | + +### mkdir + +用来创建一个目录。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +###### mkdir [DIRECTORY] + +| 参数 | 参数说明 | 取值范围 | +| --------- | ---------- | ------------------------------------- | +| DIRECTORY | 文件路径。 | DIRECTORY可以传入绝对路径和相对路径。 | + +### ping + +用来测试网络连接是否正常。需开启LWIP_SHELLCMD_ENABLE。 + +###### 命令格式 + +###### ping [ip] + +| 参数 | 参数说明 | 取值范围 | +| ---- | ------------------------------ | -------- | +| ip | 要测试是否网络连通的IPv4地址。 | N/A | + +### pwd + +用来显示当前路径。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +###### pwd + +### rm + +用来删除文件或文件夹。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +###### rm [FILE] or rm [-r/-R] [FILE] + +| 参数 | 参数说明 | 取值范围 | +| ----- | ------------------------------- | -------------------------------- | +| FILE | 文件名,可以是文件或者文件夹 。 | FILE可以传入绝对路径和相对路径。 | +| -r/-R | FILE是文件夹时需要有-r /-R。 | N/A | + +### rmdir + +用来删除文件夹。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +###### rmdir [DIRECTORY] + +| 参数 | 参数说明 | 取值范围 | +| --------- | ---------- | ------------------------------------- | +| DIRECTORY | 文件路径。 | DIRECTORY可以传入绝对路径和相对路径。 | + +### task + +用来显示当前各任务状态。 + +###### 命令格式 + +###### task + +显示内容主要包括任务号,优先级,状态,栈信息,信号,事件,CPU占用率,任务名称等 + +### touch + +用来创建文件。需开启LOSCFG_FS_VFS。 + +###### 命令格式 + +###### touch [FILE] + +| 参数 | 参数说明 | 取值范围 | +| ---- | -------- | -------------------------------- | +| FILE | 文件名。 | FILE可以传入绝对路径和相对路径。 | + +### stack + +用来查看指定任务的栈内容。需开启编译选项 LOSCFG_DEBUG_TOOLS,功能开启会影响性能。 + +###### 命令格式 + +###### stack [ID] + +| 参数 | 参数说明 | 取值范围 | +| ---- | -------- | ------------------------ | +| ID | 任务ID。 | 任务ID对应的任务需存在。 | + +### hwi + +用来查看中断的占用率。需开启编译选项 LOSCFG_DEBUG_TOOLS,功能开启会影响性能。 + +###### 命令格式 + +###### hwi + +### st + +用来查看调度信息。需开启编译选项 LOSCFG_DEBUG_TOOLS,功能开启会影响性能。 + +###### 命令格式 + +###### st -s | st -e + +| 参数 | 参数说明 | 取值范围 | +| ---- | ---------------------- | -------- | +| -s | 开始记录调度信息 | N/A | +| -e | 停止记录并打印调度信息 | N/A | + 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 8e9c2c00dc6c237a67e9c4d76ec7e086f589c8d0..275c839d1fe923debfc957b4ca4a97c37ec9198e 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-cpup.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-cpup.md @@ -5,14 +5,18 @@ CPU(中央处理器,Central Processing Unit)占用率分为系统CPU占用率和任务CPU占用率。 -系统CPU占用率(CPU Percent)是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示系统满负荷运转。 +**系统CPU占用率**:是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其单位为百分比。100表示系统满负荷运转。 -任务CPU占用率指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该任务。 +**任务CPU占用率**:指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其单位为百分比。100表示在一段时间内系统一直在运行该任务。 用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。 通过系统中各个任务的CPU占用情况,判断各个任务的CPU占用率是否符合设计的预期。 +此外开启CPUP的情况下,可选择开启中断占用率统计。 + +**中断占用率**:是指单个中断在全部中断消耗时间的占用率。占用率的有效表示范围为0~100。100表示在一段时间内仅触发该中断。 + ## 运行机制 @@ -23,44 +27,51 @@ OpenHarmony LiteOS-M的CPUP(CPU Percent,系统CPU占用率)采用任务 OpenHarmony LiteOS-M提供以下两种CPU占用率的信息查询: - 系统CPU占用率。 - - 任务CPU占用率。 -**CPU占用率的计算方法:** +此外,系统还提供了中断占用率的信息查询能力(需同时开启CPUP和定时器)。 + +**占用率的计算方法:** 系统CPU占用率=系统中除idle任务外其他任务运行总时间/系统运行总时间 任务CPU占用率=任务运行总时间/系统运行总时间 +中断占用率=单个中断运行时间/中断运行总时间 + ## 接口说明 **表1** 功能列表 -| 功能分类 | 接口描述 | +| 功能分类 | 接口描述 | | -------- | -------- | -| 获取系统CPU占用率 | - LOS_SysCpuUsage:获取当前系统CPU占用率
- LOS_HistorySysCpuUsage:获取系统历史CPU占用率 | -| 获取任务CPU占用率 | - LOS_TaskCpuUsage:获取指定任务CPU占用率
- LOS_HistoryTaskCpuUsage:获取指定任务历史CPU占用率
- LOS_HistoryTaskCpuUsage:获取指定任务历史CPU占用率 | -| 输出任务CPU占用率 | LOS_CpupUsageMonitor:输出任务历史CPU占用率 | - +| 获取系统CPU占用率 |  LOS_SysCpuUsage:获取当前系统CPU占用率
 LOS_HistorySysCpuUsage:获取系统历史CPU占用率 | +| 获取任务CPU占用率 |  LOS_TaskCpuUsage:获取指定任务CPU占用率
 LOS_HistoryTaskCpuUsage:获取指定任务历史CPU占用率
 LOS_AllTaskCpuUsage:获取所有任务CPU占用率 | +| 输出任务CPU占用率 | LOS_CpupUsageMonitor:输出任务历史CPU占用率 | +| 获取中断CPU占用率 | LOS_GetAllIrqCpuUsage:获取所有中断CPU占用率 | ## 开发流程 +在kernel/liteos_m目录下执行 make menuconfig 命令配置"Kernel->Enable Cpup"中打开YES开启任务cpup; + +开启后出现新选项“Enable Cpup include irq”打开YES开启中断cpup。 + CPU占用率的典型开发流程: -1. 调用获取系统CPU使用率函数LOS_SysCpuUsage。 +1. 调用获取系统CPU占用率函数LOS_SysCpuUsage。 -2. 调用获取系统历史CPU使用率函数LOS_HistorySysCpuUsage。 +2. 调用获取系统历史CPU占用率函数LOS_HistorySysCpuUsage。 -3. 调用获取指定任务CPU使用率函数LOS_TaskCpuUsage。 +3. 调用获取指定任务CPU占用率函数LOS_TaskCpuUsage。 - 若任务已创建,则关中断,正常获取,恢复中断; - 若任务未创建,则返回错误码; -4. 调用获取指定任务历史CPU使用率函数LOS_HistoryTaskCpuUsage。 +4. 调用获取指定任务历史CPU占用率函数LOS_HistoryTaskCpuUsage。 - 若任务已创建,则关中断,根据不同模式正常获取,恢复中断; - 若任务未创建,则返回错误码; -5. 调用获取所有任务CPU使用率函数LOS_AllCpuUsage。 +5. 调用获取所有任务CPU占用率函数LOS_AllCpuUsage。 - 若CPUP已初始化,则关中断,根据不同模式正常获取,恢复中断; - 若CPUP未初始化或有非法入参,则返回错误码; @@ -87,58 +98,67 @@ CPU占用率的典型开发流程: 前提条件: -在target_config.h中将LOSCFG_BASE_CORE_CPUP配置项打开。 +在kernel/liteos_m目录下执行 make menuconfig命令配置"Kernel->Enable Cpup"中开启任务cpup: 代码实现如下: - +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数ExampleCpup。 + + ``` #include "los_task.h" -#include "los_cpup.h" -#define MODE 4 -UINT32 g_cpuTestTaskID; -VOID ExampleCpup(VOID) -{ +#include "los_cpup.h" + +#define TEST_TASK_PRIO 5 +#define TASK_DELAY_TIME 100 +VOID CpupTask(VOID) +{ printf("entry cpup test example\n"); - while(1) { - usleep(100); - } + usleep(TASK_DELAY_TIME); + usleep(TASK_DELAY_TIME); + printf("exit cpup test example\n"); } -UINT32 ItCpupTest(VOID) -{ + +UINT32 ExampleCpup(VOID) +{ UINT32 ret; UINT32 cpupUse; - TSK_INIT_PARAM_S cpupTestTask = { 0 }; - memset(&cpupTestTask, 0, sizeof(TSK_INIT_PARAM_S)); - cpupTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleCpup; - cpupTestTask.pcName = "TestCpupTsk"; - cpupTestTask.uwStackSize = 0x800; - cpupTestTask.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_cpuTestTaskID, &cpupTestTask); + UINT32 taskID; + TSK_INIT_PARAM_S cpupTestTask = { 0 }; + + cpupTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)CpupTask; + cpupTestTask.pcName = "TestCpupTsk"; + cpupTestTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + cpupTestTask.usTaskPrio = TEST_TASK_PRIO; + ret = LOS_TaskCreate(&taskID, &cpupTestTask); if(ret != LOS_OK) { printf("cpupTestTask create failed .\n"); return LOS_NOK; } - usleep(100); + usleep(TASK_DELAY_TIME); /* 获取当前系统CPU占用率 */ cpupUse = LOS_SysCpuUsage(); printf("the current system cpu usage is: %u.%u\n", - cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); + cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); - cpupUse = LOS_HistorySysCpuUsage(CPU_LESS_THAN_1S); - /* 获取指定任务的CPU占用率,该测试例程中指定的任务为以上创建的cpup测试任务 */ + /* 获取当前系统历史CPU占用率 */ + cpupUse = LOS_HistorySysCpuUsage(CPUP_LESS_THAN_1S); printf("the history system cpu usage in all time:%u.%u\n", cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); - cpupUse = LOS_TaskCpuUsage(g_cpuTestTaskID); - /* 获取指定历史任务在系统启动到现在的CPU占用率,该测试例程中指定的任务为以上创建的cpup测试任务 */ + + /* 获取指定任务的CPU占用率 */ + cpupUse = LOS_TaskCpuUsage(taskID); printf("cpu usage of the cpupTestTask:\n TaskID: %d\n usage: %u.%u\n", - g_cpuTestTaskID, cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); - cpupUse = LOS_HistoryTaskCpuUsage(g_cpuTestTaskID, CPU_LESS_THAN_1S); + taskID, cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); + + /* 获取指定任务在系统启动到现在的CPU占用率 */ + cpupUse = LOS_HistoryTaskCpuUsage(taskID, CPUP_LESS_THAN_1S); printf("cpu usage of the cpupTestTask in all time:\n TaskID: %d\n usage: %u.%u\n", - g_cpuTestTaskID, cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); - return LOS_OK; + taskID, cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); + + return LOS_OK; } ``` @@ -146,11 +166,19 @@ UINT32 ItCpupTest(VOID) ### 结果验证 编译运行得到的结果为: - + ``` -entry cpup test example -the current system cpu usage is : 1.5 - the history system cpu usage in all time: 3.0 - cpu usage of the cpupTestTask: TaskID:10 usage: 0.0 - cpu usage of the cpupTestTask in all time: TaskID:10 usage: 0.0 +entry cpup test example +the current system cpu usage is: 8.2 +the history system cpu usage in all time:8.9 +cpu usage of the cpupTestTask: + TaskID: 5 + usage: 0.5 +cpu usage of the cpupTestTask in all time: + TaskID: 5 + usage: 0.5 + +exit cpup test example + +根据实际运行环境,上文中的数据会有差异,非固定结果 ``` 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 e0df347da27479ec128062a02c44d458cf6cd9b7..0302a6c6b129d86037be9adeaa27e7c6a24335de 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-extend-file.md +++ b/zh-cn/device-dev/kernel/kernel-mini-extend-file.md @@ -1,23 +1,30 @@ # 文件系统 +## VFS -M核的文件系统子系统当前支持的文件系统有FATFS与LittleFS。同A核一样,通过VFS层提供了POSIX标准的操作,保持了接口的一致性,但是因为M核的资源非常紧张,VFS层非常轻薄,没有提供类似A核的高级功能(如pagecache等),主要是接口的标准化和适配工作,具体的事务由各个文件系统实际承载。M核文件系统支持的功能如下表所示: +### 基本概念 - **表1** 文件操作 +**VFS(Virtual File System)** 是文件系统的虚拟层,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。 -| 接口名 | 描述 | FATFS | LITTLEFS | +M核的文件系统子系统当前支持的文件系统有FATFS与LittleFS。通过VFS层提供了POSIX标准的操作,保持了接口的一致性,但是因为M核的资源非常紧张,VFS层非常轻薄,没有提供类似A核的高级功能(如pagecache等),主要是接口的标准化和适配工作,具体的事务由各个文件系统实际承载。M核文件系统支持的功能如下表所示: + +### 接口说明 + +**表1** 文件操作 + +| 接口名 | 描述 | FATFS | LITTLEFS | | -------- | -------- | -------- | -------- | -| open | 打开文件 | 支持 | 支持 | -| close | 关闭文件 | 支持 | 支持 | -| read | 读取文件内容 | 支持 | 支持 | -| write | 往文件写入内容 | 支持 | 支持 | -| lseek | 设置文件偏移位置 | 支持 | 支持 | -| unlink | 删除文件 | 支持 | 支持 | -| rename | 重命名文件 | 支持 | 支持 | -| fstat | 通过文件句柄获取文件信息 | 支持 | 支持 | -| stat | 通过文件路径名获取文件信息 | 支持 | 支持 | -| fsync | 文件内容刷入存储设备 | 支持 | 支持 | +| open | 打开文件 | 支持 | 支持 | +| close | 关闭文件 | 支持 | 支持 | +| read | 读取文件内容 | 支持 | 支持 | +| write | 往文件写入内容 | 支持 | 支持 | +| lseek | 设置文件偏移位置 | 支持 | 支持 | +| stat | 通过文件路径名获取文件信息 | 支持 | 支持 | +| unlink | 删除文件 | 支持 | 支持 | +| rename | 重命名文件 | 支持 | 支持 | +| fstat | 通过文件句柄获取文件信息 | 支持 | 支持 | +| fsync | 文件内容刷入存储设备 | 支持 | 支持 | **表2** 目录操作 @@ -40,6 +47,8 @@ M核的文件系统子系统当前支持的文件系统有FATFS与LittleFS。同 | umount2 | 分区卸载,可通过MNT_FORCE参数进行强制卸载 | 支持 | 不支持 | | statfs | 获取分区信息 | 支持 | 不支持 | +ioctl,fcntl等接口由不同的lib库支持,与底层文件系统无关。 + ## FAT @@ -61,14 +70,93 @@ 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 #define FAT_MAX_OPEN_FILES 50 ``` - +#### 分区挂载 + +移植FATFS到新硬件设备上,需要在初始化flash驱动后,完成设备分区。 + +设备分区接口:int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, int *addrArray, int partNum); + +- dev:设备名称, 如“spinorblk0” +- fsType:文件系统类型,”vfat“ +- lengthArray:该设备上各分区的长度列表,fatfs填入百分比即可 +- addrArray:该设备上各分区的起始地址列表 +- partNum:分区的个数 + +格式化接口:int LOS_PartitionFormat(const char *partName, char *fsType, void *data); + +- partName:分区名称,设备名称+ ‘p’ + 分区号,如“spinorblk0p0” +- fsType:文件系统类型,”vfat“ +- data:私有数据 传入(VOID *)formatType,(如FMT_FAT, FMT_FAT32) + +mount接口:int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); + +- source:分区名称,设备名称+ ‘p’ + 分区号,如“spinorblk0p0” +- target:挂载路径 +- filesystemtype:文件系统类型,”vfat“ +- mountflags:mount配置参数 +- data:私有数据,传入(VOID *)formatType,(如FMT_FAT, FMT_FAT32) + +本参考代码已在 ./device/qemu/arm_mps2_an386/liteos_m/board/fs/fs_init.c 中实现,M核qemu上可直接使用,请参考并根据实际硬件修改。 + + #include "fatfs_conf.h" + #include "fs_config.h" + #include "los_config.h" + #include "ram_virt_flash.h" + #include "los_fs.h" + + struct fs_cfg { + CHAR *mount_point; + struct PartitionCfg partCfg; + }; + + INT32 FatfsLowLevelInit() + { + INT32 ret; + INT32 i; + UINT32 addr; + int data = FMT_FAT32; + + const char * const pathName[FF_VOLUMES] = {FF_VOLUME_STRS}; + HalLogicPartition *halPartitionsInfo = getPartitionInfo(); /* 获取长度和起始地址的函数,请根据实际单板适配 */ + INT32 lengthArray[FF_VOLUMES] = {25, 25, 25, 25}; + INT32 addrArray[FF_VOLUMES]; + + /* 配置各分区的地址和长度,请根据实际单板适配 */ + for (i = 0; i < FF_VOLUMES; i++) { + addr = halPartitionsInfo[FLASH_PARTITION_DATA1].partitionStartAddr + i * 0x10000; + addrArray[i] = addr; + FlashInfoInit(i, addr); + } + + /* 配置分区信息,请根据实际单板适配 */ + SetupDefaultVolToPartTable(); + + ret = LOS_DiskPartition("spinorblk0", "vfat", lengthArray, addrArray, FF_VOLUMES); + printf("%s: DiskPartition %s\n", __func__, (ret == 0) ? "succeed" : "failed"); + if (ret != 0) { + return -1; + } + + ret = LOS_PartitionFormat("spinorblk0p0", "vfat", &data); + printf("%s: PartitionFormat %s\n", __func__, (ret == 0) ? "succeed" : "failed"); + if (ret != 0) { + return -1; + } + + ret = mount("spinorblk0p0", "/system", "vfat", 0, &data); + printf("%s: mount fs on '%s' %s\n", __func__, pathName[0], (ret == 0) ? "succeed" : "failed"); + if (ret != 0) { + return -1; + } + return 0; + } #### 开发流程 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** @@ -80,13 +168,11 @@ FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC > - 读写指针未分离,例如以O_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。 > - 暂不支持文件与目录的权限管理。 > - stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。 -> > - FATFS分区挂载与卸载: > - 支持以只读属性挂载分区。当mount函数的入参为MS_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O_RDONLY属性的open,将均被拒绝。 > - mount支持通过MS_REMOUNT标记修改已挂载分区的权限。 > - 在umount操作前,需确保所有目录及文件全部关闭。 > - umount2支持通过MNT_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。 -> > - FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs_fdisk与fatfs_format: > - 在fatfs_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。 > - 在fatfs_fdisk操作前,需要该设备中的所有分区均已umount。 @@ -100,9 +186,9 @@ FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC 本实例实现以下功能: -1. 创建目录“user/test” +1. 创建目录“system/test” -2. 在“user/test”目录下创建文件“file.txt” +2. 在“system/test”目录下创建文件“file.txt” 3. 在文件起始位置写入“Hello OpenHarmony!” @@ -123,97 +209,102 @@ FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC **前提条件:** - 系统已将MMC设备分区挂载到user目录 + 系统已将设备分区挂载到目录,qemu默认已挂载system。 + + 在kernel/liteos_m目录下执行 make menuconfig 命令配置"FileSystem->Enable FS VFS"开启FS功能; + + 开启FS后出现新选项“Enable FAT”开启FAT。 **代码实现如下:** - - ``` - #include - #include - #include "sys/stat.h" - #include "fcntl.h" - #include "unistd.h" - #define LOS_OK 0 - #define LOS_NOK -1 +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数ExampleFatfs。 - int FatfsTest(void) - { + ``` +#include +#include +#include "sys/stat.h" +#include "fcntl.h" +#include "unistd.h" + +#define BUF_SIZE 20 +#define TEST_ROOT "system" /* 测试的根目录请根据实际情况调整 */ +VOID ExampleFatfs(VOID) +{ int ret; - int fd = -1; + int fd; ssize_t len; off_t off; - char dirName[20] = "user/test"; - char fileName[20] = "user/test/file.txt"; - char writeBuf[20] = "Hello OpenHarmony!"; - char readBuf[20] = {0}; + char dirName[BUF_SIZE] = TEST_ROOT"/test"; + char fileName[BUF_SIZE] = TEST_ROOT"/test/file.txt"; + char writeBuf[BUF_SIZE] = "Hello OpenHarmony!"; + char readBuf[BUF_SIZE] = {0}; - /* 创建目录“user/test” */ + /* 创建测试目录 */ ret = mkdir(dirName, 0777); if (ret != LOS_OK) { printf("mkdir failed.\n"); - return LOS_NOK; + return; } - /* 创建可读写文件"user/test/file.txt" */ + /* 创建可读写测试文件 */ fd = open(fileName, O_RDWR | O_CREAT, 0777); if (fd < 0) { printf("open file failed.\n"); - return LOS_NOK; + return; } /* 将writeBuf中的内容写入文件 */ len = write(fd, writeBuf, strlen(writeBuf)); if (len != strlen(writeBuf)) { printf("write file failed.\n"); - return LOS_NOK; + return; } /* 将文件内容刷入存储设备中 */ ret = fsync(fd); if (ret != LOS_OK) { printf("fsync failed.\n"); - return LOS_NOK; + return; } /* 将读写指针偏移至文件头 */ off = lseek(fd, 0, SEEK_SET); if (off != 0) { printf("lseek failed.\n"); - return LOS_NOK; + return; } /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */ len = read(fd, readBuf, sizeof(readBuf)); if (len != strlen(writeBuf)) { printf("read file failed.\n"); - return LOS_NOK; + return; } printf("%s\n", readBuf); - /* 关闭文件 */ + /* 关闭测试文件 */ ret = close(fd); if (ret != LOS_OK) { printf("close failed.\n"); - return LOS_NOK; + return; } - /* 删除文件"user/test/file.txt" */ + /* 删除测试文件 */ ret = unlink(fileName); if (ret != LOS_OK) { printf("unlink failed.\n"); - return LOS_NOK; + return; } - /* 删除目录“user/test” */ + /* 删除测试目录 */ ret = rmdir(dirName); if (ret != LOS_OK) { printf("rmdir failed.\n"); - return LOS_NOK; + return; } - return LOS_OK; - } + return; +} ``` @@ -221,7 +312,7 @@ FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC 编译运行得到的结果为: - + ``` Hello OpenHarmony! ``` @@ -237,86 +328,198 @@ LittleFS是一个小型的Flash文件系统,它结合日志结构(log-struct ### 开发指导 -移植LittleFS到新硬件设备上,需要申明lfs_config: +移植LittleFS到新硬件设备上,需要在初始化flash驱动后,完成设备分区。 + +设备分区接口:int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, int *addrArray, int partNum); + +- dev:设备名称 +- fsType:文件系统类型, "littlefs" +- lengthArray:该设备上各分区的长度列表 +- addrArray:该设备上各分区的起始地址列表 +- partNum:分区的个数 + +格式化接口:int LOS_PartitionFormat(const char *partName, char *fsType, void *data); + +- partName:分区名称 +- fsType:文件系统类型, "littlefs" +- data:私有数据 传入(VOID *)struct fs_cfg + +mount接口:int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); + +- source:分区名称 +- target:挂载路径 +- filesystemtype:文件系统类型,"littlefs" +- mountflags:mount配置参数 +- data:私有数据,传入(VOID *)struct fs_cfg + +本参考代码已在 ./device/qemu/arm_mps2_an386/liteos_m/board/fs/fs_init.c 中实现,M核qemu上可直接使用,请参考并根据实际硬件修改。 + - ``` -const struct lfs_config cfg = { - // block device operations - .read = user_provided_block_device_read, - .prog = user_provided_block_device_prog, - .erase = user_provided_block_device_erase, - .sync = user_provided_block_device_sync, - - // block device configuration - .read_size = 16, - .prog_size = 16, - .block_size = 4096, - .block_count = 128, - .cache_size = 16, - .lookahead_size = 16, - .block_cycles = 500, +#include "los_config.h" +#include "ram_virt_flash.h" +#include "los_fs.h" + +struct fs_cfg { + CHAR *mount_point; + struct PartitionCfg partCfg; }; + +INT32 LfsLowLevelInit() +{ + INT32 ret; + struct fs_cfg fs[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0}; + HalLogicPartition *halPartitionsInfo = getPartitionInfo(); /* 获取长度和起始地址的函数,请根据实际单板适配 */ + + INT32 lengthArray[2]; + lengthArray[0]= halPartitionsInfo[FLASH_PARTITION_DATA0].partitionLength; + + INT32 addrArray[2]; + addrArray[0] = halPartitionsInfo[FLASH_PARTITION_DATA0].partitionStartAddr; + + ret = LOS_DiskPartition("flash0", "littlefs", lengthArray, addrArray, 2); + printf("%s: DiskPartition %s\n", __func__, (ret == 0) ? "succeed" : "failed"); + if (ret != 0) { + return -1; + } + fs[0].mount_point = "/littlefs"; + fs[0].partCfg.partNo = 0; + fs[0].partCfg.blockSize = 4096; /* 4096, lfs block size */ + fs[0].partCfg.blockCount = 1024; /* 2048, lfs block count */ + fs[0].partCfg.readFunc = virt_flash_read; /* flash读函数,请根据实际单板适配 */ + fs[0].partCfg.writeFunc = virt_flash_write; /* flash写函数,请根据实际单板适配 */ + fs[0].partCfg.eraseFunc = virt_flash_erase; /* flash擦函数,请根据实际单板适配 */ + + fs[0].partCfg.readSize = 256; /* 256, lfs read size */ + fs[0].partCfg.writeSize = 256; /* 256, lfs prog size */ + fs[0].partCfg.cacheSize = 256; /* 256, lfs cache size */ + fs[0].partCfg.lookaheadSize = 16; /* 16, lfs lookahead size */ + fs[0].partCfg.blockCycles = 1000; /* 1000, lfs block cycles */ + + ret = LOS_PartitionFormat("flash0", "littlefs", &fs[0].partCfg); + printf("%s: PartitionFormat %s\n", __func__, (ret == 0) ? "succeed" : "failed"); + if (ret != 0) { + return -1; + } + ret = mount(NULL, fs[0].mount_point, "littlefs", 0, &fs[0].partCfg); + printf("%s: mount fs on '%s' %s\n", __func__, fs[0].mount_point, (ret == 0) ? "succeed" : "failed"); + if (ret != 0) { + return -1; + } + return 0; +} ``` -其中.read,.prog,.erase,.sync分别对应该硬件平台上的底层的读写\擦除\同步等接口。 +其中.readFunc,.writeFunc,.eraseFunc分别对应该硬件平台上的底层的读写\擦除等接口。 -read_size 每次读取的字节数,可以比物理读单元大以改善性能,这个数值决定了读缓存的大小,但值太大会带来更多的内存消耗。 +readSize 每次读取的字节数,可以比物理读单元大以改善性能,这个数值决定了读缓存的大小,但值太大会带来更多的内存消耗。 -prog_size 每次写入的字节数,可以比物理写单元大以改善性能,这个数值决定了写缓存的大小,必须是read_size的整数倍,但值太大会带来更多的内存消耗。 +writeSize 每次写入的字节数,可以比物理写单元大以改善性能,这个数值决定了写缓存的大小,必须是readSize的整数倍,但值太大会带来更多的内存消耗。 -block_size 每个擦除块的字节数,可以比物理擦除单元大,但此数值应尽可能小因为每个文件至少会占用一个块。必须是prog_size的整数倍。 +blockSize 每个擦除块的字节数,可以比物理擦除单元大,但此数值应尽可能小因为每个文件至少会占用一个块。必须是writeSize的整数倍。 -block_count 可以被擦除的块数量,这取决于块设备的容量及擦除块的大小。 +blockCount 可以被擦除的块数量,这取决于块设备的容量及擦除块的大小。 ### 示例代码 - 代码实现如下: - + **前提条件:** + +系统已将设备分区挂载到目录,qemu默认已挂载/littlefs。 + +在kernel/liteos_m目录下执行 make menuconfig 命令配置"FileSystem->Enable FS VFS"开启FS功能; + +开启FS后出现新选项“Enable Little FS”开启littlefs。 + +代码实现如下: + +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数ExampleLittlefs。 + ``` -#include "lfs.h" -#include "stdio.h" -lfs_t lfs; -lfs_file_t file; -const struct lfs_config cfg = { - // block device operations - .read = user_provided_block_device_read, - .prog = user_provided_block_device_prog, - .erase = user_provided_block_device_erase, - .sync = user_provided_block_device_sync, - // block device configuration - .read_size = 16, - .prog_size = 16, - .block_size = 4096, - .block_count = 128, - .cache_size = 16, - .lookahead_size = 16, - .block_cycles = 500, -}; -int main(void) { - // mount the filesystem - int err = lfs_mount(&lfs, &cfg); - // reformat if we can't mount the filesystem - // this should only happen on the first boot - if (err) { - lfs_format(&lfs, &cfg); - lfs_mount(&lfs, &cfg); +#include +#include +#include "sys/stat.h" +#include "fcntl.h" +#include "unistd.h" + +#define BUF_SIZE 20 +#define TEST_ROOT "/littlefs" /* 测试的根目录请根据实际情况调整 */ +VOID ExampleLittlefs(VOID) +{ + int ret; + int fd; + ssize_t len; + off_t off; + char dirName[BUF_SIZE] = TEST_ROOT"/test"; + char fileName[BUF_SIZE] = TEST_ROOT"/test/file.txt"; + char writeBuf[BUF_SIZE] = "Hello OpenHarmony!"; + char readBuf[BUF_SIZE] = {0}; + + /* 创建测试目录 */ + ret = mkdir(dirName, 0777); + if (ret != LOS_OK) { + printf("mkdir failed.\n"); + return; } - // read current count - uint32_t boot_count = 0; - lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT); - lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count)); - // update boot count - boot_count += 1; - lfs_file_rewind(&lfs, &file); - lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count)); - // remember the storage is not updated until the file is closed successfully - lfs_file_close(&lfs, &file); - // release any resources we were using - lfs_unmount(&lfs); - // print the boot count - printf("boot_count: %d\n", boot_count); + + /* 创建可读写测试文件 */ + fd = open(fileName, O_RDWR | O_CREAT, 0777); + if (fd < 0) { + printf("open file failed.\n"); + return; + } + + /* 将writeBuf中的内容写入文件 */ + len = write(fd, writeBuf, strlen(writeBuf)); + if (len != strlen(writeBuf)) { + printf("write file failed.\n"); + return; + } + + /* 将文件内容刷入存储设备中 */ + ret = fsync(fd); + if (ret != LOS_OK) { + printf("fsync failed.\n"); + return; + } + + /* 将读写指针偏移至文件头 */ + off = lseek(fd, 0, SEEK_SET); + if (off != 0) { + printf("lseek failed.\n"); + return; + } + + /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */ + len = read(fd, readBuf, sizeof(readBuf)); + if (len != strlen(writeBuf)) { + printf("read file failed.\n"); + return; + } + printf("%s\n", readBuf); + + /* 关闭测试文件 */ + ret = close(fd); + if (ret != LOS_OK) { + printf("close failed.\n"); + return; + } + + /* 删除测试文件 */ + ret = unlink(fileName); + if (ret != LOS_OK) { + printf("unlink failed.\n"); + return; + } + + /* 删除测试目录 */ + ret = rmdir(dirName); + if (ret != LOS_OK) { + printf("rmdir failed.\n"); + return; + } + + return LOS_OK; } ``` @@ -325,7 +528,7 @@ int main(void) { 首次编译运行得到的结果为: - + ``` -Say hello 1 times. +Hello OpenHarmony! ``` \ No newline at end of file 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 e52c87c5561598bed62ea5e724f542c79b8f290c..079491ec6fab028f210a24647ed92ec2c52e4326 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-debug.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-debug.md @@ -62,7 +62,9 @@ typedef struct { #### 示例代码 - 代码实现如下: +代码实现如下: + +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数MemTest。 ``` #include @@ -71,20 +73,20 @@ typedef struct { #include "los_memory.h" #include "los_config.h" - +#define TEST_TASK_PRIO 5 void MemInfoTaskFunc(void) { LOS_MEM_POOL_STATUS poolStatus = {0}; - /* pool为要统计信息的内存地址,此处以OS_SYS_MEM_ADDR为例 */ + /* pool为要统计信息的内存地址,此处以OS_SYS_MEM_ADDR为例 */ void *pool = OS_SYS_MEM_ADDR; LOS_MemInfoGet(pool, &poolStatus); /* 算出内存池当前的碎片率百分比 */ - unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize; + float fragment = 100 - poolStatus.maxFreeNodeSize * 100.0 / poolStatus.totalFreeSize; /* 算出内存池当前的使用率百分比 */ - unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool); - printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, - poolStatus.totalFreeSize, poolStatus.usageWaterLine); + float usage = LOS_MemTotalUsedGet(pool) * 100.0 / LOS_MemPoolSizeGet(pool); + printf("usage = %f, fragment = %f, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, + poolStatus.maxFreeNodeSize, poolStatus.totalFreeSize, poolStatus.usageWaterLine); } int MemTest(void) @@ -93,9 +95,9 @@ int MemTest(void) unsigned int taskID; TSK_INIT_PARAM_S taskStatus = {0}; taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc; - taskStatus.uwStackSize = 0x1000; + taskStatus.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; taskStatus.pcName = "memInfo"; - taskStatus.usTaskPrio = 10; + taskStatus.usTaskPrio = TEST_TASK_PRIO; ret = LOS_TaskCreate(&taskID, &taskStatus); if (ret != LOS_OK) { printf("task create failed\n"); @@ -112,7 +114,9 @@ int MemTest(void) ``` -usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 +usage = 0.458344, fragment = 0.000000, maxFreeSize = 16474928, totalFreeSize = 16474928, waterLine = 76816 + +根据实际运行环境,上文中的数据会有差异,非固定结果 ``` ## 内存泄漏检测 @@ -179,6 +183,12 @@ node size LR[0] LR[1] LR[2] 代码实现如下: +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数MemLeakTest。 + +qemu平台运行时需确保target_config.h 中对应的LOSCFG_MEM_FREE_BY_TASKID为0。 + +由于打开内存检测后,部分平台有其他任务运行,会频繁调用内存相关打印如:psp, start = xxxxx, end = xxxxxxx,请忽略打印或删除OsStackAddrGet函数中调用的打印即可。 + ``` #include @@ -198,7 +208,7 @@ void MemLeakTest(void) #### 结果验证 -编译运行输出log如下: +编译运行输出示例log如下: ``` @@ -216,7 +226,9 @@ node size LR[0] LR[1] LR[2] 0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a 0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 + +根据实际运行环境,上文中的数据会有差异,非固定结果 ``` 对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: @@ -224,7 +236,9 @@ node size LR[0] LR[1] LR[2] ``` 0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 + +根据实际运行环境,上文中的数据会有差异,非固定结果 ``` 部分汇编文件如下: @@ -246,6 +260,8 @@ node size LR[0] LR[1] LR[2] 0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a 0x80041f4: 0xbd10 POP {R4, PC} 0x80041f6: 0x0000 MOVS R0, R0 + + 根据实际运行环境,上文中的数据会有差异,非固定结果 ``` 其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 @@ -295,6 +311,12 @@ LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK:开关宏,默认关闭;若打开这 代码实现如下: +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数MemIntegrityTest。 + +qemu平台运行时需确保target_config.h 中对应的LOSCFG_MEM_FREE_BY_TASKID为0。 + +由于执行时主动触发异常,执行结束后需要重启qemu(例如打开一个新的终端界面输入killall qemu-system-arm) + ``` #include @@ -320,20 +342,28 @@ void MemIntegrityTest(void) ``` -[ERR][OsMemMagicCheckPrint], 2028, memory check error! -memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ - - broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 -/* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ - - broken node head LR info: /* 节点的LR信息需要开启内存检测功能才有有效输出 */ - LR[0]:0x0800414e - LR[1]:0x08000cc2 - LR[2]:0x00000000 - - pre node head LR info: /* 通过LR信息,可以在汇编文件中查找前节点是哪里申请,然后排查其使用的准确性 */ - LR[0]:0x08004144 - LR[1]:0x08000cc2 - LR[2]:0x00000000 -[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* 被破坏节点和其前节点的地址 */ + +/* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ +[ERR][IT_TST_INI][OsMemMagicCheckPrint], 1664, memory check error! +memory used but magic num wrong, magic num = 0x0 + + /* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ + broken node head: 0x2103d7e8 0x0 0x80000020, prev node head: 0x2103c7cc 0xabcddcba 0x80000020 + + /* 节点的LR信息需要开启前文的内存泄漏检测功能才有有效输出 */ + broken node head LR info: + LR[0]:0x2101906c + LR[1]:0x0 + LR[2]:0x0 + + /* 通过LR信息,可以在汇编文件中查找前节点是哪里申请,然后排查其使用的准确性 */ + pre node head LR info: + LR[0]:0x2101906c + LR[1]:0x0 + LR[2]:0x0 + + /* 被破坏节点和其前节点的地址 */ +[ERR][IT_TST_INI]Memory integrity check error, cur node: 0x2103d784, pre node: 0x0 + + 根据实际运行环境,上文中的数据会有差异,非固定结果 ``` 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 daa581a14689a449059bfe53265b7eb3b194f1d0..df848c5943caffd43d9e490dcbd5857383d2c2e2 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-exception.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-exception.md @@ -49,6 +49,8 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 1. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: + 本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数ExampleExcEntry。 + ``` #include #include "los_config.h" @@ -59,29 +61,30 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 #define TSK_PRIOR 4 /* 模拟异常函数 */ - - UINT32 Get_Result_Exception_0(UINT16 dividend){ - UINT32 divisor = 0; - UINT32 result = dividend / divisor; + UINT32 GetResultException0(UINT16 dividend){ + UINT32 result = *(UINT32 *)(0xffffffff); + printf("Enter GetResultException0. %u\r\n", result); return result; } - UINT32 Get_Result_Exception_1(UINT16 dividend){ - return Get_Result_Exception_0(dividend); + UINT32 GetResultException1(UINT16 dividend){ + printf("Enter GetResultException1.\r\n"); + return GetResultException0(dividend); } - UINT32 Get_Result_Exception_2(UINT16 dividend){ - return Get_Result_Exception_1(dividend); + UINT32 GetResultException2(UINT16 dividend){ + printf("Enter GetResultException2.\r\n"); + return GetResultException1(dividend); } - UINT32 Example_Exc(VOID) + UINT32 ExampleExc(VOID) { UINT32 ret; printf("Enter Example_Exc Handler.\r\n"); /* 模拟函数调用 */ - ret = Get_Result_Exception_2(TSK_PRIOR); + ret = GetResultException2(TSK_PRIOR); printf("Divided result =%u.\r\n", ret); printf("Exit Example_Exc Handler.\r\n"); @@ -90,20 +93,20 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 /* 任务测试入口函数,创建一个会发生异常的任务 */ - UINT32 Example_Exc_Entry(VOID) + UINT32 ExampleExcEntry(VOID) { UINT32 ret; - TSK_INIT_PARAM_S initParam; + TSK_INIT_PARAM_S initParam = { 0 }; /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ LOS_TaskLock(); printf("LOS_TaskLock() Success!\r\n"); - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Exc; + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleExc; initParam.usTaskPrio = TSK_PRIOR; initParam.pcName = "Example_Exc"; - initParam.uwStackSize = LOSCFG_SECURE_STACK_DEFAULT_SIZE; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ ret = LOS_TaskCreate(&g_taskExcId, &initParam); if (ret != LOS_OK) { @@ -115,99 +118,91 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 printf("Example_Exc create Success!\r\n"); - /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ - LOS_TaskUnlock(); - - return LOS_OK; - } - ``` - -1. 上述代码串口终端输出异常信息如下: + /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ + LOS_TaskUnlock(); + return LOS_OK; + } + ``` + + 述代码串口终端输出异常信息如下: + ``` - entering kernel init... LOS_TaskLock() Success! Example_Exc create Success! - Entering scheduler Enter Example_Exc Handler. - *Exception Information** - Type = 10 - ThrdPid = 4 + Enter GetResultException2. + Enter GetResultException1. + *************Exception Information************** + Type = 4 + ThrdPid = 5 Phase = exc in task - FaultAddr = 0xabababab + FaultAddr = 0xfffffffc Current task info: Task name = Example_Exc - Task ID = 4 - Task SP = 0x200051ac - Task ST = 0x20004ff0 - Task SS = 0x200 + Task ID = 5 + Task SP = 0x210549bc + Task ST = 0x21053a00 + Task SS = 0x1000 Exception reg dump: - PC = 0x80037da - LR = 0x80037fe - SP = 0x20005190 + PC = 0x2101c61a + LR = 0x2101c64d + SP = 0x210549a8 R0 = 0x4 - R1 = 0x40 - R2 = 0x4 - R3 = 0x0 - R4 = 0x4040404 + R1 = 0xa + R2 = 0x0 + R3 = 0xffffffff + R4 = 0x2103fb20 R5 = 0x5050505 R6 = 0x6060606 - R7 = 0x20005190 + R7 = 0x210549a8 R8 = 0x8080808 R9 = 0x9090909 R10 = 0x10101010 R11 = 0x11111111 - R12 = 0x12121212 + R12 = 0x0 PriMask = 0x0 xPSR = 0x41000000 ----- backtrace start ----- - backtrace 0 -- lr = 0x800381a - backtrace 1 -- lr = 0x8003836 - backtrace 2 -- lr = 0x8005a4e - backtrace 3 -- lr = 0x8000494 - backtrace 4 -- lr = 0x8008620 - backtrace 5 -- lr = 0x800282c - backtrace 6 -- lr = 0x80008a0 - backtrace 7 -- lr = 0x80099f8 - backtrace 8 -- lr = 0x800a01a - backtrace 9 -- lr = 0x800282c - backtrace 10 -- lr = 0x80008a0 - backtrace 11 -- lr = 0x80099f8 - backtrace 12 -- lr = 0x8009bf0 - backtrace 13 -- lr = 0x8009c52 - backtrace 14 -- lr = 0x80099aa + backtrace 0 -- lr = 0x2101c64c + backtrace 1 -- lr = 0x2101c674 + backtrace 2 -- lr = 0x2101c696 + backtrace 3 -- lr = 0x2101b1ec ----- backtrace end ----- - TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID name - --- -------- -------- --------- ---------- ---------- ---------- --------- ----- ---- - 0 0 Pend 0x2d0 0x104 0x200029bc 0x200027f0 0x0 0xffff Swt_Task - 1 31 Ready 0x500 0x44 0x20002f84 0x20002ac8 0x0 0xffff IdleCore000 - 2 6 Ready 0x1000 0x44 0x20003f94 0x20002fd8 0x0 0xffff TaskSampleEntry1 - 3 7 Ready 0x1000 0x44 0x20004f9c 0x20003fe0 0x0 0xffff TaskSampleEntry2 - 4 4 Running 0x200 0xec 0x200051ac 0x20004ff0 0x0 0xffff Example_Exc + TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID CPUUSE CPUUSE10s CPUUSE1s TaskEntry name + --- -------- -------- --------- --------- ---------- ---------- --------- ------ ------- --------- -------- ---------- ---- + 0 0 Pend 0x1000 0xdc 0x2104730c 0x210463e8 0 0xffff 0.0 0.0 0.0 0x2101a199 Swt_Task + 1 31 Ready 0x500 0x44 0x210478e4 0x21047428 0 0xffff 0.0 0.0 0.0 0x2101a9c9 IdleCore000 + 2 5 PendTime 0x6000 0xd4 0x2104e8f4 0x210489c8 0 0xffff 5.7 5.7 0.0 0x21016149 tcpip_thread + 3 3 Pend 0x1000 0x488 0x2104f90c 0x2104e9e8 0x1 0xffff 8.6 8.6 0.0 0x21016db5 ShellTaskEntry + 4 25 Ready 0x4000 0x460 0x21053964 0x2104f9f0 0 0xffff 9.0 8.9 0.0 0x2101c765 IT_TST_INI + 5 4 Running 0x1000 0x458 0x210549bc 0x21053a00 0 0xffff 76.5 76.6 0.0 0x2101c685 Example_Exc OS exception NVIC dump: interrupt enable register, base address: 0xe000e100, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x2001 0x0 0x0 0x0 0x0 0x0 0x0 0x0 interrupt pending register, base address: 0xe000e200, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 interrupt active register, base address: 0xe000e300, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 interrupt priority register, base address: 0xe000e400, size: 0xf0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 interrupt exception register, base address: 0xe000ed18, size: 0xc - 0x0 0x0 0xf0f00000 + 0x0 0x0 0xf0f00000 interrupt shcsr register, base address: 0xe000ed24, size: 0x4 - 0x70008 + 0x70002 interrupt control register, base address: 0xe000ed04, size: 0x4 - 0x400f806 + 0x1000e805 memory pools check: system heap memcheck over, all passed! memory pool check end! + + 根据实际运行环境,上文中的数据会有差异,非固定结果 ``` @@ -215,61 +210,68 @@ OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详 异常接管一般的定位步骤如下: +0. 确认编译时关掉优化选项,否则下述的描述内容可能被优化掉。 + 1. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为: - + ``` arm-none-eabi-objdump -S -l XXX.elf ``` 1. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。 - PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x80037da,找到当前CPU正在执行的指令行,反汇编如下所示: + PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x2101c61a,找到当前CPU正在执行的指令行,反汇编如下所示: - + ``` - UINT32 Get_Result_Exception_0(UINT16 dividend){ - 80037c8: b480 push {r7} - 80037ca: b085 sub sp, #20 - 80037cc: af00 add r7, sp, #0 - 80037ce: 4603 mov r3, r0 - 80037d0: 80fb strh r3, [r7, #6] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:10 - UINT32 divisor = 0; - 80037d2: 2300 movs r3, #0 - 80037d4: 60fb str r3, [r7, #12] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:11 - UINT32 result = dividend / divisor; - 80037d6: 88fa ldrh r2, [r7, #6] - 80037d8: 68fb ldr r3, [r7, #12] - 80037da: fbb2 f3f3 udiv r3, r2, r3 - 80037de: 60bb str r3, [r7, #8] + 2101c60c : + 2101c60c: b580 push {r7, lr} + 2101c60e: b084 sub sp, #16 + 2101c610: af00 add r7, sp, #0 + 2101c612: 4603 mov r3, r0 + 2101c614: 80fb strh r3, [r7, #6] + 2101c616: f04f 33ff mov.w r3, #4294967295 ; 0xffffffff + 2101c61a: 681b ldr r3, [r3, #0] + 2101c61c: 60fb str r3, [r7, #12] + 2101c61e: 68f9 ldr r1, [r7, #12] + 2101c620: 4803 ldr r0, [pc, #12] ; (2101c630 ) + 2101c622: f001 f92b bl 2101d87c + 2101c626: 68fb ldr r3, [r7, #12] + 2101c628: 4618 mov r0, r3 + 2101c62a: 3710 adds r7, #16 + 2101c62c: 46bd mov sp, r7 + 2101c62e: bd80 pop {r7, pc} + 2101c630: 21025f90 .word 0x21025f90 ``` - + 1. 可以看到: - 1. 异常时CPU正在执行的指令是udiv r3, r2, r3,其中r3取值为0,导致发生除零异常。 - 2. 异常发生在函数Get_Result_Exception_0中。 + 1. 异常时CPU正在执行的指令是ldr r3, [r3, #0],其中r3取值为0xffffffff,导致发生非法地址异常。 + 2. 异常发生在函数GetResultException0中。 2. 根据LR值查找异常函数的父函数。 - 包含LR值0x80037fe的反汇编如下所示: + 包含LR值0x2101c64d的反汇编如下所示: - + ``` - 080037ec : - Get_Result_Exception_1(): - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:15 - UINT32 Get_Result_Exception_1(UINT16 dividend){ - 80037ec: b580 push {r7, lr} - 80037ee: b082 sub sp, #8 - 80037f0: af00 add r7, sp, #0 - 80037f2: 4603 mov r3, r0 - 80037f4: 80fb strh r3, [r7, #6] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:16 - return Get_Result_Exception_0(dividend); - 80037f6: 88fb ldrh r3, [r7, #6] - 80037f8: 4618 mov r0, r3 - 80037fa: f7ff ffe5 bl 80037c8 - 80037fe: 4603 mov r3, r0 + 2101c634 : + 2101c634: b580 push {r7, lr} + 2101c636: b082 sub sp, #8 + 2101c638: af00 add r7, sp, #0 + 2101c63a: 4603 mov r3, r0 + 2101c63c: 80fb strh r3, [r7, #6] + 2101c63e: 4806 ldr r0, [pc, #24] ; (2101c658 ) + 2101c640: f001 f91c bl 2101d87c + 2101c644: 88fb ldrh r3, [r7, #6] + 2101c646: 4618 mov r0, r3 + 2101c648: f7ff ffe0 bl 2101c60c + 2101c64c: 4603 mov r3, r0 + 2101c64e: 4618 mov r0, r3 + 2101c650: 3708 adds r7, #8 + 2101c652: 46bd mov sp, r7 + 2101c654: bd80 pop {r7, pc} + 2101c656: bf00 nop + 2101c658: 21025fb0 .word 0x21025fb0 ``` - -1. LR值80037fe上一行是bl 80037c8 <Get_Result_Exception_0>,此处调用了异常函数,调用异常函数的父函数为Get_Result_Exception_1()。 + +1. LR值2101c648上一行是bl 2101c60c taskName = LmsTestCaseTask -runTask->taskID = 2 -***backtrace begin*** -traceback fp fixed, trace using fp = 0x402c0fd0 -traceback 0 -- lr = 0x400655a4 fp = 0x402c0ff8 -traceback 1 -- lr = 0x40065754 fp = 0x402c1010 -traceback 2 -- lr = 0x40044bd0 fp = 0x402c1038 -traceback 3 -- lr = 0x40004e14 fp = 0xcacacaca -[LMS] Dump info around address [0x4157a3c8]: - [0x4157a3a0]: 00 00 00 00 00 00 00 00 | [0x4157be3a | 0]: 1 1 - [0x4157a3a8]: ba dc cd ab 00 00 00 00 | [0x4157be3a | 4]: 2 2 - [0x4157a3b0]: 20 00 00 80 00 00 00 00 | [0x4157be3b | 0]: 2 0 - [0x4157a3b8]: 00 00 00 00 00 00 00 00 | [0x4157be3b | 4]: 0 0 - [0x4157a3c0]: 00 00 00 00 00 00 00 00 | [0x4157be3c | 0]: 0 0 - [0x4157a3c8]: [ba] dc cd ab a8 a3 57 41 | [0x4157be3c | 4]: [2] 2 - [0x4157a3d0]: 2c 1a 00 00 00 00 00 00 | [0x4157be3d | 0]: 2 3 - [0x4157a3d8]: 00 00 00 00 00 00 00 00 | [0x4157be3d | 4]: 3 3 - [0x4157a3e0]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 0]: 3 3 - [0x4157a3e8]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 4]: 3 3 - [0x4157a3f0]: 00 00 00 00 00 00 00 00 | [0x4157be3f | 0]: 3 3 -[ERR]* Kernel Address Sanitizer Error Detected End * -str[20]=0xffffffba +[ERR][TestLmsTsk]***** Kernel Address Sanitizer Error Detected Start ***** +[ERR][TestLmsTsk]Heap buffer overflow error detected +[ERR][TestLmsTsk]Illegal READ address at: [0x21040414] +[ERR][TestLmsTsk]Shadow memory address: [0x21041e84 : 6] Shadow memory value: [2] +psp, start = 21057d88, end = 21057e80 +taskName = TestLmsTsk +taskID = 5 +----- traceback start ----- +traceback 0 -- lr = 0x210099f4 +traceback 1 -- lr = 0x2101da6e +traceback 2 -- lr = 0x2101db38 +traceback 3 -- lr = 0x2101c494 +----- traceback end ----- + +[LMS] Dump info around address [0x21040414]: + + [0x21040390]: 00 00 00 00 00 00 00 00 | [0x21041e7c | 4]: 1 1 + [0x21040398]: 00 00 00 00 00 00 00 00 | [0x21041e7d | 0]: 1 1 + [0x210403a0]: 00 00 00 00 00 00 00 00 | [0x21041e7d | 4]: 1 1 + [0x210403a8]: 00 00 00 00 00 00 00 00 | [0x21041e7e | 0]: 1 1 + [0x210403b0]: 00 00 00 00 00 00 00 00 | [0x21041e7e | 4]: 1 1 + [0x210403b8]: 00 00 00 00 00 00 00 00 | [0x21041e7f | 0]: 1 1 + [0x210403c0]: 00 00 00 00 00 00 00 00 | [0x21041e7f | 4]: 1 1 + [0x210403c8]: 00 00 00 00 00 00 00 00 | [0x21041e80 | 0]: 1 1 + [0x210403d0]: 00 00 00 00 00 00 00 00 | [0x21041e80 | 4]: 1 1 + [0x210403d8]: 00 00 00 00 00 00 00 00 | [0x21041e81 | 0]: 1 1 + [0x210403e0]: 00 00 00 00 00 00 00 00 | [0x21041e81 | 4]: 1 1 + [0x210403e8]: 00 00 00 00 00 00 00 00 | [0x21041e82 | 0]: 1 1 + [0x210403f0]: 00 00 00 00 00 00 00 00 | [0x21041e82 | 4]: 1 1 + [0x210403f8]: 40 1e 04 21 05 07 00 80 | [0x21041e83 | 0]: 2 2 + [0x21040400]: 00 00 00 00 00 00 00 00 | [0x21041e83 | 4]: 0 0 + [0x21040408]: 00 00 00 00 00 00 00 00 | [0x21041e84 | 0]: 0 0 + [0x21040410]: 00 00 00 00 [f8] 03 04 21 | [0x21041e84 | 4]: 0 [2] + [0x21040418]: 00 8b 06 00 00 00 00 00 | [0x21041e85 | 0]: 2 3 + [0x21040420]: 00 00 00 00 00 00 00 00 | [0x21041e85 | 4]: 3 3 + [0x21040428]: 00 00 00 00 00 00 00 00 | [0x21041e86 | 0]: 3 3 + [0x21040430]: 00 00 00 00 00 00 00 00 | [0x21041e86 | 4]: 3 3 + [0x21040438]: 00 00 00 00 00 00 00 00 | [0x21041e87 | 0]: 3 3 + [0x21040440]: 00 00 00 00 00 00 00 00 | [0x21041e87 | 4]: 3 3 + [0x21040448]: 00 00 00 00 00 00 00 00 | [0x21041e88 | 0]: 3 3 + [0x21040450]: 00 00 00 00 00 00 00 00 | [0x21041e88 | 4]: 3 3 + [0x21040458]: 00 00 00 00 00 00 00 00 | [0x21041e89 | 0]: 3 3 + [0x21040460]: 00 00 00 00 00 00 00 00 | [0x21041e89 | 4]: 3 3 + [0x21040468]: 00 00 00 00 00 00 00 00 | [0x21041e8a | 0]: 3 3 + [0x21040470]: 00 00 00 00 00 00 00 00 | [0x21041e8a | 4]: 3 3 + [0x21040478]: 00 00 00 00 00 00 00 00 | [0x21041e8b | 0]: 3 3 + [0x21040480]: 00 00 00 00 00 00 00 00 | [0x21041e8b | 4]: 3 3 + [0x21040488]: 00 00 00 00 00 00 00 00 | [0x21041e8c | 0]: 3 3 + [0x21040490]: 00 00 00 00 00 00 00 00 | [0x21041e8c | 4]: 3 3 +[ERR][TestLmsTsk]***** Kernel Address Sanitizer Error Detected End ***** +str[20]=0xfffffff8 ######LmsTestOsmallocOverflow stop ###### -###### LmsTestUseAfterFree start ###### -[ERR]* Kernel Address Sanitizer Error Detected Start * -[ERR]Use after free error detected -[ERR]Illegal READ address at: [0x4157a3d4] -[ERR]Shadow memory address: [0x4157be3d : 2] Shadow memory value: [3] -OsBackTrace fp = 0x402c0f90 -runTask->taskName = LmsTestCaseTask -runTask->taskID = 2 -***backtrace begin*** -traceback fp fixed, trace using fp = 0x402c0fd8 -traceback 0 -- lr = 0x40065680 fp = 0x402c0ff8 -traceback 1 -- lr = 0x40065758 fp = 0x402c1010 -traceback 2 -- lr = 0x40044bd0 fp = 0x402c1038 -traceback 3 -- lr = 0x40004e14 fp = 0xcacacaca -[LMS] Dump info around address [0x4157a3d4]: - [0x4157a3a8]: ba dc cd ab 00 00 00 00 | [0x4157be3a | 4]: 2 2 - [0x4157a3b0]: 20 00 00 80 00 00 00 00 | [0x4157be3b | 0]: 2 0 - [0x4157a3b8]: 00 00 00 00 00 00 00 00 | [0x4157be3b | 4]: 0 0 - [0x4157a3c0]: 00 00 00 00 00 00 00 00 | [0x4157be3c | 0]: 0 0 - [0x4157a3c8]: ba dc cd ab a8 a3 57 41 | [0x4157be3c | 4]: 2 2 - [0x4157a3d0]: 2c 1a 00 00 [00] 00 00 00 | [0x4157be3d | 0]: 2 [3] - [0x4157a3d8]: 00 00 00 00 00 00 00 00 | [0x4157be3d | 4]: 3 3 - [0x4157a3e0]: 00 00 00 00 00 00 00 00 | [0x4157be3e | 0]: 3 3 - [0x4157a3e8]: ba dc cd ab c8 a3 57 41 | [0x4157be3e | 4]: 2 2 - [0x4157a3f0]: 0c 1a 00 00 00 00 00 00 | [0x4157be3f | 0]: 2 3 - [0x4157a3f8]: 00 00 00 00 00 00 00 00 | [0x4157be3f | 4]: 3 3 -[ERR]* Kernel Address Sanitizer Error Detected End * + +######LmsTestUseAfterFree start ###### +[ERR][TestLmsTsk]***** Kernel Address Sanitizer Error Detected Start ***** +[ERR][TestLmsTsk]Use after free error detected +[ERR][TestLmsTsk]Illegal READ address at: [0x2104041c] +[ERR][TestLmsTsk]Shadow memory address: [0x21041e85 : 2] Shadow memory value: [3] +psp, start = 21057d90, end = 21057e80 +taskName = TestLmsTsk +taskID = 5 +----- traceback start ----- +traceback 0 -- lr = 0x210099f4 +traceback 1 -- lr = 0x2101daec +traceback 2 -- lr = 0x2101db3c +traceback 3 -- lr = 0x2101c494 +----- traceback end ----- + +[LMS] Dump info around address [0x2104041c]: + + [0x21040398]: 00 00 00 00 00 00 00 00 | [0x21041e7d | 0]: 1 1 + [0x210403a0]: 00 00 00 00 00 00 00 00 | [0x21041e7d | 4]: 1 1 + [0x210403a8]: 00 00 00 00 00 00 00 00 | [0x21041e7e | 0]: 1 1 + [0x210403b0]: 00 00 00 00 00 00 00 00 | [0x21041e7e | 4]: 1 1 + [0x210403b8]: 00 00 00 00 00 00 00 00 | [0x21041e7f | 0]: 1 1 + [0x210403c0]: 00 00 00 00 00 00 00 00 | [0x21041e7f | 4]: 1 1 + [0x210403c8]: 00 00 00 00 00 00 00 00 | [0x21041e80 | 0]: 1 1 + [0x210403d0]: 00 00 00 00 00 00 00 00 | [0x21041e80 | 4]: 1 1 + [0x210403d8]: 00 00 00 00 00 00 00 00 | [0x21041e81 | 0]: 1 1 + [0x210403e0]: 00 00 00 00 00 00 00 00 | [0x21041e81 | 4]: 1 1 + [0x210403e8]: 00 00 00 00 00 00 00 00 | [0x21041e82 | 0]: 1 1 + [0x210403f0]: 00 00 00 00 00 00 00 00 | [0x21041e82 | 4]: 1 1 + [0x210403f8]: 40 1e 04 21 05 07 00 80 | [0x21041e83 | 0]: 2 2 + [0x21040400]: 00 00 00 00 00 00 00 00 | [0x21041e83 | 4]: 0 0 + [0x21040408]: 00 00 00 00 00 00 00 00 | [0x21041e84 | 0]: 0 0 + [0x21040410]: 00 00 00 00 f8 03 04 21 | [0x21041e84 | 4]: 0 2 + [0x21040418]: 05 8b 06 00 [00] 00 00 00 | [0x21041e85 | 0]: 2 [3] + [0x21040420]: 00 00 00 00 00 00 00 00 | [0x21041e85 | 4]: 3 3 + [0x21040428]: 00 00 00 00 00 00 00 00 | [0x21041e86 | 0]: 3 3 + [0x21040430]: 14 04 04 21 00 84 06 00 | [0x21041e86 | 4]: 2 2 + [0x21040438]: 00 00 00 00 00 00 00 00 | [0x21041e87 | 0]: 3 3 + [0x21040440]: 00 00 00 00 00 00 00 00 | [0x21041e87 | 4]: 3 3 + [0x21040448]: 00 00 00 00 00 00 00 00 | [0x21041e88 | 0]: 3 3 + [0x21040450]: 00 00 00 00 00 00 00 00 | [0x21041e88 | 4]: 3 3 + [0x21040458]: 00 00 00 00 00 00 00 00 | [0x21041e89 | 0]: 3 3 + [0x21040460]: 00 00 00 00 00 00 00 00 | [0x21041e89 | 4]: 3 3 + [0x21040468]: 00 00 00 00 00 00 00 00 | [0x21041e8a | 0]: 3 3 + [0x21040470]: 00 00 00 00 00 00 00 00 | [0x21041e8a | 4]: 3 3 + [0x21040478]: 00 00 00 00 00 00 00 00 | [0x21041e8b | 0]: 3 3 + [0x21040480]: 00 00 00 00 00 00 00 00 | [0x21041e8b | 4]: 3 3 + [0x21040488]: 00 00 00 00 00 00 00 00 | [0x21041e8c | 0]: 3 3 + [0x21040490]: 00 00 00 00 00 00 00 00 | [0x21041e8c | 4]: 3 3 + [0x21040498]: 00 00 00 00 00 00 00 00 | [0x21041e8d | 0]: 3 3 +[ERR][TestLmsTsk]***** Kernel Address Sanitizer Error Detected End ***** str[ 0]=0x 0 ######LmsTestUseAfterFree stop ###### ``` 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 664a106625caeff2456c175ab1a0eece8b625b0d..a50b89c619b13944c85e65ad6e06cd72c4c37243 100644 --- a/zh-cn/device-dev/kernel/kernel-mini-memory-trace.md +++ b/zh-cn/device-dev/kernel/kernel-mini-memory-trace.md @@ -42,7 +42,7 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 - IDENTITY类型UINTPTR,表示事件操作的主体对象。 - Params类型UINTPTR,表示事件的参数。 - 对文件fd读写操作的简易插桩示例: - + ``` /* 假设自定义读操作为type: 1, 写操作为type: 2 */ LOS_TRACE_EASY(1, fd, flag, size); /* 在读fd文件的适当位置插入 */ @@ -62,7 +62,7 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 2. 定义FS模块的具体事件类型 - + ``` /* 定义规范为#TYPE# = TRACE_#MOD#_FLAG | NUMBER, */ FS_READ = TRACE_FS_FLAG | 0; /* 读文件 */ @@ -71,7 +71,7 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 3. 定义事件参数 - + ``` /* 定义规范为#TYPE#_PARAMS(IDENTITY, parma1...) IDENTITY, ... */ #define FS_READ_PARAMS(fp, fd, flag, size) fp, fd, flag, size /* 宏定义的参数对应于Trace缓冲区中记录的事件参数,用户可对任意参数字段进行裁剪 */ @@ -80,7 +80,7 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 4. 在目标代码中插桩 - + ``` /* 定义规范为LOS_TRACE(#TYPE#, #TYPE#_PARAMS(IDENTITY, parma1...)) */ LOS_TRACE(FS_READ, fp, fd, flag, size); /* 读文件操作的代码桩 */ @@ -178,7 +178,9 @@ OpenHarmony LiteOS-M内核的Trace模块提供下面几种功能,接口详细 示例代码如下: - +本演示代码在 ./kernel/liteos_m/testsuites/src/osTest.c 中编译验证,在TestTaskEntry中调用验证入口函数ExampleTraceTest。 + + ``` #include "los_trace.h" UINT32 g_traceTestTaskId; @@ -200,9 +202,9 @@ VOID Example_Trace(VOID) LOS_TraceStop(); LOS_TraceRecordDump(FALSE); } -UINT32 Example_Trace_test(VOID){ +UINT32 ExampleTraceTest(VOID){ UINT32 ret; - TSK_INIT_PARAM_S traceTestTask; + TSK_INIT_PARAM_S traceTestTask = { 0 }; /* 创建用于trace测试的任务 */ memset(&traceTestTask, 0, sizeof(TSK_INIT_PARAM_S)); traceTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Trace; @@ -229,7 +231,7 @@ UINT32 Example_Trace_test(VOID){ 输出结果如下: - + ``` ***TraceInfo begin*** clockFreq = 50000000 @@ -244,6 +246,8 @@ Index Time(cycles) EventType CurTask Identity params 6 0x3706f804 0x45 0x1 0x0 0x1f 0x4 0x0 7 0x37070e59 0x45 0x0 0x1 0x0 0x8 0x1f ***TraceInfo end*** + +根据实际运行环境,上文中的数据会有差异,非固定结果 ``` 输出的事件信息包括:发生时间、事件类型、事件发生在哪个任务中、事件操作的主体对象、事件的其他参数。 @@ -258,7 +262,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-apx-bitwise.md b/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md index 68cc022a69fb0ec50e8fb25b71b78101c77405e7..a94c73c188f659e871b711556bc095b39c5a1420 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-bitwise.md @@ -14,9 +14,9 @@ | **功能分类** | **接口描述** | | -------- | -------- | -| 置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位 | ## 编程实例 @@ -34,7 +34,10 @@ 4. 获取标志位为1的最低bit位。 - +### 编程示例 + +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数BitSample。 + ``` #include "los_bitmap.h" #include "los_printf.h" 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 d13c006214da35581213e47da24e583cb16b861a..782dd68968e5c741075bb5687e651e7923ae79a8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-dll.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-dll.md @@ -17,10 +17,10 @@ | 增加节点 | - 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_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_DL_LIST_FOR_EACH:遍历双向链表
- LOS_DL_LIST_FOR_EACH_SAFE:遍历双向链表,并存储当前节点的后继节点用于安全校验 | +| 遍历包含双向链表的结构体 | - LOS_DL_LIST_FOR_EACH_ENTRY:遍历指定双向链表,获取包含该链表节点的结构体地址
- LOS_DL_LIST_FOR_EACH_ENTRY_SAFE:遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址 | ## 开发流程 @@ -48,10 +48,10 @@ > - 如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。 - **编程实例** +## 编程实例 -**实例描述** +### 实例描述 本实例实现如下功能: @@ -64,7 +64,11 @@ 4. 测试操作是否成功。 +### 编程示例 +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ListSample + +示例代码如下: ``` #include "stdio.h" 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 229046a8a171f82ed9260cdf567da6ecc43b8a98..58bca463e0917145fd0fa437f854d9f4725fd16b 100644 --- a/zh-cn/device-dev/kernel/kernel-small-apx-library.md +++ b/zh-cn/device-dev/kernel/kernel-small-apx-library.md @@ -15,22 +15,24 @@ musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony 标准库支持接口的详细情况请参考C库的API文档,其中也涵盖了与POSIX标准之间的差异说明。 -## 操作实例 +### 编程实例 + + +#### 实例描述 在本示例中,主线程创建了THREAD_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread_join方法等待所有线程执行结束。 - +#### 编程示例 + +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExamplePosix。 + +示例代码如下: + ``` #include #include #include -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - #define THREAD_NUM 3 int g_startNum = 0; /* 启动的线程数 */ int g_wakenNum = 0; /* 唤醒的线程数 */ @@ -40,10 +42,8 @@ struct testdata { pthread_cond_t cond; } g_td; -/* - * 子线程入口函数 - */ -static void *ChildThreadFunc(void *arg) +/* 子线程入口函数 */ +static VOID *ChildThreadFunc(VOID *arg) { int rc; pthread_t self = pthread_self(); @@ -51,7 +51,7 @@ static void *ChildThreadFunc(void *arg) /* 获取mutex锁 */ rc = pthread_mutex_lock(&g_td.mutex); if (rc != 0) { - printf("ERROR:take mutex lock failed, error code is %d!\n", rc); + dprintf("ERROR:take mutex lock failed, error code is %d!\n", rc); goto EXIT; } @@ -61,7 +61,7 @@ static void *ChildThreadFunc(void *arg) /* 等待cond条件变量 */ rc = pthread_cond_wait(&g_td.cond, &g_td.mutex); if (rc != 0) { - printf("ERROR: pthread condition wait failed, error code is %d!\n", rc); + dprintf("ERROR: pthread condition wait failed, error code is %d!\n", rc); (void)pthread_mutex_unlock(&g_td.mutex); goto EXIT; } @@ -69,7 +69,7 @@ static void *ChildThreadFunc(void *arg) /* 尝试获取mutex锁,正常场景,此处无法获取锁 */ rc = pthread_mutex_trylock(&g_td.mutex); if (rc == 0) { - printf("ERROR: mutex gets an abnormal lock!\n"); + dprintf("ERROR: mutex gets an abnormal lock!\n"); goto EXIT; } @@ -79,14 +79,14 @@ static void *ChildThreadFunc(void *arg) /* 释放mutex锁 */ rc = pthread_mutex_unlock(&g_td.mutex); if (rc != 0) { - printf("ERROR: mutex release failed, error code is %d!\n", rc); + dprintf("ERROR: mutex release failed, error code is %d!\n", rc); goto EXIT; } EXIT: return NULL; } -static int testcase(void) +static int ExamplePosix(VOID) { int i, rc; pthread_t thread[THREAD_NUM]; @@ -94,14 +94,14 @@ static int testcase(void) /* 初始化mutex锁 */ rc = pthread_mutex_init(&g_td.mutex, NULL); if (rc != 0) { - printf("ERROR: mutex init failed, error code is %d!\n", rc); + dprintf("ERROR: mutex init failed, error code is %d!\n", rc); goto ERROROUT; } /* 初始化cond条件变量 */ rc = pthread_cond_init(&g_td.cond, NULL); if (rc != 0) { - printf("ERROR: pthread condition init failed, error code is %d!\n", rc); + dprintf("ERROR: pthread condition init failed, error code is %d!\n", rc); goto ERROROUT; } @@ -109,10 +109,11 @@ static int testcase(void) for (i = 0; i < THREAD_NUM; i++) { rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL); if (rc != 0) { - printf("ERROR: pthread create failed, error code is %d!\n", rc); + dprintf("ERROR: pthread create failed, error code is %d!\n", rc); goto ERROROUT; } } + dprintf("pthread_create ok\n"); /* 等待所有子线程都完成mutex锁的获取 */ while (g_startNum < THREAD_NUM) { @@ -122,14 +123,14 @@ static int testcase(void) /* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */ rc = pthread_mutex_lock(&g_td.mutex); if (rc != 0) { - printf("ERROR: mutex lock failed, error code is %d\n", rc); + dprintf("ERROR: mutex lock failed, error code is %d\n", rc); goto ERROROUT; } /* 释放mutex锁 */ rc = pthread_mutex_unlock(&g_td.mutex); if (rc != 0) { - printf("ERROR: mutex unlock failed, error code is %d!\n", rc); + dprintf("ERROR: mutex unlock failed, error code is %d!\n", rc); goto ERROROUT; } @@ -137,7 +138,7 @@ static int testcase(void) /* 在cond条件变量上广播信号 */ rc = pthread_cond_signal(&g_td.cond); if (rc != 0) { - printf("ERROR: pthread condition failed, error code is %d!\n", rc); + dprintf("ERROR: pthread condition failed, error code is %d!\n", rc); goto ERROROUT; } } @@ -146,52 +147,42 @@ static int testcase(void) /* 检查是否所有子线程都已被唤醒 */ if (g_wakenNum != THREAD_NUM) { - printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum); + dprintf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum); goto ERROROUT; } + dprintf("all threads awaked\n"); /* join所有子线程,即等待其结束 */ for (i = 0; i < THREAD_NUM; i++) { rc = pthread_join(thread[i], NULL); if (rc != 0) { - printf("ERROR: pthread join failed, error code is %d!\n", rc); + dprintf("ERROR: pthread join failed, error code is %d!\n", rc); goto ERROROUT; } } + dprintf("all threads join ok\n"); /* 销毁cond条件变量 */ rc = pthread_cond_destroy(&g_td.cond); if (rc != 0) { - printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc); + dprintf("ERROR: pthread condition destroy failed, error code is %d!\n", rc); goto ERROROUT; } return 0; ERROROUT: return -1; } +``` -/* - * 示例代码主函数 - */ -int main(int argc, char *argv[]) -{ - int rc; +#### 验证结果 - /* 启动测试函数 */ - rc = testcase(); - if (rc != 0) { - printf("ERROR: testcase failed!\n"); - } + 输出结果如下: - return 0; -} -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ ``` - +pthread_create ok +all threads awaked +all threads join ok +``` ## 与Linux标准库差异 @@ -209,20 +200,17 @@ int main(int argc, char *argv[]) ### 内存 -**h2与Linux mmap的差异** +**与Linux mmap的差异** mmap接口原型为:void \*mmap (void \*addr, size_t length, int prot, int flags, int fd, off_t offset)。 其中,参数fd的生命周期实现与Linux glibc存在差异。具体体现在,glibc在成功调用mmap进行映射后,可以立即释放fd句柄。在OpenHarmony内核中,不允许用户在映射成功后立即关闭相关fd,只允许在取消映射munmap后再进行fd的close操作。如果用户不进行fd的close操作,操作系统将在进程退出时对该fd进行回收。 - -**h2代码举例** +**代码举例** Linux目前支持的情况如下: - - ``` int main(int argc, char *argv[]) { @@ -239,7 +227,7 @@ int main(int argc, char *argv[]) perror("mmap"); exit(EXIT_FAILURE); } - close(fd); /* OpenHarmony does not support closing fd immediately after the mapping is successful. */ + close(fd); /* OpenHarmony does not support closing fd immediately after the mapping is successful. */ ... exit(EXIT_SUCCESS); } @@ -247,7 +235,7 @@ int main(int argc, char *argv[]) OpenHarmony支持的情况如下: - + ``` int main(int argc, char *argv[]) { @@ -266,7 +254,7 @@ int main(int argc, char *argv[]) } ... munmap(addr, length); - close(fd); /* Close fd after the munmap is canceled. */ + close(fd); /* Close fd after the munmap is canceled. */ exit(EXIT_SUCCESS); } ``` 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 ac9755b5eea1c077d3646635cd4bac19667271ea..366928f4f4c103f9a2244f1f48256f1a1b7a05c0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-atomic.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-atomic.md @@ -16,19 +16,17 @@ OpenHarmony系统通过对ARMv6架构中的LDREX和STREX进行封装,向用户 - LDREX Rx, [Ry] 读取内存中的值,并标记对该段内存的独占访问: - - 读取寄存器Ry指向的4字节内存数据,保存到Rx寄存器中。 - 对Ry指向的内存区域添加独占访问标记。 - STREX Rf, Rx, [Ry] 检查内存是否有独占访问标记,如果有则更新内存值并清空标记,否则不更新内存: - - 有独占访问标记 - - 将寄存器Rx中的值更新到寄存器Ry指向的内存。 - - 标志寄存器Rf置为0。 + - 将寄存器Rx中的值更新到寄存器Ry指向的内存。 + - 标志寄存器Rf置为0。 - 没有独占访问标记 - - 不更新内存。 - - 标志寄存器Rf置为1。 + - 不更新内存。 + - 标志寄存器Rf置为1。 - 判断标志寄存器 - 标志寄存器为0时,退出循环,原子操作结束。 @@ -40,36 +38,36 @@ OpenHarmony系统通过对ARMv6架构中的LDREX和STREX进行封装,向用户 ### 接口说明 -OpenHarmony LiteOS-A内核的原子操作模块提供下面几种功能,接口详细信息可以查看API参考。 +OpenHarmony LiteOS-A内核的原子操作模块提供以下几种功能。 **表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内存数据 | ### 开发流程 @@ -77,7 +75,7 @@ OpenHarmony LiteOS-A内核的原子操作模块提供下面几种功能,接口 有多个任务对同一个内存数据进行加减或交换等操作时,使用原子操作保证结果的可预知性。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> 原子操作接口仅支持整型数据。 +> 原子操作接口仅支持整型数据。 ### 编程实例 @@ -96,7 +94,7 @@ OpenHarmony LiteOS-A内核的原子操作模块提供下面几种功能,接口 示例代码如下: - + ``` #include "los_hwi.h" #include "los_atomic.h" @@ -159,7 +157,7 @@ UINT32 Example_AtomicTaskEntry(VOID) **结果验证** - + ``` g_sum = 0 -``` +``` \ No newline at end of file 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 ab1018409e3517cf543bf383a51136b23e92f523..79fbfb580cbb93dba338293e60261b552834e288 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md @@ -3,16 +3,28 @@ ## 基本概念 -中断是指出现需要时,CPU暂停执行当前程序,转而执行新程序的过程。即在程序运行过程中,出现了一个必须由CPU立即处理的事务。此时,CPU暂时中止当前程序的执行转而处理这个事务,这个过程就叫做中断。通过中断机制,可以使CPU避免把大量时间耗费在等待、查询外设状态的操作上,大大提高系统实时性以及执行效率。 +中断是指出现需要时,CPU暂停执行当前程序,转而执行新程序的过程。即在程序运行过程中,出现了一个必须由CPU立即处理的事务,此时CPU暂时中止当前程序的执行转而处理这个事务,这个过程就叫做中断。通过中断机制,可以使CPU避免把大量时间耗费在等待、查询外设状态的操作上,大大提高系统实时性以及执行效率。 + +目前的中断支持有 + ++ 中断初始化 ++ 中断创建 ++ 开/关中断 ++ 恢复中断 ++ 删除中断 异常处理是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,例如虚拟内存缺页异常、打印异常发生时函数的调用栈信息、CPU现场信息、任务的堆栈情况等。 ## 运行机制 -外设可以在没有CPU介入的情况下完成一定的工作,但某些情况下也需要CPU为其执行一定的工作。通过中断机制,在外设不需要CPU介入时,CPU可以执行其它任务,而当外设需要CPU时,产生一个中断信号,该信号连接至中断控制器。中断控制器是一方面接收其它外设中断引脚的输入,另一方面它会发出中断信号给CPU。可以通过对中断控制器编程来打开和关闭中断源、设置中断源的优先级和触发方式。常用的中断控制器有VIC(Vector Interrupt Controller)和GIC(General Interrupt Controller)。在ARM Cortex-A7中使用的中断控制器是GIC。CPU收到中断控制器发送的中断信号后,中断当前任务来响应中断请求。 +外设可以在没有CPU介入的情况下完成一定的工作,但某些情况下也需要CPU为其执行一定的工作。通过中断机制,在外设不需要CPU介入时,CPU可以执行其它任务,而当外设需要CPU时,产生一个中断信号,该信号连接至中断控制器。 + +中断控制器一方面接收其它外设中断引脚的输入,另一方面会发出中断信号给CPU。可以通过对中断控制器编程来打开和关闭中断源、设置中断源的优先级和触发方式。常用的中断控制器有VIC(Vector Interrupt Controller)和GIC(General Interrupt Controller)。在ARM Cortex-A7中使用的中断控制器是GIC。 -异常处理就是可以打断CPU正常运行流程的一些事情,如未定义指令异常、试图修改只读的数据异常、不对齐的地址访问异常等。当异常发生时,CPU暂停当前的程序,先处理异常事件,然后再继续执行被异常打断的程序。 +CPU收到中断控制器发送的中断信号后,中断当前任务来响应中断请求。 + +异常指可以打断CPU正常运行流程的一些事情,如未定义指令异常、试图修改只读的数据异常、不对齐的地址访问异常等。当异常发生时,CPU暂停当前的程序,先处理异常事件,然后再继续执行被异常打断的程序。 以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的入口函数。 @@ -28,11 +40,27 @@ 异常处理为内部机制,不对外提供接口,中断模块提供对外接口如下: - | 功能分类 | 接口描述 | -| -------- | -------- | -| 创建和删除中断 | - 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_IntLock关闭所有中断之前的状态 | + +##### 获取系统中断信息 + +| 接口名 | 接口描述 | +| ----------------------- | ------------------------ | +| LOS_GetSystemHwiMaximum | 获取系统支持的最大中断数 | + ### 开发流程 @@ -53,32 +81,30 @@ 2. 删除中断。 -代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI_NUM_TEST产生中断时,会调用中断处理函数: - +代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI_NUM_TEST产生中断时,会调用中断处理函数(该示例代码的测试函数可以加在kernel/liteos_a/testsuites/kernel/src/osTest.c中的TestTaskEntry中进行测试): - -``` +```c #include "los_hwi.h" /*中断处理函数*/ STATIC VOID HwiUsrIrq(VOID) { - printf("in the func HwiUsrIrq \n"); + PRINK("in the func HwiUsrIrq \n"); } static UINT32 Example_Interrupt(VOID) { UINT32 ret; - HWI_HANDLE_T hwiNum = 7; - HWI_PRIOR_T hwiPrio = 3; + HWI_HANDLE_T hwiNum = 7; // 7: 使用的中断号 + HWI_PRIOR_T hwiPrio = 3; // 3: 中断优先级 HWI_MODE_T mode = 0; HWI_ARG_T arg = 0; /*创建中断*/ ret = LOS_HwiCreate(hwiNum, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, (HwiIrqParam *)arg); - if(ret == LOS_OK){ - printf("Hwi create success!\n"); + if (ret == LOS_OK) { + PRINK("Hwi create success!\n"); } else { - printf("Hwi create failed!\n"); + PRINK("Hwi create failed!\n"); return LOS_NOK; } @@ -86,11 +112,11 @@ static UINT32 Example_Interrupt(VOID) LOS_TaskDelay(50); /*删除中断*/ - ret = LOS_HwiDelete(hwiNum, (HwiIrqParam *)arg); - if(ret == LOS_OK){ - printf("Hwi delete success!\n"); + ret = LOS_HwiDelete(hwiNum, (HwiIrqParam *)arg); + if (ret == LOS_OK) { + PRINK("Hwi delete success!\n"); } else { - printf("Hwi delete failed!\n"); + PRINK("Hwi delete failed!\n"); return LOS_NOK; } return LOS_OK; @@ -102,7 +128,6 @@ static UINT32 Example_Interrupt(VOID) 编译运行得到的结果为: - ``` Hwi create success! Hwi delete success! 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 388c81166d1afafb8a86dda0a59567394985ae90..85eac776972bb42ad8ac8071f2518052acb083ef 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 @@ -3,7 +3,7 @@ ## 基本概念 -进程是系统资源管理的最小单元。OpenHarmony LiteOS-A内核提供的进程模块主要用于实现用户态进程的隔离,内核态被视为一个进程空间,不存在其它进程(KIdle除外,KIdle进程是系统提供的空闲进程,和KProcess共享一个进程空间)。 +进程是系统资源管理的最小单元。OpenHarmony LiteOS-A 内核提供的进程模块主要用于实现用户态进程的隔离,内核态被视为一个进程空间,不存在其它进程(KIdle除外,KIdle进程是系统提供的空闲进程,和KProcess共享一个进程空间。KProcess 是内核态进程的根进程,KIdle 是其子进程)。 - 进程模块主要为用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。 @@ -36,10 +36,10 @@ **进程状态迁移说明:** - Init→Ready: - 进程创建或fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程插入调度队列,此时进程进入就绪状态。 + 进程创建或 fork 时,拿到对应进程控制块后进入 Init 状态,即进程初始化阶段,当该阶段完成后进程将被插入调度队列,此时进程进入就绪状态。 - Ready→Running: - 进程创建后进入就绪态,发生进程切换时,就绪列表中最高优先级的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存,但对外呈现的进程状态为运行态。 + 进程创建后进入就绪态,发生进程切换时,就绪列表中优先级最高且获得时间片的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存,但对外呈现的进程状态为运行态。 - Running→Pending: 进程在最后一个线程转为阻塞态时, 进程内所有的线程均处于阻塞态,此时进程同步进入阻塞态,然后发生进程切换。 @@ -54,7 +54,7 @@ 进程由运行态转为就绪态的情况有以下两种: 1. 有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。 - 2. 若进程的调度策略为LOS_SCHED_RR,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。 + 2. 若进程的调度策略为 LOS_SCHED_RR(时间片轮转),且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。 - Running→Zombies: 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。 @@ -78,16 +78,47 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离, ### 接口说明 - **表1** 进程管理模块接口 +##### 表1 进程及进程组 + +| 接口名 | 接口描述 | +| ------------------------- | ---------------------- | +| LOS_GetCurrProcessID | 获取当前进程的进程ID | +| LOS_GetProcessGroupID | 获取指定进程的进程组ID | +| LOS_GetCurrProcessGroupID | 获取当前进程的进程组ID | + +##### 表2 用户及用户组 + +| 接口名 | 接口描述 | +| ----------------- | ---------------------------------------- | +| LOS_GetUserID | 获取当前进程的用户ID | +| LOS_GetGroupID | 获取当前进程的用户组ID | +| LOS_CheckInGroups | 检查指定用户组ID是否在当前进程的用户组内 | + +##### 表3 进程调度控制 + +| 接口名 | 接口 | +| ----------------------- | -------------------------------------------- | +| LOS_GetProcessScheduler | 获取指定进程的调度策略 | +| LOS_SetProcessScheduler | 设置指定进程的调度参数,包括优先级和调度策略 | +| LOS_SetProcessPriority | 设置进程优先级 | +| LOS_GetProcessPriority | 获取进程优先级 | + +##### 表4 系统进程信息获取 + +| 接口名 | 接口描述 | +| --------------------------- | -------------------------- | +| LOS_GetSystemProcessMaximum | 获取系统支持的最大进程数目 | +| LOS_GetUsedPIDList | 获得已使用的进程ID列表 | + +##### 表5 进程创建与结束 + +| 接口名 | 接口描述 | +| ---------- | -------------------------- | +| LOS_Fork | 创建子进程 | +| LOS_Wait | 等待子进程结束并回收子进程 | +| LOS_Waitid | 等待相应ID的进程结束 | +| LOS_Exit | 退出进程 | -| 功能分类 | 接口描述 | -| -------- | -------- | -| 进程调度参数控制 | - 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:获取系统支持的最大进程数目 | ### 开发流程 @@ -96,7 +127,7 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离, > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > - idle线程的数量跟随CPU核心数,每个CPU均有一个相应的idle线程。 -> +> > - 不支持创建除KProcess和KIdle进程之外的其它内核态进程。 -> +> > - 用户态进程通过系统调用进入内核态后创建的线程属于KProcess, 不属于当前用户态进程。 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 8a6609d70d616c72d24a878e9adecde79bb16ca6..c13860cf5f71ca1f1693f6226af4ba5212f0cb17 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 @@ -3,18 +3,18 @@ ## 基本概念 -OpenHarmony LiteOS-A内核 了高优先级优先+同优先级时间片轮转的抢占式调度机制,系统从启动开始基于real time的时间轴向前运行,使得该调度算法具有很好的实时性。 +OpenHarmony LiteOS-A内核采用了高优先级优先 + 同优先级时间片轮转的抢占式调度机制,系统从启动开始基于real time的时间轴向前运行,使得该调度算法具有很好的实时性。 -OpenHarmony 的调度算法将tickless机制天然嵌入到调度算法中,一方面使得系统具有更低的功耗,另一方面也使得tick中断按需响应,减少无用的tick中断响应,进一步提高系统的实时性。 +OpenHarmony 的调度算法将 tickless 机制天然嵌入到调度算法中,一方面使得系统具有更低的功耗,另一方面也使得 tick 中断按需响应,减少无用的 tick 中断响应,进一步提高系统的实时性。 -OpenHarmony 的进程调度策略支持SCHED_RR,线程调度策略支持SCHED_RR和SCHED_FIFO。 +OpenHarmony 的进程调度策略支持 SCHED_RR(时间片轮转),线程调度策略支持 SCHED_RR 和 SCHED_FIFO(先进先出)。 OpenHarmony 调度的最小单元为线程。 ## 运行机制 -OpenHarmony 采用进程优先级队列+线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。 +OpenHarmony 采用进程优先级队列 + 线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。 **图1** 调度优先级桶队列示意图 @@ -31,9 +31,13 @@ OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中 ### 接口说明 - | 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 触发系统调度 | LOS_Schedule | 触发系统调度 | +| 接口**名称** | 描述 | +| -------- | -------- | +| LOS_Schedule | 触发系统调度 | +| LOS_GetTaskScheduler | 获取指定任务的调度策略 | +| LOS_SetTaskScheduler | 设置指定任务的调度策略 | +| LOS_GetProcessScheduler | 获取指定进程的调度策略 | +| LOS_SetProcessScheduler | 设置指定进程的调度参数,包括优先级和调度策略 | ### 开发流程 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 a7934c306676f213033cf5b644d15555ecda34c9..ffe02de8d9733d24fad0a490e73a8fa9747872dc 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 @@ -52,7 +52,7 @@ OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0 有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,并加入就绪列表中。 - Running→Exit: - 运行中的任务运行结束,任务状态由运行态变为退出态。若为设置了分离属性(LOS_TASK_STATUS_DETACHED)的任务,运行结束后将直接销毁。 + 运行中的任务运行结束,任务状态由运行态变为退出态。若为设置了分离属性( 由头文件 los_task.h 中的宏定义 LOS_TASK_STATUS_DETACHED 设置)的任务,运行结束后将直接销毁。 ## 运行机制 @@ -67,16 +67,58 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起 ### 接口说明 - | 功能分类 | 接口描述 | -| -------- | -------- | -| 任务的创建和删除 | - 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 | +##### 表1 任务的创建和删除 + +| 接口名 | 接口描述 | +| ------------------ | ------------------------------------------------------------ | +| LOS_TaskCreate | 创建任务,若所创建任务的优先级比当前的运行的任务优先级高且任务调度没有锁定,
则该任务将被调度进入运行态 | +| LOS_TaskCreateOnly | 创建任务并阻塞,任务恢复前不会将其加入就绪队列中 | +| LOS_TaskDelete | 删除指定的任务,回收其任务控制块和任务栈所消耗的资源 | + +##### 表2 任务的状态控制 + +| 接口名 | 接口描述 | +| --------------- | ------------------------------------------------------------ | +| LOS_TaskResume | 恢复挂起的任务 | +| LOS_TaskSuspend | 挂起指定的任务,该任务将从就绪任务队列中移除 | +| LOS_TaskJoin | 阻塞当前任务,等待指定任务运行结束并回收其资源 | +| LOS_TaskDetach | 修改任务的 joinable 属性为 detach 属性,detach 属性的任务运行结束会自动回收任务控制块资源 | +| LOS_TaskDelay | 延迟当前任务的执行,在延后指定的时间(tick数)后可以被调度 | +| LOS_TaskYield | 将当前任务从具有相同优先级的任务队列,移动到就绪任务队列的末尾 | + +##### 表3 任务调度 + +| 接口名 | 接口描述 | +| -------------------- | ------------------------------------------------------------ | +| LOS_TaskLock | 锁定任务调度,阻止任务切换 | +| LOS_TaskUnlock | 解锁任务调度。通过该接口可以使任务锁数量减1,若任务多次加锁,那么
任务调度在锁数量减为0时才会完全解锁 | +| LOS_GetTaskScheduler | 获取指定任务的调度策略 | +| LOS_SetTaskScheduler | 设置指定任务的调度参数,包括优先级和调度策略 | +| LOS_Schedule | 触发主动的任务调度 | + +##### 表4 任务相关信息获取 + +| 接口名 | 接口描述 | +| ------------------------ | ------------------------ | +| LOS_CurTaskIDGet | 获取当前任务的ID | +| LOS_TaskInfoGet | 获取指定任务的信息 | +| LOS_GetSystemTaskMaximum | 获取系统支持的最大任务数 | + +##### 表5 任务优先级 + +| 接口名 | 接口描述 | +| ----------------- | ------------------------------ | +| LOS_CurTaskPriSet | 设置当前正在运行的任务的优先级 | +| LOS_TaskPriSet | 设置指定任务的优先级 | +| LOS_TaskPriGet | 获取指定任务的优先级 | + +##### 表6 任务绑核操作 + +| 接口名 | 接口描述 | +| ------------------ | ------------------------------------------- | +| LOS_TaskCpuAffiSet | 绑定指定任务到指定CPU上运行,仅在多核下使用 | +| LOS_TaskCpuAffiGet | 获取指定任务的绑核信息,仅在多核下使用 | + ### 开发流程 @@ -93,78 +135,79 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起 2. 任务参与调度运行,执行用户指定的业务代码。 -3. 任务执行结束,如果设置了LOS_TASK_STATUS_DETACHED属性,则自动回收任务资源,如果任务设置了LOS_TASK_ATTR_JOINABLE属性,则需要调用LOS_TaskJoin回收任务资源,默认为LOS_TASK_STATUS_DETACHED属性。 +3. 任务执行结束,如果设置了 LOS_TASK_STATUS_DETACHED 属性,则自动回收任务资源,如果任务设置了 LOS_TASK_ATTR_JOINABLE 属性,则需要调用LOS_TaskJoin 回收任务资源,默认为 LOS_TASK_STATUS_DETACHED 属性。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > - 内核态具有最高权限,可以操作任意进程内的任务。 -> +> > - 用户态进程通过系统调用进入内核态后创建的任务属于KProcess, 不属于当前用户态进程。 ### 编程实例 -代码实现如下: +代码实现如下(该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。): - -``` + +```c UINT32 g_taskLoID; -UINT32 g_taskHiID; -#define TSK_PRIOR_HI 4 -#define TSK_PRIOR_LO 5 -UINT32 ExampleTaskHi(VOID) -{ +UINT32 g_taskHiID; +#define TSK_PRIOR_HI 4 +#define TSK_PRIOR_LO 5 +UINT32 ExampleTaskHi(VOID) +{ UINT32 ret; - PRINTK("Enter TaskHi Handler.\n"); - /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoID任务) */ + PRINTK("Enter TaskHi Handler.\n"); + /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoID任务) */ ret = LOS_TaskDelay(2); - if (ret != LOS_OK) { + if (ret != LOS_OK) { PRINTK("Delay Task Failed.\n"); - return LOS_NOK; - } - /* 2个Tick时间到了后,该任务恢复,继续执行 */ - PRINTK("TaskHi LOS_TaskDelay Done.\n"); - /* 挂起自身任务 */ - ret = LOS_TaskSuspend(g_taskHiID); + return LOS_NOK; + } + /* 2个Tick时间到了后,该任务恢复,继续执行 */ + PRINTK("TaskHi LOS_TaskDelay Done.\n"); + /* 挂起自身任务 */ + ret = LOS_TaskSuspend(g_taskHiID); if (ret != LOS_OK) { - PRINTK("Suspend TaskHi Failed.\n"); + PRINTK("Suspend TaskHi Failed.\n"); return LOS_NOK; - } - PRINTK("TaskHi LOS_TaskResume Success.\n"); + } + PRINTK("TaskHi LOS_TaskResume Success.\n"); return LOS_OK; } -/* 低优先级任务入口函数 */ +/* 低优先级任务入口函数 */ UINT32 ExampleTaskLo(VOID) -{ - UINT32 ret; - PRINTK("Enter TaskLo Handler.\n"); +{ + UINT32 ret; + PRINTK("Enter TaskLo Handler.\n"); /* 延时2个Tick,延时后该任务会挂起,执行剩余任务中就高优先级的任务(背景任务) */ - ret = LOS_TaskDelay(2); - if (ret != LOS_OK) { - PRINTK("Delay TaskLo Failed.\n"); - return LOS_NOK; - } + ret = LOS_TaskDelay(2); + if (ret != LOS_OK) { + PRINTK("Delay TaskLo Failed.\n"); + return LOS_NOK; + } PRINTK("TaskHi LOS_TaskSuspend Success.\n"); /* 恢复被挂起的任务g_taskHiID */ ret = LOS_TaskResume(g_taskHiID); if (ret != LOS_OK) { PRINTK("Resume TaskHi Failed.\n"); return LOS_NOK; - } - PRINTK("TaskHi LOS_TaskDelete Success.\n"); + } + PRINTK("TaskHi LOS_TaskDelete Success.\n"); return LOS_OK; -} -/* 任务测试入口函数,在里面创建优先级不一样的两个任务 */ -UINT32 ExampleTaskCaseEntry(VOID) -{ - UINT32 ret; +} +/* 任务测试入口函数,在里面创建优先级不一样的两个任务 */ +UINT32 ExampleTaskCaseEntry(VOID) +{ + UINT32 ret; TSK_INIT_PARAM_S initParam = {0}; /* 锁任务调度 */ LOS_TaskLock(); PRINTK("LOS_TaskLock() Success!\n"); + /* 高优先级任务的初始化参数,其资源回收需要其他任务调用 LOS_TaskJoin */ initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskHi; - initParam.usTaskPrio = TSK_PRIOR_HI; + initParam.usTaskPrio = TSK_PRIOR_HI; initParam.pcName = "HIGH_NAME"; initParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_ATTR_JOINABLE; @@ -175,23 +218,24 @@ UINT32 ExampleTaskCaseEntry(VOID) LOS_TaskUnlock(); PRINTK("ExampleTaskHi create Failed! ret=%d\n", ret); return LOS_NOK; - } + } PRINTK("ExampleTaskHi create Success!\n"); + /* 低优先级任务的初始化参数,任务结束后会自行结束销毁 */ initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleTaskLo; initParam.usTaskPrio = TSK_PRIOR_LO; initParam.pcName = "LOW_NAME"; initParam.uwStackSize = LOS_TASK_MIN_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED; - /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ ret = LOS_TaskCreate(&g_taskLoID, &initParam); - if (ret!= LOS_OK) { - LOS_TaskUnlock(); + if (ret!= LOS_OK) { + LOS_TaskUnlock(); PRINTK("ExampleTaskLo create Failed!\n"); - return LOS_NOK; - } - PRINTK("ExampleTaskLo create Success!\n"); + return LOS_NOK; + } + PRINTK("ExampleTaskLo create Success!\n"); /* 解锁任务调度,此时会发生任务调度,执行就绪列表中最高优先级任务 */ LOS_TaskUnlock(); @@ -203,12 +247,12 @@ UINT32 ExampleTaskCaseEntry(VOID) } while(1){}; return LOS_OK; -} +} ``` 编译运行得到的结果为: - + ``` LOS_TaskLock() Success! ExampleTaskHi create Success! 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 230c1bd90b092e73b4885b1700997be80b604254..dd2459887b373f89358020b246d2b8ff8f75e10d 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-softtimer.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-softtimer.md @@ -3,9 +3,13 @@ ## 基本概念 -软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数。定时精度与系统Tick时钟的周期有关。硬件定时器受硬件的限制,数量上不足以满足用户的实际需求,因此为了满足用户需求,提供更多的定时器,OpenHarmony LiteOS-A内核提供软件定时器功能。软件定时器扩展了定时器的数量,允许创建更多的定时业务。 +软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数。定时精度与系统Tick时钟的周期有关。 -软件定时器功能上支持: +硬件定时器受硬件的限制,数量上不足以满足用户的实际需求,因此为了满足用户需求,提供更多的定时器,OpenHarmony LiteOS-A内核提供软件定时器功能。 + +软件定时器扩展了定时器的数量,允许创建更多的定时业务。 + +**软件定时器支持以下功能:** - 静态裁剪:能通过宏关闭软件定时器功能。 @@ -22,13 +26,17 @@ ## 运行机制 -软件定时器是系统资源,在模块初始化的时候已经分配了一块连续的内存,系统支持的最大定时器个数由los_config.h中的LOSCFG_BASE_CORE_SWTMR_LIMIT宏配置。软件定时器使用了系统的一个队列和一个任务资源,软件定时器的触发遵循队列规则,先进先出。同一时刻设置的定时时间短的定时器总是比定时时间长的靠近队列头,满足优先被触发的准则。软件定时器以Tick为基本计时单位,当用户创建并启动一个软件定时器时,OpenHarmony系统会根据当前系统Tick时间及用户设置的定时间隔确定该定时器的到期Tick时间,并将该定时器控制结构挂入计时全局链表。 +软件定时器是系统资源,在模块初始化的时候已经分配了一块连续的内存,系统支持的最大定时器个数由los_config.h中的LOSCFG_BASE_CORE_SWTMR_LIMIT宏配置。 + +软件定时器使用了系统的一个队列和一个任务资源,软件定时器的触发遵循队列规则,先进先出。同一时刻设置的定时时间短的定时器总是比定时时间长的靠近队列头,满足优先被触发的准则。 + +软件定时器以Tick为基本计时单位,当用户创建并启动一个软件定时器时,OpenHarmony系统会根据当前系统Tick时间及用户设置的定时间隔确定该定时器的到期Tick时间,并将该定时器控制结构挂入计时全局链表。 当Tick中断到来时,在Tick中断处理函数中扫描软件定时器的计时全局链表,看是否有定时器超时,若有则将超时的定时器记录下来。 Tick中断处理函数结束后,软件定时器任务(优先级为最高)被唤醒,在该任务中调用之前记录下来的定时器的超时回调函数。 -定时器状态 +**定时器状态:** - OS_SWTMR_STATUS_UNUSED(未使用) 系统在定时器模块初始化的时候将系统中所有定时器资源初始化成该状态。 @@ -39,9 +47,7 @@ Tick中断处理函数结束后,软件定时器任务(优先级为最高) - OS_SWTMR_STATUS_TICKING(计数) 在定时器创建后调用LOS_SwtmrStart接口,定时器将变成该状态,表示定时器运行时的状态。 -定时器模式 - -OpenHarmony系统的软件定时器提供三类定时器机制: +**定时器模式:** - 第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动删除。 @@ -55,20 +61,20 @@ OpenHarmony系统的软件定时器提供三类定时器机制: ### 接口说明 -OpenHarmony LiteOS-A内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 +OpenHarmony LiteOS-A内核的软件定时器模块提供以下几种功能。 **表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数 | ### 开发流程 -软件定时器的典型开发流程: +**软件定时器的典型开发流程:** 1. 配置软件定时器。 - 确认配置项LOSCFG_BASE_CORE_SWTMR和LOSCFG_BASE_IPC_QUEUE为打开状态; @@ -88,14 +94,15 @@ OpenHarmony LiteOS-A内核的软件定时器模块提供下面几种功能,接 6. 删除定时器LOS_SwtmrDelete。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> > - 软件定时器的回调函数中不要做过多操作,不要使用可能引起任务挂起或者阻塞的接口或操作。 -> +> > - 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级设定为0,且不允许修改 。 -> +> > - 系统可配置的软件定时器资源个数是指:整个系统可使用的软件定时器资源总个数,而并非是用户可使用的软件定时器资源个数。例如:系统软件定时器多占用一个软件定时器资源数,那么用户能使用的软件定时器资源就会减少一个。 -> +> > - 创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。 -> +> > - 创建单次不自删除属性的定时器,用户需要调用定时器删除接口删除定时器,回收定时器资源,避免资源泄露。 @@ -110,7 +117,7 @@ OpenHarmony LiteOS-A内核的软件定时器模块提供下面几种功能,接 - 配置好OS_SWTMR_HANDLE_QUEUE_SIZE软件定时器队列最大长度。 **编程示例** - + ``` #include "los_swtmr.h" @@ -176,7 +183,7 @@ void Timer_example(void) **运行结果** - + ``` create Timer1 success start Timer1 success @@ -206,4 +213,4 @@ g_timercount2 =9 tick_last1=2101 g_timercount2 =10 tick_last1=2201 -``` +``` \ No newline at end of file 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 9dca8cc0a5b64b3e0991d73247b281c3ed105bf5..5177b7f5dce34580d4c950f73c992b91c5d691bc 100644 --- a/zh-cn/device-dev/kernel/kernel-small-basic-time.md +++ b/zh-cn/device-dev/kernel/kernel-small-basic-time.md @@ -3,9 +3,11 @@ ## 基本概念 -时间管理以系统时钟为基础。时间管理提供给应用程序所有和时间有关的服务。系统时钟是由定时/计数器产生的输出脉冲触发中断而产生的,一般定义为整数或长整数。输出脉冲的周期叫做一个“时钟滴答”。系统时钟也称为时标或者Tick。一个Tick的时长可以静态配置。用户是以秒、毫秒为单位计时,而操作系统时钟计时是以Tick为单位的,当用户需要对系统操作时,例如任务挂起、延时等,输入秒为单位的数值,此时需要时间管理模块对二者进行转换。 +时间管理以系统时钟为基础。时间管理提供给应用程序所有和时间有关的服务。系统时钟是由定时/计数器产生的输出脉冲触发中断而产生的,一般定义为整数或长整数。输出脉冲的周期叫做一个“时钟滴答”。 -Tick与秒之间的对应关系可以配置。 +系统时钟也称为时标或者Tick。一个Tick的时长可以静态配置。用户是以秒、毫秒为单位计时,而操作系统时钟计时是以Tick为单位的,当用户需要对系统操作时,例如任务挂起、延时等,输入秒为单位的数值,此时需要时间管理模块对二者进行转换。 + +**Tick与秒之间的对应关系可以配置。** - **Cycle** 系统最小的计时单位。Cycle的时长由系统主频决定,系统主频就是每秒钟的Cycle数。 @@ -13,24 +15,24 @@ Tick与秒之间的对应关系可以配置。 - **Tick** Tick是操作系统的基本时间单位,对应的时长由系统主频及每秒Tick数决定,由用户配置。 -OpenHarmony系统的时间管理模块提供时间转换、统计、延迟功能以满足用户对时间相关需求的实现。 +**OpenHarmony系统的时间管理模块提供时间转换、统计、延迟功能以满足用户对时间相关需求的实现。** ## 开发指导 -用户需要了解当前系统运行的时间以及Tick与秒、毫秒之间的转换关系时,需要使用到时间管理模块的接口。 +用户需要了解当前系统运行的时间以及Tick与秒、毫秒之间的转换关系,以及需要使用到时间管理模块的接口。 ### 接口说明 -OpenHarmony LiteOS-A内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 +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数 | ### 开发流程 @@ -40,25 +42,26 @@ OpenHarmony LiteOS-A内核的时间管理提供下面几种功能,接口详细 2. 获取系统Tick数完成时间统计等。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> - 获取系统Tick数需要在系统时钟使能之后。 -> -> - 时间管理不是单独的功能模块,依赖于los_config.h中的OS_SYS_CLOCK和LOSCFG_BASE_CORE_TICK_PER_SECOND两个配置选项。 -> -> - 系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间计算。 +> +> - 获取系统Tick数需要在系统时钟使能之后。 +> +> - 时间管理不是单独的功能模块,依赖于los_config.h中的OS_SYS_CLOCK和LOSCFG_BASE_CORE_TICK_PER_SECOND两个配置选项。 +> +> - 系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间计算。 ### 编程实例 前置条件: -- 配置好LOSCFG_BASE_CORE_TICK_PER_SECOND,即系统每秒的Tick数,范围(0, 1000]。 +- 配置好LOSCFG_BASE_CORE_TICK_PER_SECOND,即系统每秒的Tick数,范围(0, 1000)。 - 配置好OS_SYS_CLOCK 系统时钟频率,单位:Hz。 **示例代码** 时间转换: - + ``` VOID Example_TransformTime(VOID) { @@ -73,7 +76,7 @@ VOID Example_TransformTime(VOID) 时间统计和时间延迟: - + ``` VOID Example_GetTime(VOID) { @@ -106,7 +109,7 @@ VOID Example_GetTime(VOID) 时间转换: - + ``` uwTick = 10000 uwMs = 100 @@ -114,9 +117,9 @@ uwMs = 100 时间统计和时间延迟: - + ``` LOS_CyclePerTickGet = 49500 -LOS_TickCountGet = 5042 -LOS_TickCountGet after delay = 5242 -``` +LOS_TickCountGet = 347931 +LOS_TickCountGet after delay = 348134 +``` \ No newline at end of file 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 56737c618168cddd11a50b91dae498ecde549733..e88c74b265ede038ef78fc675ebbe2335a2b78ff 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 @@ -15,7 +15,7 @@ OpenHarmony LiteOS-A的事件模块提供的事件,具有如下特点: - 任务通过创建事件控制块来触发事件或等待事件。 -- 事件间相互独立,内部实现为一个32位无符号整型,每一位标识一种事件类型。第25位不可用,因此最多可支持31种事件类型。 +- 事件间相互独立,内部实现为一个32位无符号整型,每一位标识一种事件类型。(0表示该时间类型未发生,1表示该事件类型已经发生,一共31种事件类型,第25bit位(`0x02U << 24`)系统保留) - 事件仅用于任务间的同步,不提供数据传输功能。 @@ -31,7 +31,7 @@ OpenHarmony LiteOS-A的事件模块提供的事件,具有如下特点: ### 事件控制块 - + ``` /** * 事件控制块数据结构 @@ -80,10 +80,10 @@ OpenHarmony LiteOS-A内核的事件模块提供下面几种功能。 | 功能分类 | 接口描述 | | -------- | -------- | | 初始化事件 | LOS_EventInit:初始化一个事件控制块 | -| 读/写事件 | - LOS_EventRead:读取指定事件类型,超时时间为相对时间:单位为Tick
- LOS_EventWrite:写指定的事件类型 | +| 读/写事件 | - LOS_EventRead:读取指定事件类型,超时时间为相对时间:单位为Tick
- LOS_EventWrite:写指定的事件类型 | | 清除事件 | LOS_EventClear:清除指定的事件类型 | -| 校验事件掩码 | - LOS_EventPoll:根据用户传入的事件ID、事件掩码及读取模式,返回用户传入的事件是否符合预期
- LOS_EventDestroy:销毁指定的事件控制块 | -| 销毁事件 | LOS_EventDestroy:销毁指定的事件控制块 | +| 校验事件掩码 | - LOS_EventPoll:根据用户传入的事件ID、事件掩码及读取模式,返回用户传入的事件是否符合预期
- LOS_EventDestroy:销毁指定的事件控制块 | +| 销毁事件 | LOS_EventDestroy:销毁指定的事件控制块 | ### 开发流程 @@ -103,7 +103,7 @@ OpenHarmony LiteOS-A内核的事件模块提供下面几种功能。 6. 事件控制块销毁 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> - 进行事件读写操作时,事件的第25位为保留位,不可以进行位设置。 +> - 进行事件读写操作时,事件的第25bit(`0x02U << 24`)为保留bit位,不可以进行位设置。 > > - 对同一事件反复写入,算作一次写入。 @@ -128,9 +128,10 @@ OpenHarmony LiteOS-A内核的事件模块提供下面几种功能。 ### 编程示例 +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数Example_EventEntry。 + 示例代码如下: - ``` #include "los_event.h" #include "los_task.h" @@ -143,21 +144,21 @@ UINT32 g_testTaskId; EVENT_CB_S g_exampleEvent; /* 等待的事件类型 */ -#define EVENT_WAIT 0x00000001 - +#define EVENT_WAIT 0x00000001 +#define EVENT_TIMEOUT 500 /* 用例任务入口函数 */ VOID Example_Event(VOID) { UINT32 event; /* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */ - printf("Example_Event wait event 0x%x \n", EVENT_WAIT); + dprintf("Example_Event wait event 0x%x \n", EVENT_WAIT); - event = LOS_EventRead(&g_exampleEvent, EVENT_WAIT, LOS_WAITMODE_AND, 100); + event = LOS_EventRead(&g_exampleEvent, EVENT_WAIT, LOS_WAITMODE_AND, EVENT_TIMEOUT); if (event == EVENT_WAIT) { - printf("Example_Event,read event :0x%x\n", event); + dprintf("Example_Event,read event :0x%x\n", event); } else { - printf("Example_Event,read event timeout\n"); + dprintf("Example_Event,read event timeout\n"); } } @@ -169,7 +170,7 @@ UINT32 Example_EventEntry(VOID) /* 事件初始化 */ ret = LOS_EventInit(&g_exampleEvent); if (ret != LOS_OK) { - printf("init event failed .\n"); + dprintf("init event failed .\n"); return -1; } @@ -181,30 +182,23 @@ UINT32 Example_EventEntry(VOID) task1.usTaskPrio = 5; ret = LOS_TaskCreate(&g_testTaskId, &task1); if (ret != LOS_OK) { - printf("task create failed.\n"); + dprintf("task create failed.\n"); return LOS_NOK; } /* 写g_testTaskId 等待事件 */ - printf("Example_TaskEntry write event.\n"); + dprintf("Example_TaskEntry write event.\n"); ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT); if (ret != LOS_OK) { - printf("event write failed.\n"); + dprintf("event write failed.\n"); return LOS_NOK; } /* 清标志位 */ - printf("EventMask:%d\n", g_exampleEvent.uwEventID); + dprintf("EventMask:%d\n", g_exampleEvent.uwEventID); LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID); - printf("EventMask:%d\n", g_exampleEvent.uwEventID); - - /* 删除任务 */ - ret = LOS_TaskDelete(g_testTaskId); - if (ret != LOS_OK) { - printf("task delete failed.\n"); - return LOS_NOK; - } + dprintf("EventMask:%d\n", g_exampleEvent.uwEventID); return LOS_OK; } @@ -215,7 +209,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 8bebc6f1cbb3bf8b0a9ab3825a62169561ac215d..34a11809784b79c61dbeebbadbe086d216bc60ce 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 @@ -87,7 +87,7 @@ ### 编程实例 -**实例描述** +#### 实例描述 本实例实现如下流程: @@ -99,17 +99,18 @@ 4. 100Tick休眠时间到达后,Example_MutexTask2被唤醒, 释放互斥锁,唤醒Example_MutexTask1。Example_MutexTask1成功获取到互斥锁后,释放,删除互斥锁。 -**示例代码** +#### 编程示例 + +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数Example_MutexEntry。 示例代码如下: - ``` #include #include "los_mux.h" /* 互斥锁 */ -LosMux g_testMux; +LosMux g_testMutex; /* 任务ID */ UINT32 g_testTaskId01; UINT32 g_testTaskId02; @@ -117,48 +118,49 @@ UINT32 g_testTaskId02; VOID Example_MutexTask1(VOID) { UINT32 ret; + LOS_TaskDelay(50); - printf("task1 try to get mutex, wait 10 ticks.\n"); + dprintf("task1 try to get mutex, wait 10 ticks.\n"); /* 申请互斥锁 */ - ret = LOS_MuxLock(&g_testMux, 10); + ret = LOS_MuxLock(&g_testMutex, 10); if (ret == LOS_OK) { - printf("task1 get mutex g_testMux.\n"); + dprintf("task1 get mutex g_testMux.\n"); /* 释放互斥锁 */ - LOS_MuxUnlock(&g_testMux); + LOS_MuxUnlock(&g_testMutex); return; - } - if (ret == LOS_ETIMEDOUT ) { - printf("task1 timeout and try to get mutex, wait forever.\n"); - /* 申请互斥锁 */ - ret = LOS_MuxLock(&g_testMux, LOS_WAIT_FOREVER); - if (ret == LOS_OK) { - printf("task1 wait forever, get mutex g_testMux.\n"); - /* 释放互斥锁 */ - LOS_MuxUnlock(&g_testMux); - /* 删除互斥锁 */ - LOS_MuxDestroy(&g_testMux); - printf("task1 post and delete mutex g_testMux.\n"); - return; - } + } + if (ret == LOS_ETIMEDOUT) { + dprintf("task1 timeout and try to get mutex, wait forever.\n"); + /* 申请互斥锁 */ + ret = LOS_MuxLock(&g_testMutex, LOS_WAIT_FOREVER); + if (ret == LOS_OK) { + dprintf("task1 wait forever, get mutex g_testMux.\n"); + /* 释放互斥锁 */ + LOS_MuxUnlock(&g_testMutex); + /* 删除互斥锁 */ + LOS_MuxDestroy(&g_testMutex); + dprintf("task1 post and delete mutex g_testMux.\n"); + return; + } } return; } VOID Example_MutexTask2(VOID) { - printf("task2 try to get mutex, wait forever.\n"); + dprintf("task2 try to get mutex, wait forever.\n"); /* 申请互斥锁 */ - (VOID)LOS_MuxLock(&g_testMux, LOS_WAIT_FOREVER); + (VOID)LOS_MuxLock(&g_testMutex, LOS_WAIT_FOREVER); - printf("task2 get mutex g_testMux and suspend 100 ticks.\n"); + dprintf("task2 get mutex g_testMux and suspend 100 ticks.\n"); /* 任务休眠100Ticks */ LOS_TaskDelay(100); - printf("task2 resumed and post the g_testMux\n"); + dprintf("task2 resumed and post the g_testMux\n"); /* 释放互斥锁 */ - LOS_MuxUnlock(&g_testMux); + LOS_MuxUnlock(&g_testMutex); return; } @@ -169,7 +171,7 @@ UINT32 Example_MutexEntry(VOID) TSK_INIT_PARAM_S task2; /* 初始化互斥锁 */ - LOS_MuxInit(&g_testMux, NULL); + LOS_MuxInit(&g_testMutex, NULL); /* 锁任务调度 */ LOS_TaskLock(); @@ -182,7 +184,7 @@ UINT32 Example_MutexEntry(VOID) task1.usTaskPrio = 5; ret = LOS_TaskCreate(&g_testTaskId01, &task1); if (ret != LOS_OK) { - printf("task1 create failed.\n"); + dprintf("task1 create failed.\n"); return LOS_NOK; } @@ -194,7 +196,7 @@ UINT32 Example_MutexEntry(VOID) task2.usTaskPrio = 4; ret = LOS_TaskCreate(&g_testTaskId02, &task2); if (ret != LOS_OK) { - printf("task2 create failed.\n"); + dprintf("task2 create failed.\n"); return LOS_NOK; } @@ -209,11 +211,11 @@ UINT32 Example_MutexEntry(VOID) 编译运行得到的结果为: - + ``` -task1 try to get mutex, wait 10 ticks. task2 try to get mutex, wait forever. task2 get mutex g_testMux and suspend 100 ticks. +task1 try to get mutex, wait 10 ticks. task1 timeout and try to get mutex, wait forever. task2 resumed and post the g_testMux task1 wait forever, get mutex g_testMux. 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 cdf3f64c4fa5a7d9c7df3d71481568661c23d1bb..28c7569cd2512f74a1243c0bd684b5037def56e0 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 @@ -7,7 +7,7 @@ 任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 -可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 +可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将读队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: @@ -31,7 +31,7 @@ ### 队列控制块 - + ``` /** * 队列控制块数据结构 @@ -137,9 +137,12 @@ typedef struct { ### 编程示例 +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExampleQueue, + +为方便用户观察,建议调用ExampleQueue前先调用 LOS_Msleep(5000) 进行短时间延时,避免其他打印过多。 + 示例代码如下: - ``` #include "los_task.h" #include "los_queue.h" @@ -154,7 +157,7 @@ VOID SendEntry(VOID) ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); if(ret != LOS_OK) { - printf("send message failure, error: %x\n", ret); + dprintf("send message failure, error: %x\n", ret); } } @@ -164,30 +167,36 @@ VOID RecvEntry(VOID) CHAR readBuf[BUFFER_LEN] = {0}; UINT32 readLen = BUFFER_LEN; - //休眠1s - usleep(1000000); + LOS_Msleep(1000); ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); if(ret != LOS_OK) { - printf("recv message failure, error: %x\n", ret); + dprintf("recv message failure, error: %x\n", ret); } - printf("recv message: %s\n", readBuf); + dprintf("recv message: %s\n", readBuf); ret = LOS_QueueDelete(g_queue); if(ret != LOS_OK) { - printf("delete the queue failure, error: %x\n", ret); + dprintf("delete the queue failure, error: %x\n", ret); } - printf("delete the queue success!\n"); + dprintf("delete the queue success!\n"); } UINT32 ExampleQueue(VOID) { - printf("start queue example\n"); + dprintf("start queue example\n"); UINT32 ret = 0; UINT32 task1, task2; TSK_INIT_PARAM_S initParam = {0}; + ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); + if(ret != LOS_OK) { + dprintf("create queue failure, error: %x\n", ret); + } + + dprintf("create the queue success!\n"); + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; initParam.usTaskPrio = 9; initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; @@ -196,7 +205,8 @@ UINT32 ExampleQueue(VOID) LOS_TaskLock(); ret = LOS_TaskCreate(&task1, &initParam); if(ret != LOS_OK) { - printf("create task1 failed, error: %x\n", ret); + dprintf("create task1 failed, error: %x\n", ret); + LOS_QueueDelete(g_queue); return ret; } @@ -204,17 +214,13 @@ UINT32 ExampleQueue(VOID) initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; ret = LOS_TaskCreate(&task2, &initParam); if(ret != LOS_OK) { - printf("create task2 failed, error: %x\n", ret); + dprintf("create task2 failed, error: %x\n", ret); + LOS_QueueDelete(g_queue); 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(); + LOS_Msleep(5000); return ret; } ``` @@ -224,9 +230,9 @@ UINT32 ExampleQueue(VOID) 编译运行得到的结果为: - + ``` -start test example +start queue 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-semaphore.md b/zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md index 2ab8ebb7631d97c44596c1b29a5b0e2edb2fb068..b15369f207ef711d378a57bc3f537467fda2db1e 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 @@ -22,7 +22,7 @@ **信号量控制块** - + ``` /** * 信号量控制块数据结构 @@ -116,9 +116,10 @@ typedef struct { ### 编程示例 +本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExampleSem。 + 示例代码如下: - ``` #include "los_sem.h" #include "securec.h" @@ -128,7 +129,8 @@ static UINT32 g_testTaskId01; static UINT32 g_testTaskId02; /* 测试任务优先级 */ -#define TASK_PRIO_TEST 5 +#define TASK_PRIO_LOW 5 +#define TASK_PRIO_HI 4 /* 信号量结构体id */ static UINT32 g_semId; @@ -137,11 +139,10 @@ VOID ExampleSemTask1(VOID) { UINT32 ret; - printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n"); + dprintf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n"); /* 定时阻塞模式申请信号量,定时时间为10ticks */ ret = LOS_SemPend(g_semId, 10); - /* 申请到信号量 */ if (ret == LOS_OK) { LOS_SemPost(g_semId); @@ -149,12 +150,13 @@ VOID ExampleSemTask1(VOID) } /* 定时时间到,未申请到信号量 */ if (ret == LOS_ERRNO_SEM_TIMEOUT) { - printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n"); + dprintf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n"); /*永久阻塞模式申请信号量*/ ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); - printf("ExampleSemTask1 wait_forever and get sem g_semId.\n"); + dprintf("ExampleSemTask1 wait_forever and get sem g_semId.\n"); if (ret == LOS_OK) { + dprintf("ExampleSemTask1 post sem g_semId.\n"); LOS_SemPost(g_semId); return; } @@ -164,19 +166,18 @@ VOID ExampleSemTask1(VOID) VOID ExampleSemTask2(VOID) { UINT32 ret; - printf("ExampleSemTask2 try get sem g_semId wait forever.\n"); + dprintf("ExampleSemTask2 try get sem g_semId wait forever.\n"); /* 永久阻塞模式申请信号量 */ ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); - if (ret == LOS_OK) { - printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n"); + dprintf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n"); } /* 任务休眠20 ticks */ LOS_TaskDelay(20); - printf("ExampleSemTask2 post sem g_semId.\n"); + dprintf("ExampleSemTask2 post sem g_semId.\n"); /* 释放信号量 */ LOS_SemPost(g_semId); return; @@ -199,10 +200,10 @@ UINT32 ExampleSem(VOID) task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1; task1.pcName = "TestTask1"; task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = TASK_PRIO_TEST; + task1.usTaskPrio = TASK_PRIO_LOW; ret = LOS_TaskCreate(&g_testTaskId01, &task1); if (ret != LOS_OK) { - printf("task1 create failed .\n"); + dprintf("task1 create failed .\n"); return LOS_NOK; } @@ -211,16 +212,19 @@ UINT32 ExampleSem(VOID) task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2; task2.pcName = "TestTask2"; task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task2.usTaskPrio = (TASK_PRIO_TEST - 1); + task2.usTaskPrio = TASK_PRIO_HI; ret = LOS_TaskCreate(&g_testTaskId02, &task2); if (ret != LOS_OK) { - printf("task2 create failed.\n"); + dprintf("task2 create failed.\n"); return LOS_NOK; } /* 解锁任务调度 */ LOS_TaskUnlock(); + /* 任务休眠400 ticks */ + LOS_TaskDelay(400); + ret = LOS_SemPost(g_semId); /* 任务休眠400 ticks */ @@ -237,12 +241,13 @@ UINT32 ExampleSem(VOID) 编译运行得到的结果为: - + ``` ExampleSemTask2 try get sem g_semId wait forever. -ExampleSemTask2 get sem g_semId and then delay 20 ticks. ExampleSemTask1 try get sem g_semId, timeout 10 ticks. ExampleSemTask1 timeout and try get sem g_semId wait forever. +ExampleSemTask2 get sem g_semId and then delay 20 ticks. ExampleSemTask2 post sem g_semId. ExampleSemTask1 wait_forever and get sem g_semId. +ExampleSemTask1 post sem g_semId. ``` 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 3c70d1195c576bb7fcae13a046042496908ea2b4..f9a50100fa2569422ce04beecbaac2da47c39e32 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 @@ -10,26 +10,29 @@ Futex(Fast userspace mutex,用户态快速互斥锁)是内核提供的一种 当用户态线程释放锁时,先在用户态进行锁状态的判断维护,若此时没有其他线程被该锁阻塞,则直接在用户态进行解锁返回;反之,则需要进行阻塞线程的唤醒操作,通过Futex系统调用请求内核介入来唤醒阻塞队列中的线程。 + ## 运行机制 当用户态产生锁的竞争或释放需要进行相关线程的调度操作时,会触发Futex系统调用进入内核,此时会将用户态锁的地址传入内核,并在内核的Futex中以锁地址来区分用户态的每一把锁,因为用户态可用虚拟地址空间为1GiB,为了便于查找、管理,内核Futex采用哈希桶来存放用户态传入的锁。 -当前哈希桶共有80个,0~63号桶用于存放私有锁(以虚拟地址进行哈希),64~79号桶用于存放共享锁(以物理地址进行哈希),私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。 +当前哈希桶共有80个,~~0-63号桶用于存放私有锁(以虚拟地址进行哈希),64-79~~号桶用于存放共享锁(以物理地址进行哈希),私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。 + +## Futex设计图 - **图1** Futex设计图 + **图1** ![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有以下三种操作: +## Futex有以下三种操作: - **表1** Futex模块接口 +**Futex模块接口** -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 设置线程等待 | OsFutexWait | 向Futex表中插入代表被阻塞的线程的node | -| 唤醒被阻塞线程 | OsFutexWake | 唤醒一个被指定锁阻塞的线程 | -| 调整锁的地址 | OsFutexRequeue | 调整指定锁在Futex表中的位置 | +| 功能分类 | 接口**名称** | 描述 | +| -------------- | -------------- | ------------------------------------- | +| 设置线程等待 | OsFutexWait | 向Futex表中插入代表被阻塞的线程的node | +| 唤醒被阻塞线程 | OsFutexWake | 唤醒一个被指定锁阻塞的线程 | +| 调整锁的地址 | OsFutexRequeue | 调整指定锁在Futex表中的位置 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> Futex系统调用通常与用户态逻辑共同组成用户态锁,故推荐使用用户态POSIX接口的锁。 +> Futex系统调用通常与用户态逻辑共同组成用户态锁,故推荐使用用户态POSIX接口的锁。 \ No newline at end of file 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 aaa1f061537203ee243ba8ce14556ac89c4d52d0..e045d156ffa6baa2d533ccda05a87f8454aa3a2e 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 @@ -12,46 +12,53 @@ **表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); -> ``` -> -> a. 31 号信号,该信号用来注册该进程的回调函数处理入口,不可重复注册。 -> -> b. 0-30 号信号,该信号段用来注册与去注册回调函数。 -> -> 注册回调函数: -> -> -> ``` -> int sigaction(int, const struct sigaction *__restrict, struct sigaction *__restrict); -> ``` -> -> 支持信号注册的配置修改和配置获取,目前仅支持SIGINFO的选项,SIGINFO内容见sigtimedwait接口内描述。 -> -> 发送信号: -> -> a. 进程接收信号存在默认行为,单不支持POSIX标准所给出的STOP及CONTINUE、COREDUMP功能。 -> -> b. 进程无法屏蔽SIGSTOP、SIGKILL、SIGCONT信号。 -> -> c. 某进程后被杀死后,若其父进程不回收该进程,其转为僵尸进程。 -> -> d. 进程接收到某信号后,直到该进程被调度后才会执行信号回调。 -> -> e. 进程结束后会发送SIGCHLD信号给父进程,该发送动作无法取消。 -> -> f. 无法通过信号唤醒处于DELAY状态的进程。 +> 信号机制为提供给用户态程序进程间通信的能力,故推荐使用上表1列出的用户态POSIX相关接口。 +> +> **注册回调函数:** +> +> +> ``` +> void *signal(int sig, void (*func)(int))(int); +> ``` +> +> - 31 号信号,该信号用来注册该进程的回调函数处理入口,不可重复注册。 +> +> +> - 0-30 号信号,该信号段用来注册与去注册回调函数。 +> +> +> **注册回调函数:** +> +> +> ``` +> int sigaction(int, const struct sigaction *__restrict, struct sigaction *__restrict); +> ``` +> +> 支持信号注册的配置修改和配置获取,目前仅支持SIGINFO的选项,SIGINFO内容见sigtimedwait接口内描述。 +> +> **发送信号:** +> +> - 进程接收信号存在默认行为,单不支持POSIX标准所给出的STOP及CONTINUE、COREDUMP功能。 +> +> +> - 进程无法屏蔽SIGSTOP、SIGKILL、SIGCONT信号。 +> +> +> - 某进程后被杀死后,若其父进程不回收该进程,其转为僵尸进程。 +> +> +> - 进程接收到某信号后,直到该进程被调度后才会执行信号回调。 +> +> +> - 进程结束后会发送SIGCHLD信号给父进程,该发送动作无法取消。 +> +> +> - 无法通过信号唤醒处于DELAY状态的进程。 \ 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 a88b52fbe6f9c54ac59f3a1ff83dc440d3a25edd..62dc10cba0747b8e1e6b29d5373a43bb6f3d9bba 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-ipc.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-ipc.md @@ -5,12 +5,20 @@ LiteIPC是OpenHarmony LiteOS-A内核提供的一种新型IPC(Inter-Process Communication,即进程间通信)机制,不同于传统的System V IPC机制,LiteIPC主要是为RPC(Remote Procedure Call,即远程过程调用)而设计的,而且是通过设备文件的方式对上层提供接口的,而非传统的API函数方式。 -LiteIPC中有两个主要概念,一个是ServiceManager,另一个是Service。整个系统只能有一个ServiceManager,而Service可以有多个。ServiceManager有两个主要功能:一是负责Service的注册和注销,二是负责管理Service的访问权限(只有有权限的任务(Task)可以向对应的Service发送IPC消息)。 +LiteIPC中有两个主要概念,一个是ServiceManager,另一个是Service。整个系统只能有一个ServiceManager,而Service可以有多个。 + +**ServiceManager有两个主要功能:** + +- 一是负责Service的注册和注销, + +- 二是负责管理Service的访问权限(只有有权限的任务(Task)可以向对应的Service发送IPC消息)。 ## 运行机制 -首先将需要接收IPC消息的任务通过ServiceManager注册成为一个Service,然后通过ServiceManager为该Service任务配置访问权限,即指定哪些任务可以向该Service任务发送IPC消息。LiteIPC的核心思想就是在内核态为每个Service任务维护一个IPC消息队列,该消息队列通过LiteIPC设备文件向上层用户态程序分别提供代表收取IPC消息的读操作和代表发送IPC消息的写操作。 +首先将需要接收IPC消息的任务通过ServiceManager注册成为一个Service,然后通过ServiceManager为该Service任务配置访问权限,即指定哪些任务可以向该Service任务发送IPC消息。 + +LiteIPC的核心思想就是在内核态为每个Service任务维护一个IPC消息队列,该消息队列通过LiteIPC设备文件向上层用户态程序分别提供代表收取IPC消息的读操作和代表发送IPC消息的写操作。 ## 开发指导 @@ -20,11 +28,11 @@ LiteIPC中有两个主要概念,一个是ServiceManager,另一个是Service **表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内部使用。 +> LiteIPC模块接口都只在LiteOS-A内部使用。 \ No newline at end of file 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 b82577accf4e2a79da7eb0563d3f103a663b3cad..323cafe4712e0d10d5a9bd61f7c46416baec92c8 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-linking.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-linking.md @@ -16,7 +16,7 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 ## 运行机制 - **图1** 动态加载流程 + **图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)。 @@ -25,18 +25,18 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 3. 动态链接器自举并查找应用程序依赖的所有共享库并对导入符号进行重定位,最后跳转至应用程序的e_entry(或base + e_entry),开始运行应用程序。 - **图2** 程序执行流程 + **图2** **程序执行流程** ![zh-cn_image_0000001133264664](figures/zh-cn_image_0000001133264664.png) -1. 加载器与链接器调用mmap映射PT_LOAD段; +1. 加载器与链接器调用mmap映射PT_LOAD段。 -2. 内核调用map_pages接口查找并映射pagecache已有的缓存; +2. 内核调用map_pages接口查找并映射pagecache已有的缓存。 -3. 程序执行时,虚拟内存区间若无具体的物理内存做映射,系统将触发缺页中断,将elf文件内容读入物理内存,并将该内存块加入pagecache; +3. 程序执行时,虚拟内存区间若无具体的物理内存做映射,系统将触发缺页中断,将elf文件内容读入物理内存,并将该内存块加入pagecache。 -4. 将已读入文件内容的物理内存与虚拟地址区间做映射; +4. 将已读入文件内容的物理内存与虚拟地址区间做映射。 -5. 程序继续执行; +5. 程序继续执行。 ## 开发指导 @@ -46,11 +46,11 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 **表1** 内核加载器模块接口 -| 功能分类 | 接口**名称** | 描述 | -| -------- | -------- | -------- | -| 模块初始化 | LOS_DoExecveFile | 根据输入的参数执行指定的用户程序 | +| 功能分类 | 接口**名称** | 描述 | +| ---------- | ---------------- | -------------------------------- | +| 模块初始化 | LOS_DoExecveFile | 根据输入的参数执行指定的用户程序 | ### 开发流程 -LOS_DoExecveFile接口一般由用户通过exec家族函数利用系统调用机制创建新的进程,内核不能直接调用该接口启动新进程。 +LOS_DoExecveFile接口一般由用户通过exec家族函数利用系统调用机制创建新的进程,内核不能直接调用该接口启动新进程。 \ No newline at end of file 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 5049f8883af54c553de6def88f3fedbb39f96798..f3090ce771a2fef676aa6b7bfc263df708c08af5 100644 --- a/zh-cn/device-dev/kernel/kernel-small-bundles-share.md +++ b/zh-cn/device-dev/kernel/kernel-small-bundles-share.md @@ -12,7 +12,7 @@ OpenHarmony系统通过VDSO机制实现上层用户态程序可以快速读取 VDSO其核心思想就是内核看护一段内存,并将这段内存映射(只读)进用户态应用程序的地址空间,应用程序通过链接vdso.so后,将某些系统调用替换为直接读取这段已映射的内存从而避免系统调用达到加速的效果。 -VDSO总体可分为数据页与代码页两部分: +**VDSO总体可分为数据页与代码页两部分:** - 数据页提供内核映射给用户进程的内核时数据; @@ -21,7 +21,7 @@ VDSO总体可分为数据页与代码页两部分: **图1** VDSO系统设计 ![zh-cn_image_0000001173586763](figures/zh-cn_image_0000001173586763.jpg) -如图1所示,当前VDSO机制有以下几个主要步骤: +**如图1所示,当前VDSO机制有以下几个主要步骤:** ① 内核初始化时进行VDSO数据页的创建; @@ -42,6 +42,9 @@ VDSO总体可分为数据页与代码页两部分: ⑨ 将从VDSO数据页获取到的数据作为结果返回给用户程序; > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> - 当前VDSO机制支持LibC库clock_gettime接口的CLOCK_REALTIME_COARSE与CLOCK_MONOTONIC_COARSE功能,clock_gettime接口的使用方法详见POSIX标准。用户调用C库接口clock_gettime(CLOCK_REALTIME_COARSE, &ts)或者clock_gettime(CLOCK_MONOTONIC_COARSE, &ts)即可使用VDSO机制。 -> -> - 使用VDSO机制得到的时间精度会与系统tick中断的精度保持一致,适用于对时间没有高精度要求且短时间内会高频触发clock_gettime或gettimeofday系统调用的场景,若有高精度要求,不建议采用VDSO机制。 +> +> - 当前VDSO机制支持LibC库clock_gettime接口的CLOCK_REALTIME_COARSE与CLOCK_MONOTONIC_COARSE功能,clock_gettime接口的使用方法详见POSIX标准。 +> +> - 用户调用C库接口clock_gettime(CLOCK_REALTIME_COARSE, &ts)或者clock_gettime(CLOCK_MONOTONIC_COARSE, &ts)即可使用VDSO机制。 +> +> - 使用VDSO机制得到的时间精度会与系统tick中断的精度保持一致,适用于对时间没有高精度要求且短时间内会高频触发clock_gettime或gettimeofday系统调用的场景,若有高精度要求,不建议采用VDSO机制。 \ No newline at end of file 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 11da1497e3478b2207bada0f8ee52728eaa577eb..9485fdbc1ac4b258569b3999ef13cf77d94f4762 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 @@ -42,11 +42,12 @@ LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK:开关宏,默认关闭;若打开这 **示例代码** +该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试. 代码实现如下: - -``` + +```c #include #include #include "los_memory.h" @@ -70,12 +71,12 @@ void MemIntegrityTest(void) 编译运行输出log如下: - + ``` [ERR][OsMemMagicCheckPrint], 2028, memory check error! memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ - broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 + broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 /* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ broken node head LR info: /* 节点的LR信息需要开启内存检测功能才有有效输出 */ 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 29281d54b2486a737a7efccd1d66ebfd6ae14e4b..bad2be2d79deed987460895029a11df7463b97cb 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 @@ -7,14 +7,14 @@ - 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小; -- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-100\*最大空闲内存块大小/剩余内存大小)来度量 +- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-100\*最大空闲内存块大小/剩余内存大小)来度量; - 其他统计信息:调用接口LOS_MemInfoGet时,会扫描内存池的节点信息,统计出相关信息。 ## 功能配置 -LOSCFG_MEM_WATERLINE:开关宏,默认关闭;若需要打开这个功能,可以在配置项中开启“Debug-> Enable memory pool waterline or not”。如需获取内存水线,需要打开该配置。 +LOSCFG_MEM_WATERLINE:开关宏,默认关闭;若需要打开这个功能,可以在配置项中开启“Debug-> Enable MEM Debug-> Enable memory pool waterline or not”。如需获取内存水线,需要打开该配置。 ## 开发指导 @@ -24,8 +24,8 @@ LOSCFG_MEM_WATERLINE:开关宏,默认关闭;若需要打开这个功能, 关键结构体介绍: - -``` + +```c typedef struct { UINT32 totalUsedSize; // 内存池的内存使用量 UINT32 totalFreeSize; // 内存池的剩余内存大小 @@ -38,7 +38,7 @@ typedef struct { } LOS_MEM_POOL_STATUS; ``` -- 内存水线获取:调用LOS_MemInfoGet接口,第1个参数是内存池首地址,第2个参数是LOS_MEM_POOL_STATUS类型的句柄,其中字段usageWaterLine即水线值。 +- 内存水线获取:调用 LOS_MemInfoGet(VOID *pool, LOS_MEM_POOL_STATUS *poolStatus)接口,第1个参数是内存池首地址,第2个参数是LOS_MEM_POOL_STATUS类型的句柄,其中字段usageWaterLine即水线值。 - 内存碎片率计算:同样调用LOS_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-100\*最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。 @@ -53,13 +53,13 @@ typedef struct { 3. 利用公式算出使用率及碎片率。 - **示例代码** +本演示代码在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证,在TestTaskEntry中调用验证入口函数MemTest。 - 代码实现如下: - -``` +代码实现如下: + +```c #include #include #include "los_task.h" @@ -70,15 +70,14 @@ void MemInfoTaskFunc(void) { LOS_MEM_POOL_STATUS poolStatus = {0}; - /* pool为要统计信息的内存地址,此处以OS_SYS_MEM_ADDR为例 */ + /* pool为要统计信息的内存地址,此处以OS_SYS_MEM_ADDR为例 */ void *pool = OS_SYS_MEM_ADDR; LOS_MemInfoGet(pool, &poolStatus); /* 算出内存池当前的碎片率百分比 */ unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize; /* 算出内存池当前的使用率百分比 */ unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool); - printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, - poolStatus.totalFreeSize, poolStatus.usageWaterLine); + dprintf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, poolStatus.totalFreeSize, poolStatus.usageWaterLine); } int MemTest(void) @@ -92,10 +91,10 @@ int MemTest(void) taskStatus.usTaskPrio = 10; ret = LOS_TaskCreate(&taskID, &taskStatus); if (ret != LOS_OK) { - printf("task create failed\n"); - return -1; + dprintf("task create failed\n"); + return LOS_NOK; } - return 0; + return LOS_OK; } ``` @@ -105,8 +104,8 @@ 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 e7c75955c37d6e9c643124d8d0b7c8a712fe3e49..97a08f31900427e34bb285509cd4dde83da25753 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 @@ -8,11 +8,11 @@ ## 功能配置 -1. LOSCFG_MEM_LEAKCHECK:开关宏,默认关闭;如需要打开这个功能,可以在配置项中开启“Debug-> Enable Function call stack of Mem operation recorded”。 +1. LOSCFG_MEM_LEAKCHECK:开关宏,默认关闭;如需要打开这个功能,可以在配置项中开启“Debug-> Enable MEM Debug-> Enable Function call stack of Mem operation recorded”。 2. LOS_RECORD_LR_CNT:记录的LR层数,默认3层;每层LR消耗sizeof(void \*)字节数的内存。 -3. LOS_OMIT_LR_CNT:忽略的LR层数,默认2层,即从调用LOS_MemAlloc的函数开始记录,可根据实际情况调整。为啥需要这个配置?有3点原因如下: +3. LOS_OMIT_LR_CNT:忽略的LR层数,默认2层,即从调用LOS_MemAlloc的函数开始记录,可根据实际情况调整。需要此配置原因如下: - LOS_MemAlloc接口内部也有函数调用; - 外部可能对LOS_MemAlloc接口有封装; - LOS_RECORD_LR_CNT 配置的LR层数有限; @@ -27,17 +27,17 @@ 该调测功能可以分析关键的代码逻辑中是否存在内存泄漏。开启这个功能,每次申请内存时,会记录LR信息。在需要检测的代码段前后,调用LOS_MemUsedNodeShow接口,每次都会打印指定内存池已使用的全部节点信息,对比前后两次的节点信息,新增的节点信息就是疑似泄漏的内存节点。通过LR,可以找到具体申请的代码位置,进一步确认是否泄漏。 -调用LOS_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 +调用LOS_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等工具查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 ``` -node size LR[0] LR[1] LR[2] -0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 -0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0 -0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4 +node size LR[0] LR[1] LR[2] +0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 +0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4 0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4 -0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0 -0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0 ``` > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** @@ -61,21 +61,36 @@ node size LR[0] LR[1] LR[2] **示例代码** +本演示代码在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证,在TestTaskEntry中调用验证入口函数MemLeakTest。 + +为了方便展示建议创建新的内存池,需要在target_config.h 中定义 LOSCFG_MEM_MUL_POOL 代码实现如下: -``` +```c #include #include #include "los_memory.h" #include "los_config.h" +#define TEST_NEW_POOL_SIZE 2000 +#define TEST_MALLOC_SIZE 8 + void MemLeakTest(void) { - OsMemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); - void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - OsMemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); + VOID *pool = NULL; + + /* 由于原内存池分配过多, 为了方便展示, 创建新的内存池 */ + pool = LOS_MemAlloc(OS_SYS_MEM_ADDR, TEST_NEW_POOL_SIZE); + (VOID)LOS_MemInit(pool, TEST_NEW_POOL_SIZE); + + OsMemUsedNodeShow(pool); + void *ptr1 = LOS_MemAlloc(pool, TEST_MALLOC_SIZE); + void *ptr2 = LOS_MemAlloc(pool, TEST_MALLOC_SIZE); + OsMemUsedNodeShow(pool); + + /* 释放内存池 */ + (VOID)LOS_MemDeInit(pool); } ``` @@ -86,51 +101,50 @@ void MemLeakTest(void) 编译运行输出log如下: ``` -node size LR[0] LR[1] LR[2] -0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc -0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc -0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e -0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a -0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 - -node size LR[0] LR[1] LR[2] -0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc -0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc -0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e -0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a -0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 -0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +/* 第一次OsMemUsedNodeShow打印,由于该内存池未分配,所以无内存节点 */ +node LR[0] LR[1] LR[2] + + +/* 第二次OsMemUsedNodeShow打印,有两个新的内存节点 */ +node LR[0] LR[1] LR[2] +0x00402e0d90: 0x004009f040 0x0040037614 0x0040005480 +0x00402e0db0: 0x004009f04c 0x0040037614 0x0040005480 + ``` 对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: ``` -0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +0x00402e0d90: 0x004009f040 0x0040037614 0x0040005480 +0x00402e0db0: 0x004009f04c 0x0040037614 0x0040005480 ``` 部分汇编文件如下: ``` - MemLeakTest: - 0x80041d4: 0xb510 PUSH {R4, LR} - 0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart - 0x80041d8: 0x0020 MOVS R0, R4 - 0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a - 0x80041de: 0x2108 MOVS R1, #8 - 0x80041e0: 0x0020 MOVS R0, R4 - 0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998 - 0x80041e6: 0x2108 MOVS R1, #8 - 0x80041e8: 0x0020 MOVS R0, R4 - 0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998 - 0x80041ee: 0x0020 MOVS R0, R4 - 0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a - 0x80041f4: 0xbd10 POP {R4, PC} - 0x80041f6: 0x0000 MOVS R0, R0 +4009f014: 7d 1e a0 e3 mov r1, #2000 +4009f018: 00 00 90 e5 ldr r0, [r0] +4009f01c: 67 7a fe eb bl #-398948 +4009f020: 7d 1e a0 e3 mov r1, #2000 +4009f024: 00 40 a0 e1 mov r4, r0 +4009f028: c7 79 fe eb bl #-399588 +4009f02c: 04 00 a0 e1 mov r0, r4 +4009f030: 43 78 fe eb bl #-401140 +4009f034: 04 00 a0 e1 mov r0, r4 +4009f038: 08 10 a0 e3 mov r1, #8 +4009f03c: 5f 7a fe eb bl #-398980 +4009f040: 04 00 a0 e1 mov r0, r4 +4009f044: 08 10 a0 e3 mov r1, #8 +4009f048: 5c 7a fe eb bl #-398992 +4009f04c: 04 00 a0 e1 mov r0, r4 +4009f050: 3b 78 fe eb bl #-401172 +4009f054: 3c 00 9f e5 ldr r0, [pc, #60] +4009f058: 40 b8 fe eb bl #-335616 +4009f05c: 04 00 a0 e1 mov r0, r4 +4009f060: 2c 7a fe eb bl #-399184 ``` -其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 +其中,通过查找0x4009f040,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 diff --git a/zh-cn/device-dev/kernel/kernel-small-debug-perf.md b/zh-cn/device-dev/kernel/kernel-small-debug-perf.md new file mode 100644 index 0000000000000000000000000000000000000000..d0fd27d409de6dbbf7d5a9e565a731306409aa54 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-small-debug-perf.md @@ -0,0 +1,270 @@ +# Perf调测 + + +## 基本概念 + +Perf为性能分析工具,依赖PMU(Performance Monitoring Unit)对采样事件进行计数和上下文采集,统计出热点分布(hot spot)和热路径(hot path)。 + + +## 运行机制 + +基于事件采样原理,以性能事件为基础,当事件发生时,相应的事件计数器溢出发生中断,在中断处理函数中记录事件信息,包括当前的pc、当前运行的任务ID以及调用栈等信息。 + +Perf提供2种工作模式,计数模式和采样模式。 + +计数模式仅统计事件发生的次数和耗时,采样模式会收集上下文数据到环形buffer中,需要IDE进行数据解析生成热点函数与热点路径。 + + +## 接口说明 + +OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细信息可以查看[API](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_perf.h)参考。 + + **表1** Perf模块接口说明 + +| 功能分类 | 接口描述 | +| -------- | -------- | +| 开启/停止Perf采样 | LOS_PerfInit : 初始化Perf
LOS_PerfStart:开启采样
LOS_PerfStop:停止采样 | +| 配置Perf采样事件 | LOS_PerfConfig:配置采样事件的类型、周期等 | +| 读取采样数据 | LOS_PerfDataRead:读取采样数据到指定地址 | +| 注册采样数据缓冲区的钩子函数 | LOS_PerfNotifyHookReg:注册缓冲区水线到达的处理钩子
LOS_PerfFlushHookReg:注册缓冲区刷cache的钩子 | + + +1. Perf采样事件的结构体为PerfConfigAttr,详细字段含义及取值详见 [kernel\include\los_perf.h](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_perf.h) 。 + +2. 采样数据缓冲区为环形buffer,buffer中读过的区域可以覆盖写,未被读过的区域不能被覆盖写。 + +3. 缓冲区有限,用户可通过注册水线到达的钩子进行buffer溢出提醒或buffer读操作。默认水线值为buffer总大小的1/2。 示例如下: + + ```c + VOID Example_PerfNotifyHook(VOID) + { + CHAR buf[LOSCFG_PERF_BUFFER_SIZE] = {0}; + UINT32 len; + PRINT_DEBUG("perf buffer reach the waterline!\n"); + len = LOS_PerfDataRead(buf, LOSCFG_PERF_BUFFER_SIZE); + OsPrintBuff(buf, len); /* print data */ + } + LOS_PerfNotifyHookReg(Example_PerfNotifyHook); + ``` + +4. 若perf采样的buffer涉及到CPU跨cache,则用户可通过注册刷cache的钩子,进行cache同步。 示例如下: + + ```c + VOID Example_PerfFlushHook(VOID *addr, UINT32 size) + { + OsCacheFlush(addr, size); /* platform interface */ + } + LOS_PerfNotifyHookReg(Example_PerfFlushHook); + ``` + + 刷cache接口视具体的平台自行配置。 + + +## 开发指导 + + +### 内核态开发流程 + +开启Perf调测的典型流程如下: + +1. 配置Perf模块相关宏。 + 配置Perf控制宏LOSCFG_KERNEL_PERF,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Perf Feature"中打开: + + | 配置项 | 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 | + | LOSCFG_PERF_CALC_TIME_BY_CYCLE | Time-consuming Calc Methods->By Cpu Cycle | Perf计时单位为cycle | YES/NO | + | LOSCFG_PERF_BUFFER_SIZE | Perf Sampling Buffer Size | Perf采样buffer的大小 | INT | + | LOSCFG_PERF_HW_PMU | Enable Hardware Pmu Events for Sampling | 使能硬件PMU事件,需要目标平台支持硬件PMU | YES/NO | + | LOSCFG_PERF_TIMED_PMU | Enable Hrtimer Period Events for Sampling | 使能高精度周期事件,需要目标平台支持高精度定时器 | YES/NO | + | LOSCFG_PERF_SW_PMU | Enable Software Events for Sampling | 使能软件事件,需要开启LOSCFG_KERNEL_HOOK | YES/NO | + +2. 调用LOS_PerfConfig配置需要采样的事件。 + Perf提供2种模式的配置,及3大类型的事件配置: + + 2种模式:计数模式(仅统计事件发生次数)、采样模式(收集上下文如任务ID、pc、backtrace等)。 + + 3种事件类型:CPU硬件事件(cycle、branch、icache、dcache等)、高精度周期事件(cpu clock)、OS软件事件(task switch、mux pend、irq等)。 + +3. 在需要采样的代码起始点调用LOS_PerfStart(UINT32 sectionId), 入参sectionId标记不同的采样回话id。 + +4. 在需要采样的代码结束点调用LOS_PerfStop。 + +5. 调用输出缓冲区数据的接口LOS_PerfDataRead读取采样数据,并使用IDE工具进行解析。 + + +#### 内核态编程实例 + +本实例实现如下功能: + +1. 创建perf测试任务。 + +2. 配置采样事件。 + +3. 启动perf。 + +4. 执行需要统计的算法。 + +5. 停止perf。 + +6. 输出统计结果。 + + +#### 内核态示例代码 + +前提条件:在menuconfig菜单中完成perf模块的配置, 并勾选Enable Hook Feature,Enable Software Events for Sampling。 + +为方便学习,本演示代码直接在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证即可。 + +实例代码如下: + +```c +#include "los_perf.h" +#define TEST_MALLOC_SIZE 200 +#define TEST_TIME 5 + +/* 验证函数中进行malloc和free */ +VOID test(VOID) +{ + VOID *p = NULL; + int i; + for (i = 0; i < TEST_TIME; i++) { + p = LOS_MemAlloc(m_aucSysMem1, TEST_MALLOC_SIZE); + if (p == NULL) { + PRINT_ERR("test alloc failed\n"); + return; + } + + (VOID)LOS_MemFree(m_aucSysMem1, p); + } +} + +STATIC VOID OsPrintBuff(const CHAR *buf, UINT32 num) +{ + UINT32 i = 0; + PRINTK("num: "); + for (i = 0; i < num; i++) { + PRINTK(" %02d", i); + } + PRINTK("\n"); + PRINTK("hex: "); + for (i = 0; i < num; i++) { + PRINTK(" %02x", buf[i]); + } + PRINTK("\n"); +} +STATIC VOID perfTestHwEvent(VOID) +{ + UINT32 ret; + CHAR *buf = NULL; + UINT32 len; + + //LOS_PerfInit(NULL, 0); + + + PerfConfigAttr attr = { + .eventsCfg = { + .type = PERF_EVENT_TYPE_SW, + .events = { + [0] = {PERF_COUNT_SW_TASK_SWITCH, 0xff}, /* 抓取调度 */ + [1] = {PERF_COUNT_SW_MEM_ALLOC, 0xff}, /* 抓取内存分配 */ + + PERF_COUNT_SW_TASK_SWITCH + }, + .eventsNr = 2, + .predivided = 1, /* cycle counter increase every 64 cycles */ + }, + .taskIds = {0}, + .taskIdsNr = 0, + .needSample = 0, + .sampleType = PERF_RECORD_IP | PERF_RECORD_CALLCHAIN, + }; + ret = LOS_PerfConfig(&attr); + if (ret != LOS_OK) { + PRINT_ERR("perf config error %u\n", ret); + return; + } + PRINTK("------count mode------\n"); + LOS_PerfStart(0); + test(); /* this is any test function*/ + LOS_PerfStop(); + PRINTK("--------sample mode------ \n"); + attr.needSample = 1; + LOS_PerfConfig(&attr); + LOS_PerfStart(2); // 2: set the section id to 2. + test(); /* this is any test function*/ + LOS_PerfStop(); + buf = LOS_MemAlloc(m_aucSysMem1, LOSCFG_PERF_BUFFER_SIZE); + if (buf == NULL) { + PRINT_ERR("buffer alloc failed\n"); + return; + } + /* get sample data */ + len = LOS_PerfDataRead(buf, LOSCFG_PERF_BUFFER_SIZE); + OsPrintBuff(buf, len); /* print data */ + (VOID)LOS_MemFree(m_aucSysMem1, buf); +} + +UINT32 Example_Perf_test(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S perfTestTask = {0}; + UINT32 taskID; + /* 创建用于perf测试的任务 */ + perfTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)perfTestHwEvent; + perfTestTask.pcName = "TestPerfTsk"; /* 测试任务名称 */ + perfTestTask.uwStackSize = 0x1000; // 0x8000: perf test task stack size + perfTestTask.usTaskPrio = 5; // 5: perf test task priority + ret = LOS_TaskCreate(&taskID, &perfTestTask); + if (ret != LOS_OK) { + PRINT_ERR("PerfTestTask create failed. 0x%x\n", ret); + return LOS_NOK; + } + return LOS_OK; +} +LOS_MODULE_INIT(perfTestHwEvent, LOS_INIT_LEVEL_KMOD_EXTENDED); +``` + + +#### 内核态结果验证 + + 输出结果如下: + +``` +type: 2 +events[0]: 1, 0xff +events[1]: 3, 0xff +predivided: 1 +sampleType: 0x60 +needSample: 0 +------count mode------ +[task switch] eventType: 0x1 [core 0]: 0 +[mem alloc] eventType: 0x3 [core 0]: 5 +time used: 0.005000(s) +--------sample mode------ +type: 2 +events[0]: 1, 0xff +events[1]: 3, 0xff +predivided: 1 +sampleType: 0x60 +needSample: 1 +dump perf data, addr: 0x402c3e6c length: 0x5000 +time used: 0.000000(s) +num: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 +hex: 00 ffffffef ffffffef ffffffef 02 00 00 00 14 00 00 00 60 00 00 00 02 00 00 00 + +根据实际运行环境,过程打印会有差异 +``` + +- 针对计数模式,系统在perf stop后会打印: + 事件名称(cycles)、事件类型(0xff)、事件发生的次数(5466989440)。 + + 当采样事件为硬件PMU事件时,打印的事件类型为实际的硬件事件id,非enum PmuHWId中定义的抽象类型。 + +- 针对采样模式,系统在perf stop后会打印采样数据的地址和长度: + dump section data, addr: (0x8000000) length: (0x5000) + + 用户可以通过JTAG口导出该片内存,再使用IDE线下工具解析。 + + 或者通过LOS_PerfDataRead将数据读到指定地址,进行查看或进一步处理。示例中OsPrintBuff为测试接口,其按字节打印Read到的采样数据,num表示第几个字节,hex表示该字节中的数值。 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 7e84b5195532059544f948b4dd6661fcf318640f..0da63e4873506c9ae019e5e2affaae47cbe15d92 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 @@ -6,16 +6,16 @@ CPU(中央处理器,Central Processing Unit)占用率分为系统CPU占用率、进程CPU占用率、任务CPU占用率和中断CPU占用率。用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。通过系统中各个进程/任务/中断的CPU占用情况,判断各个进程/任务/中断的CPU占用率是否符合设计的预期。 - 系统CPU占用率(CPU Percent) - 指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示系统满负荷运转。 + 指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分之一。100表示系统满负荷运转。 - 进程CPU占用率 - 指单个进程的CPU占用率,用于表示单个进程在一段时间内的闲忙程度。进程CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该进程。 + 指单个进程的CPU占用率,用于表示单个进程在一段时间内的闲忙程度。进程CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分之一。100表示在一段时间内系统一直在运行该进程。 - 任务CPU占用率 - 指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该任务。 + 指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分之一。100表示在一段时间内系统一直在运行该任务。 - 中断CPU占用率 - 指单个中断的CPU占用率,用于表示单个中断在一段时间内的闲忙程度。中断CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该中断。 + 指单个中断的CPU占用率,用于表示单个中断在一段时间内的闲忙程度。中断CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分之一。100表示在一段时间内系统一直在运行该中断。 ## 运行机制 @@ -50,13 +50,14 @@ OpenHarmony 提供以下四种CPU占用率的信息查询: **表1** CPUP模块接口 -| 功能分类 | 接口**名称** | 描述 | +| 功能分类 | 接口**名称** | 描述 | | -------- | -------- | -------- | -| 系统CPU占用率 | LOS_HistorySysCpuUsage | 获取系统历史CPU占用率 | -| 进程CPU占用率 | LOS_HistoryProcessCpuUsage | 获取指定进程历史CPU占用率 | -| 进程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占用率 | +| 重置 | LOS_CpupReset | 重置CPU 占用率相关数据 | ### 开发流程 @@ -102,48 +103,50 @@ CPU占用率的典型开发流程: **示例代码** +本演示代码在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证,在TestTaskEntry中调用验证入口函数CpupTest。 代码实现如下: - -``` + +```c #include "los_task.h" -#include "los_cpup.h" +#include "los_cpup.h" #define MODE 4 -UINT32 g_cpuTestTaskID; -VOID ExampleCpup(VOID) -{ - printf("entry cpup test example\n"); - while(1) { - usleep(100); +UINT32 g_cpuTestTaskID; +VOID ExampleCpup(VOID) +{ + int i = 0; + dprintf("entry cpup test example\n"); + for (i = 0; i < 10; i++) { + usleep(100); // 100: delay for 100ms } } -UINT32 ItCpupTest(VOID) -{ +UINT32 CpupTest(VOID) +{ UINT32 ret; UINT32 cpupUse; - TSK_INIT_PARAM_S cpupTestTask = { 0 }; + TSK_INIT_PARAM_S cpupTestTask = {0}; memset(&cpupTestTask, 0, sizeof(TSK_INIT_PARAM_S)); cpupTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleCpup; - cpupTestTask.pcName = "TestCpupTsk"; - cpupTestTask.uwStackSize = 0x800; - cpupTestTask.usTaskPrio = 5; + cpupTestTask.pcName = "TestCpupTsk"; + cpupTestTask.uwStackSize = 0x800; // 0x800: cpup test task stack size + cpupTestTask.usTaskPrio = 5; // 5: cpup test task priority ret = LOS_TaskCreate(&g_cpuTestTaskID, &cpupTestTask); - if(ret != LOS_OK) { + if (ret != LOS_OK) { printf("cpupTestTask create failed .\n"); return LOS_NOK; } - usleep(100); + usleep(100); // 100: delay for 100ms /* 获取当前系统历史CPU占用率 */ - cpupUse = LOS_HistorySysCpuUsage(CPU_LESS_THAN_1S); - printf("the history system cpu usage in all time:%u.%u\n", + cpupUse = LOS_HistorySysCpuUsage(CPUP_LAST_ONE_SECONDS); + dprintf("the history system cpu usage in all time:%u.%u\n", cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); - /* 获取指定任务的CPU占用率,该测试例程中指定的任务为以上创建的cpup测试任务 */ - cpupUse = LOS_HistoryTaskCpuUsage(g_cpuTestTaskID, CPU_LESS_THAN_1S); - printf("cpu usage of the cpupTestTask in all time:\n TaskID: %d\n usage: %u.%u\n", - g_cpuTestTaskID, cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); - return LOS_OK; + /* 获取指定任务的CPU占用率,该测试例程中指定的任务为以上创建的cpup测试任务 */ + cpupUse = LOS_HistoryTaskCpuUsage(g_cpuTestTaskID, CPUP_LAST_ONE_SECONDS); + dprintf("cpu usage of the cpupTestTask in all time:\n TaskID: %d\n usage: %u.%u\n", + g_cpuTestTaskID, cpupUse / LOS_CPUP_PRECISION_MULT, cpupUse % LOS_CPUP_PRECISION_MULT); + return LOS_OK; } ``` @@ -151,9 +154,11 @@ UINT32 ItCpupTest(VOID) 编译运行得到的结果为: - + ``` entry cpup test example the history system cpu usage in all time: 3.0 cpu usage of the cpupTestTask in all time: TaskID:10 usage: 0.0 + +根据实际运行环境,打印会有差异 ``` 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 f5f8df2f9c69e0c500b665bf5cadf7a5a2681895..2d37c9d61de5941f2c72e61ab858ea4e1846d7ce 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 @@ -13,12 +13,12 @@ cpup [_mode_] [_taskID_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | -| mode | - 缺省:显示系统最近10s内的CPU占用率。
- 0:显示系统最近10s内的CPU占用率。
- 1:显示系统最近1s内的CPU占用率。
- 其他数字:显示系统启动至今总的CPU 占用率。 | [0,0xFFFFFFFF] | -| taskID | 任务ID号 | [0,0xFFFFFFFF] | +| mode | - 缺省:显示系统最近10s内的CPU占用率。
- 0:显示系统最近10s内的CPU占用率。
- 1:显示系统最近1s内的CPU占用率。
- 其他数字:显示系统启动至今总的CPU 占用率。 | [0, 0xFFFFFFFF] | +| taskID | 任务ID号 | [0, 0xFFFFFFFF] | ## 使用指南 @@ -37,8 +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 164bbb70804ba1fb045824fab116f9e3f6c763d0..fd0ebe27bd33d13b0d50a4d652806695b123567e 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 @@ -19,13 +19,13 @@ date命令用于查询系统日期和时间。 ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 使用帮助。 | N/A | -| +Format | 根据Format格式打印日期和时间。 | --help中列出的占位符。 | -| -u | 显示UTC,而不是当前时区 | N/A | +| 参数 | 参数说明 | 取值范围 | +| ------- | ------------------------------ | ---------------------- | +| --help | 使用帮助。 | N/A | +| +Format | 根据Format格式打印日期和时间。 | --help中列出的占位符。 | +| -u | 显示UTC,而不是当前时区 | N/A | ## 使用指南 @@ -36,6 +36,9 @@ date命令用于查询系统日期和时间。 - 目前命令不支持设置时间和日期。 +## 特殊说明 + +date -u参数 shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -46,8 +49,8 @@ date命令用于查询系统日期和时间。 示例:按指定格式打印系统日期 - + ``` OHOS:/$ date +%Y--%m--%d 1970--01--01 -``` +``` \ No newline at end of file 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 5c1bc4e332ecd4df168a47b267df834236156738..b30fcfd00e5bb13ee9942a1b0c6e5834d3e3e09e 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 @@ -3,7 +3,7 @@ ## 命令功能 -dmesg命令用于显示系统启动过程和运行过程中的信息。 +dmesg命令用于显示开机信息,以及系统启动过程和运行过程中的信息。 ## 命令格式 @@ -21,22 +21,22 @@ dmesg > [_fileA_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -c | 打印缓存区内容并清空缓存区。 | N/A | -| -C | 清空缓存区。 | N/A | -| -D/-E | 关闭/开启控制台打印。 | N/A | -| -L/-U | 关闭/开启串口打印。 | N/A | -| -s size | 设置缓存区大小 size是要设置的大小。 | N/A | -| -l level | 设置缓存等级。 | 0 - 5 | -| > fileA | 将缓存区内容重定向写入文件。 | N/A | +| 参数 | 参数说明 | 取值范围 | +| --------------- | ---------------------------------------- | --------------- | +| -c | 打印缓存区内容并清空缓存区。 | N/A | +| -C | 清空缓存区。 | N/A | +| -D/-E | 关闭/开启控制台打印。 | N/A | +| -L/-U | 关闭/开启串口打印。 | N/A | +| -s size | 设置缓存区大小 size是要设置的大小。 | N/A | +| -l level | 设置缓存等级。 | [0, 5] | +| > fileA | 将缓存区内容重定向写入文件。 | N/A | ## 使用指南 -- 该命令依赖于LOSCFG_SHELL_DMESG,使用时通过menuconfig在配置项中开启"Enable Shell dmesg": +- 该命令依赖于LOSCFG_SHELL_DMESG,在kernel/liteos_a中输入make menuconfig命令。此时会弹出配置项,找到Debug选项并进入,然后在配置项中开启"Enable Shell dmesg": Debug ---> Enable a Debug Version ---> Enable Shell ---> Enable Shell dmesg - dmesg参数缺省时,默认打印缓存区内容。 @@ -53,9 +53,9 @@ dmesg > [_fileA_] ## 输出说明 - **示例**:dmesg重定向到文件 - +**示例** dmesg重定向到文件 + ``` OHOS # dmesg > dmesg.log Dmesg write log to dmesg.log success -``` +``` \ No newline at end of file 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 0777cb4fd2de7c68e72594b70d8fa0f8d0af03eb..abd8f19eb5095b564f7b8a4c372fc736a4819bba 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 @@ -3,7 +3,7 @@ ## 命令功能 -exec命令属于shell内置命令,目前实现最基础的执行用户态程序的功能。 +exec命令属于shell内置命令,在exec执行命令时,不启用新的shell进程。目前实现最基础的执行用户态程序的功能 ## 命令格式 @@ -13,11 +13,11 @@ exec <_executable-file_> ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| executable-file | 有效的可执行文件。 | N/A | +| 参数 | 参数说明 | +| --------------- | ------------------ | +| executable-file | 有效的可执行文件。 | ## 使用指南 @@ -34,11 +34,11 @@ exec <_executable-file_> ## 输出说明 - + ``` OHOS # exec helloworld OHOS # hello world! ``` > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> 可执行文件执行后,先打印“OHOS \#”提示符原因:目前Shell “exec”命令执行均为后台执行,结果可能导致提示符提前打印。 +> 可执行文件执行后,先打印“OHOS \#”提示符原因:目前Shell “exec”命令执行均为后台执行,结果可能导致提示符提前打印。 \ No newline at end of file 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 d66ac6c1d2ebfbd69210d17278f0e74c5e5054bc..585a924fe969a83c28c6c0d50d58fc849e6feab6 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 @@ -13,17 +13,17 @@ free [_-b | -k | -m | -g | -t_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| 无参数 | 以Byte为单位显示。 | N/A | -| --help/-h | 查看free命令支持的参数列表。 | N/A | -| -b | 以Byte为单位显示。 | N/A | -| -k | 以KiB为单位显示。 | N/A | -| -m | 以MiB为单位显示。 | N/A | -| -g | 以GiB为单位显示。 | N/A | -| -t | 以TiB为单位显示。 | N/A | +| 参数 | 参数说明 | +| -------- | -------- | +| 无参数 | 以Byte为单位显示。 | +| --help/-h | 查看free命令支持的参数列表。 | +| -b | 以Byte为单位显示。 | +| -k | 以KiB为单位显示。 | +| -m | 以MiB为单位显示。 | +| -g | 以GiB为单位显示。 | +| -t | 以TiB为单位显示。 | ## 使用指南 @@ -57,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 47847e242506a858499ebd7cef7c8f285740f3f9..cbe033416b025ee0b0fd880d9802cbe79a658996 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 @@ -13,7 +13,7 @@ help ## 参数说明 -无。 +无 ## 使用指南 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 f184a21da0189920c0ae1aaff5639d548334cd9c..52ea5c5e7c2e0760bc1480cb5032310e5f5dce20 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 @@ -13,7 +13,7 @@ hwi ## 参数说明 -无。 +无 ## 使用指南 @@ -106,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 c29953e112a2961fb15490b7033d689afb00f159..b35ec5e5361f628593d07f33243fbb6b917ec538 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 @@ -3,7 +3,7 @@ ## 命令功能 -命令用于发送特定信号给指定进程。 +kill命令用于发送特定信号给指定进程,让它去终结不正常的应用。 ## 命令格式 @@ -13,31 +13,34 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看kill命令支持的参数列表 | N/A | -| -l | 列出信号名称和编号。 | N/A | -| -s | 发送信号 | N/A | -| signo | 信号ID。 | [1,30] | -| pid | 进程ID。 | [1,MAX_INT] | +| 参数 | 参数说明 | 取值范围 | +| ------ | -------------------------- | ----------- | +| --help | 查看kill命令支持的参数列表 | N/A | +| -l | 列出信号名称和编号。 | N/A | +| -s | 发送信号 | N/A | +| signo | 信号ID。 | [1, 30] | +| pid | 进程ID。 | [1, MAX_INT] | > ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** -> signo有效范围为[0,64],建议取值范围为[1,30],其余为保留内容。 +> signo有效范围为[0, 64],建议取值范围为[1, 30],其余为保留内容。 ## 使用指南 - 必须指定发送的信号编号及进程号。 -- 进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为[1-256]。 +- 进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为[1, 256]。 +## 特殊说明 + +kill命令以及参数 shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 - 查看当前进程列表,查看需要杀死的进程PID(42)。 - + ``` OHOS:/$ ps allCpu(%): 4.67 sys, 195.33 idle @@ -60,7 +63,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:/$ @@ -91,9 +94,9 @@ kill [-l [_signo_] | _-s signo_ | _-signo_] _pid..._ 发送成功或失败输出结果如下。 -**示例 1** 发送信号给指定进程 +**示例1** 发送信号给指定进程 + - ``` OHOS:/$ kill -s 9 42 OHOS:/$ @@ -102,12 +105,12 @@ OHOS:/$ 信号发送成功会显示的提示进程已被杀死。 -**示例 2** 信号发送失败 +**示例2** 信号发送失败 + - ``` OHOS:/$ kill -100 31 kill: Unknown signal '(null)' ``` -信号发送失败,示例2所示原因为信号发送命令参数无效,请排查信号编号及进程编号是否有效。 +信号发送失败,示例2所示原因为信号发送命令参数无效,请排查信号编号及进程编号是否有效。 \ No newline at end of file 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 35b30bd90fece1cfa45b25efce7fbdb524a56778..5747814bb8ded3f2fad4e61017b0c481633d76bb 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 @@ -13,11 +13,11 @@ log level [_levelNum_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | -| levelNum | 配置日志打印等级。 | [0,5] | +| levelNum | 配置日志打印等级。 | [0, 5] | ## 使用指南 @@ -52,9 +52,9 @@ log level [_levelNum_] ## 输出说明 -**示例**:设置当前日志打印级别为3 +**示例** 设置当前日志打印级别为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 6edb6f2c18540ac1c42e2b15c44bdedd4ea72ef4..a8f9681b442e3c60c411d6a1b73a20b0f718afff 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 @@ -13,7 +13,7 @@ memcheck ## 参数说明 -无。 +无 ## 使用指南 @@ -34,15 +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 c7c4a19f652e2f66a40844cd78271d8763c71618..c54a17367a3736cfb008d549a418ac9803279ea4 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 @@ -21,19 +21,20 @@ oom -h | --help ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -i [interval] | 设置oom线程任务检查的时间间隔。 | 100ms ~ 10000ms | -| -m [mem byte] | 设置低内存阈值。 | 0MB ~ 1MB,0MB表示不做低内存阈值检查。 | -| -r [mem byte] | 设置pagecache内存回收阈值。 | 低内存阈值 ~ 系统可用最大内存。 | -| -h \| --help | 使用帮助。 | N/A | +| 参数 | 参数说明 | 取值范围 | +| ----------------------- | ------------------------------- | ------------------------------------------------------------ | +| -i [interval] | 设置oom线程任务检查的时间间隔。 | [100, 10000] 单位: ms | +| -m [mem byte] | 设置低内存阈值。 | 0MB ~ 1MB,0MB表示不做低内存阈值检查。 | +| -r [mem byte] | 设置pagecache内存回收阈值。 | 低内存阈值 ~ 系统可用最大内存,一个pagecache页一般为4KB,也有16 ~ 64KB的情况。 | +| -h \| --help | 使用帮助。 | N/A | ## 使用指南 参数缺省时,显示oom功能当前配置信息。 + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 当系统内存不足时,会打印出内存不足的提示信息。 @@ -49,9 +50,9 @@ oom -h | --help ## 输出说明 -**示例1:**oom缺省打印配置信息 +**示例1** oom缺省打印配置信息 + - ``` OHOS:/$ oom [oom] oom loop task status: enabled @@ -62,7 +63,7 @@ OHOS:/$ oom 系统内存不足时打印提示信息 - + ``` T:20 Enter:IT MEM 00M 001 [oom] OS is in low memory state @@ -109,22 +110,22 @@ traceback 5 -- 1r = 0x20c4df50 fp = 0хb0b0b0b 1r in /1ib/libc.so - -> 0x62f50 ``` -**示例2**:设置 oom 线程任务检查的时间间隔 +**示例2** 设置 oom 线程任务检查的时间间隔 + - ``` OHOS:/$ oom -i 100 [oom] set oom check interval (100)ms successful ``` - **表2** 输出说明 +**表2** 输出说明 -| 输出 | 说明 | -| -------- | -------- | -| [oom] OS is in low memory state
total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte), free: 0x7f000(byte), low memory threshold: 0x80000(byte) | 操作系统处于低内存状态。
整个系统可用物理内存为0x1bcf000 byte,已经使用了 0x1b50000 byte, 还剩0x7f000 byte,当前设置的低内存阈值为0x80000 byte。 | -| [oom] candidate victim process init pid: 1, actual phy mem byte: 82602 | 打印当前各个进程的内存使用情况,init进程实际占用物理内存82602byte。 | -| [oom] candidate victim process UserProcess12 pid: 12, actual phy mem byte: 25951558 | UserProcess12进程实际使用25951558byte内存。 | -| [oom] max phy mem used process UserProcess12 pid: 12, actual phy mem: 25951558 | 当前使用内存最多的进程是UserProcess12。 | -| excFrom: User! | 当系统处于低内存的情况下,UserProcess12进程再去申请内存时失败退出。 | +| 输出 | 说明 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| [oom] OS is in low memory state
total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte), free: 0x7f000(byte), low memory threshold: 0x80000(byte) | 操作系统处于低内存状态。
整个系统可用物理内存为0x1bcf000 byte,已经使用了 0x1b50000 byte, 还剩0x7f000 byte,当前设置的低内存阈值为0x80000 byte。 | +| [oom] candidate victim process init pid: 1, actual phy mem byte: 82602 | 打印当前各个进程的内存使用情况,init进程实际占用物理内存82602byte。 | +| [oom] candidate victim process UserProcess12 pid: 12, actual phy mem byte: 25951558 | UserProcess12进程实际使用25951558byte内存。 | +| [oom] max phy mem used process UserProcess12 pid: 12, actual phy mem: 25951558 | 当前使用内存最多的进程是UserProcess12。 | +| excFrom: User! | 当系统处于低内存的情况下,UserProcess12进程再去申请内存时失败退出。 | \ No newline at end of file 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 639152773cef118341b0199db113eba959b46967..0e6203b3b75cf98ef0edce1eec473b362039509e 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 @@ -28,8 +28,8 @@ Debug版本才具备的命令。 ## 输出说明 - **示例:**查看物理页使用情况 - +**示例** 查看物理页使用情况 + ``` OHOS # pmm phys_seg base size free_pages @@ -55,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 b81be050fa28a9ff6745707050fe3dda78cd268c..6ef9d0487a07a7d279d6aaa57228853d43a43948 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 @@ -13,7 +13,7 @@ reboot ## 参数说明 -无。 +无 ## 使用指南 @@ -28,4 +28,4 @@ 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 bac39a77df20e2169506d9b62b87977b6e5f9675..3db9ef7170c686f99104c30aa1a745a6053234c7 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 @@ -13,7 +13,7 @@ reset ## 参数说明 -无。 +无 ## 使用指南 @@ -28,4 +28,4 @@ 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 bdcf23dbcf131ab20306089829c72c997cea2d45..c5a88de39cf7b09764b4594805d79444fc5c2ffe 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 @@ -13,7 +13,7 @@ sem [_ID__ / fulldata_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -40,8 +40,8 @@ sem [_ID__ / fulldata_] ## 输出说明 - **示例1**:查询所有在用的信号量信息 - +**示例1** 查询所有在用的信号量信息 + ``` OHOS # sem SemID Count @@ -67,7 +67,7 @@ OHOS # sem 0x00000006 0 ``` - **表2** 输出说明 +**表2** 输出说明 | 输出 | 说明 | | -------- | -------- | @@ -79,8 +79,8 @@ OHOS # sem > > ● sem命令的ID参数在[0, 1023]范围内时,返回对应ID的信号量的状态(如果对应ID的信号量未被使用则进行提示);其他取值时返回参数错误的提示。 - **示例2:**查询所有在用的信号量信息 - +**示例2** 查询所有在用的信号量信息 + ``` OHOS # sem fulldata Used Semaphore List: @@ -113,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 c8a872c90c992abb05771fcc702425c4e92c1a78..57500e7436546a7cf2f6e776781eab433c0039b2 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 @@ -13,12 +13,12 @@ stack ## 参数说明 -无。 +无 ## 使用指南 -无。 +无 ## 使用实例 @@ -28,8 +28,8 @@ stack ## 输出说明 - **示例:**系统堆栈使用情况 - +**示例** 系统堆栈使用情况 + ``` OHOS # stack stack name cpu id stack addr total size used size @@ -40,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 6465bb4c8826ddb0e55de2b2740e5f5e6fefe795..af014d300dce083df3603cd7098be2e3d9e31713 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 @@ -13,12 +13,12 @@ su [_uid_] [_gid_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | -| uid | 目标用户的用户id值。 | - 为空。
- [0,60000] | -| gid | 目标用户的群组id值。 | - 为空。
- [0,60000] | +| uid | 目标用户的用户id值。 | - 为空。
- [0, 60000] | +| gid | 目标用户的群组id值。 | - 为空。
- [0, 60000] | ## 使用指南 @@ -37,8 +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 73d7c12d49fc311131f6792497b63fdea4167752..63b7ea7fdb334d11563272a5f774c948c6003dcb 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 @@ -13,11 +13,11 @@ swtmr [_ID_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | -| ID | 软件定时器ID号。 | [0,0xFFFFFFFF] | +| ID | 软件定时器ID号。 | [0, 0xFFFFFFFF] | ## 使用指南 @@ -38,8 +38,8 @@ swtmr [_ID_] ## 输出说明 - **示例1:**查询所有软件定时器相关信息 - +**示例1** 查询所有软件定时器相关信息 + ``` OHOS # swtmr SwTmrID State Mode Interval Count Arg handlerAddr @@ -59,8 +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 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 b272a957851ccdabe3e17305c2c7fabe18a626d9..a9dcc0e5df8780865f5b5877e1ac889f64815340 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 @@ -13,12 +13,12 @@ systeminfo ## 参数说明 -无。 +无 ## 使用指南 -无。 +无 ## 使用实例 @@ -28,8 +28,8 @@ systeminfo ## 输出说明 - **示例:**查看系统资源使用情况 - +**示例** 查看系统资源使用情况 + ``` OHOS:/$ systeminfo Module Used Total Enabled @@ -40,16 +40,15 @@ OHOS:/$ systeminfo SwTmr 20 1024 YES ``` - **表1** 输出说明 - -| 输出 | 说明 | -| -------- | -------- | -| Module | 模块名称。 | -| Used | 当前使用量。 | -| Total | 最大可用量。 | -| Enabled | 模块是否开启。 | -| Task | 任务。 | -| Sem | 信号量。 | -| Mutex | 互斥量。 | -| Queue | 队列。 | -| SwTmr | 定时器。 | +**表1** 输出说明 + +| 输出 | 说明 | +| ------- | -------------- | +| Module | 模块名称。 | +| Used | 当前使用量。 | +| Total | 最大可用量。 | +| Enabled | 模块是否开启。 | +| Task | 任务。 | +| Sem | 信号量。 | +| Queue | 队列。 | +| SwTmr | 定时器。 | \ No newline at end of file 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 2babe2adc87c2249f0e935ec83f5b01394e2e7c3..42f6a75f81c5594394c98b0eabc22bee215489a6 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 @@ -13,7 +13,7 @@ task/task -a ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -32,9 +32,8 @@ task/task -a ## 输出说明 -**示例:**查询任务部分信息 +**示例** 查询任务部分信息 - ``` OHOS # task allCpu(%): 3.54 sys, 196.46 idle @@ -61,7 +60,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 41d77ab903df37265daf6e82421d6fd390ee589f..5decca4e6385de69ca3c669b3018f44bbb7f4d90 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 @@ -13,18 +13,21 @@ top [_-a_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 缺省值 | 取值范围 | -| -------- | -------- | -------- | -------- | -| --help | 查看top命令支持的参数列表。 | N/A | | -| -a | 显示更详细的信息。 | N/A | | +| 参数 | 参数说明 | +| ------ | --------------------------- | +| --help | 查看top命令支持的参数列表。 | +| -a | 显示更详细的信息。 | ## 使用指南 参数缺省时默认打印部分任务信息。 +## 特殊说明 + +shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -33,8 +36,8 @@ top [_-a_] ## 输出说明 - **示例1** top 命令显示详情 - +**示例1** top 命令显示详情 + ``` OHOS:/$ top allCpu(%): 4.68 sys, 195.32 idle @@ -78,19 +81,19 @@ OHOS:/$ top 64 2 0x3 -1 Pending 0x4000 0x244 0.0 0 USB_NGIAN_BULK_TasK ``` - **表2** 输出元素说明 - -| 输出 | 说明 | -| -------- | -------- | -| PID | 进程ID。 | -| PPID | 父进程ID。 | -| PGID | 进程组ID。 | -| UID | 用户ID。 | -| Status | 任务当前的状态。 | -| CPUUSE10s | 10秒内CPU使用率。 | -| PName | 进程名。 | -| TID | 任务ID。 | -| StackSize | 任务堆栈的大小。 | -| WaterLine | 栈使用的峰值。 | -| MEMUSE | 内存使用量。 | -| TaskName | 任务名。 | +**表2** 输出元素说明 + +| 输出 | 说明 | +| --------- | ----------------- | +| PID | 进程ID。 | +| PPID | 父进程ID。 | +| PGID | 进程组ID。 | +| UID | 用户ID。 | +| Status | 任务当前的状态。 | +| CPUUSE10s | 10秒内CPU使用率。 | +| PName | 进程名。 | +| TID | 任务ID。 | +| StackSize | 任务堆栈的大小。 | +| WaterLine | 栈使用的峰值。 | +| MEMUSE | 内存使用量。 | +| TaskName | 任务名。 | \ No newline at end of file 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 751e98cd71e0dc448080120cd85aeacba4c595fb..c5f9fb60c550df1de6d060e53aca09c1a640d7bc 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 @@ -11,18 +11,18 @@ uname命令用于显示当前操作系统的名称,版本创建时间,系统 uname [_-a | -s | -r | -m | -n | -v | --help_] - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | -| -------- | -------- | -| --help | 显示uname指令格式提示。 | -| 无参数 | 默认显示操作系统名称。 | -| -a | 显示全部信息。 | -| -s | 显示操作系统名称。 | -| -r | 显示内核发行版本。 | -| -m | 显示系统架构名称。 | -| -n | 显示主机的网络域名称。 | -| -v | 显示版本信息。 | +| 参数 | 参数说明 | +| ------ | ----------------------- | +| --help | 显示uname指令格式提示。 | +| 无参数 | 默认显示操作系统名称。 | +| -a | 显示全部信息。 | +| -s | 显示操作系统名称。 | +| -r | 显示内核发行版本。 | +| -m | 显示系统架构名称。 | +| -n | 显示主机的网络域名称。 | +| -v | 显示版本信息。 | ## 使用指南 @@ -31,6 +31,9 @@ uname [_-a | -s | -r | -m | -n | -v | --help_] - 除参数--help和-a以外,其他参数可以相互搭配使用;uname -a 等价于 uname -srmnv。 +## 特殊说明 + +-r -m -n参数暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -43,20 +46,18 @@ uname [_-a | -s | -r | -m | -n | -v | --help_] ## 输出说明 -**示例1:** 查看系统信息 +**示例1** 查看系统信息 - ``` OHOS:/$ uname -a LiteOS hisilicon 2.0.0.37 LiteOS 2.0.0.37 Oct 21 2021 17:39:32 Cortex-A7 OHOS:/$ ``` -**示例2:** 只查看操作系统名称和系统架构名称 +**示例2** 只查看操作系统名称和系统架构名称 - ``` OHOS:/$ uname -ms LiteOS Cortex-A7 OHOS:/$ -``` +``` \ No newline at end of file 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 ec2d40a5dac31cd51dcbad680eb1f1d10e934de8..efdd94ffb058251a000ab1e7256da5cf494484a5 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 @@ -15,13 +15,13 @@ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | | -a | 输出所有进程的虚拟内存使用情况。 | N/A | | -h \| --help | 命令格式说明。 | N/A | -| pid | 进程ID,说明指定进程的虚拟内存使用情况。 | [0,63] | +| pid | 进程ID,说明指定进程的虚拟内存使用情况。 | [0, 63] | ## 使用指南 @@ -36,8 +36,8 @@ ## 输出说明 - **示例:**PID为3的进程虚拟内存使用信息 - +**示例** PID为3的进程虚拟内存使用信息 + ``` OHOS # vmm 3 PID aspace name base size pages @@ -62,7 +62,7 @@ OHOS # vmm 3 0x408c3ce0 /lib/libc++.so 0x23cb0000 0x00001000 CH US RD WR 1 1 ``` - **表2** 进程基本信息 +**表2** 进程基本信息 | 输出 | 说明 | | -------- | -------- | @@ -73,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 c80ea6b3bda3332915997a8426762fc3c0c7d313..9bb03350521552877a0f2742cd605dea4448e12c 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 @@ -38,8 +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-file-cat.md b/zh-cn/device-dev/kernel/kernel-small-debug-shell-file-cat.md index 1d3dbee27da897e5cce4e27c69cf0a1d177a8563..e756d0cf96809066f6915b9d6bc39638e6a3fa02 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 @@ -13,7 +13,7 @@ cat [_pathname_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -32,8 +32,8 @@ cat用于显示文本文件的内容。 ## 输出说明 - **示例**:查看 hello-openharmony.txt 文件的信息 - +**示例** 查看 hello-openharmony.txt 文件的信息 + ``` 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 6e46ea2069167e6d56ebc60ef5d083772b4c81a0..ad47d7bedb4e9afd20ef7c8ac4a355111ab5a40d 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 @@ -13,7 +13,7 @@ cd [_path_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -42,9 +42,8 @@ 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 ba5c5f55f149d8fd85a600a3179b9bd9c177c118..18b805ac99dbdc085852b1278358d2a543b2a682 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 @@ -13,20 +13,22 @@ chgrp [_group_] [_pathname_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| group | 文件群组。 | [0,0xFFFFFFFF] | -| pathname | 文件路径。 | 已存在的文件。 | +| 参数 | 参数说明 | 取值范围 | +| -------- | ---------- | -------------- | +| group | 文件群组。 | [0, 0xFFFFFFFF] | +| pathname | 文件路径。 | 已存在的文件。 | ## 使用指南 - 在需要修改的文件名前加上文件群组值就可以修改该文件的所属组。 - - fatfs文件系统不支持修改用户组id。 +## 特殊说明 + +shell端暂不支持。 ## 使用实例 @@ -35,8 +37,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 @@ -44,4 +46,4 @@ OHOS:/dev$ chgrp 100 testfile OHOS:/dev$ ll testfile -rw-r--r-- 0 0 100 0 1970-01-01 00:00 testfile OHOS:/dev$ -``` +``` \ No newline at end of file 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 f20dadc5251d4ce611a07af7fce7553d6f45c1fc..3c72ac2854e0bc8e3a5493ea9f0726383f55a5a6 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 @@ -13,12 +13,12 @@ chmod [_mode_] [_filename_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| mode | 文件或文件夹权限,用8进制表示对应User、Group、及Others(拥有者、群组、其他组)的权限。 | [0,777] | -| filename | 文件路径。 | 已存在的文件。 | +| 参数 | 参数说明 | 取值范围 | +| -------- | ------------------------------------------------------------ | -------------- | +| mode | 文件或文件夹权限,用8进制表示对应User、Group、及Others(拥有者、群组、其他组)的权限。 | [0, 777] | +| filename | 文件路径。 | 已存在的文件。 | ## 使用指南 @@ -27,6 +27,9 @@ chmod [_mode_] [_filename_] - fatfs文件系统所有创建的文件和挂载节点的权限属性保持一致,目前节点的权限只有用户读写权限,group和others权限不生效;且只允许修改用户读写权限,读写权限只有rw和ro两种。其他文件系统无限制。 +## 特殊说明 + +shell端暂不支持。 ## 使用实例 @@ -35,9 +38,8 @@ chmod [_mode_] [_filename_] ## 输出说明 -**示例:**修改/dev目录下 hello-openharmony.txt 文件的权限 +**示例** 修改/dev目录下 hello-openharmony.txt 文件的权限 - ``` OHOS:/dev$ chmod 644 hello-openharmony.txt OHOS:/dev$ ll hello-openharmony.txt @@ -45,4 +47,4 @@ OHOS:/dev$ ll 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 -``` +``` \ No newline at end of file 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 78c19d79a09dda19c07945a8d19a4ae25b3db2c3..fd3fbe56936e9e991c00289575474bf16784a147 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 @@ -13,18 +13,21 @@ chown [_owner_] [_pathname_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| owner | 文件拥有者。 | [0,0xFFFFFFFF] | -| pathname | 文件路径。 | 已存在的文件。 | +| 参数 | 参数说明 | 取值范围 | +| -------- | ------------ | -------------- | +| owner | 文件拥有者。 | [0, 0xFFFFFFFF] | +| pathname | 文件路径。 | 已存在的文件。 | ## 使用指南 修改文件的所有者,目前fatfs不支持修改。 +## 特殊说明 + +shell端暂不支持。 ## 使用实例 @@ -33,9 +36,8 @@ chown [_owner_] [_pathname_] ## 输出说明 -示例 1 修改 /dev下的testfile 文件的uid为100 +**示例1** 修改 /dev下的testfile 文件的uid为100 - ``` OHOS:/dev$ touch testfile OHOS:/dev$ ll testfile @@ -43,4 +45,4 @@ OHOS:/dev$ ll testfile OHOS:/dev$ chown 100 testfile OHOS:/dev$ ll testfile -rw-r--r-- 0 100 100 0 1970-01-01 00:00 testfile -``` +``` \ No newline at end of file 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 e61e8c673a1d77ed2c35d14e557520f673f4b0ff..9f6cad18bc20abae12fe8b36ecdbc58bdf103c26 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 @@ -47,9 +47,8 @@ cp [_SOURCEFILE_] [_DESTFILE_] ## 输出说明 -**示例:**同时拷贝两个文件至指定目录 +**示例** 同时拷贝两个文件至指定目录 - ``` OHOS:/$ ls bin hello-OHOS.txt proc system vendor 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 b891546e73f8657e8998c7a1f3927cf48677167a..ad372fb8a79812770cb68beb074f2541b92c70d3 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 @@ -13,16 +13,16 @@ du [_-kKmh_] [_file..._] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看du命令支持的参数列表。 | N/A | -| -k | 显示占用的块,每块1024bytes(默认)。 | N/A | -| -K | 显示占用的块,每块512bytes(posix标准)。 | N/A | -| -m | 兆字节为单位。 | N/A | -| -h | 以K,M,G为单位,提高信息的可读性(例如,1K 243M 2G)。 | N/A | -| file | 指定的需要统计的文件。 | N/A | +| 参数 | 参数说明 | +| ------ | ------------------------------------------------------------ | +| --help | 查看du命令支持的参数列表。 | +| -k | 显示占用的块,每块1024bytes(默认)。 | +| -K | 显示占用的块,每块512bytes(posix标准)。 | +| -m | 兆字节为单位。 | +| -h | 以K,M,G为单位,提高信息的可读性(例如,1K 243M 2G)。 | +| file | 指定的需要统计的文件。 | ## 使用指南 @@ -31,6 +31,9 @@ du [_-kKmh_] [_file..._] - file的内容既为文件名,不能包含其所在的目录。 +## 特殊说明 + +shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -39,10 +42,9 @@ du [_-kKmh_] [_file..._] ## 输出说明 -**示例:**显示结果如下 +**示例** 显示结果如下 - ``` OHOS:/$ du -h testfile 1.8K testfile -``` +``` \ No newline at end of file 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 36b0a095b14c99dc859845b3beb754782bb4a7e8..4e22551ab277c1d3e2f26529ecf6efa0e517774e 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 @@ -13,7 +13,7 @@ format <_dev_inodename_> <_sectors_> <_option_> [_label_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | | -------- | -------- | @@ -39,9 +39,8 @@ format <_dev_inodename_> <_sectors_> <_option_> [_label_] ## 输出说明 -**示例**:格式化mmc卡 +**示例** 格式化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 e3dbbbf23be397f5f4cd7e3685516feca1805a19..00740d520e4752f86b4edee6b8cbfc3c25147b78 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 @@ -11,63 +11,71 @@ ls命令用来显示当前目录的内容。 ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> 系统启动过程中已经通过 alias 为 ls=toybox ls --color=auto 、ll = ls -alF 、 la=ls -A 和 l=ls -CF 赋能,使这几个命令的初始行为就和linux相同(详细效果见输出说明)。所以若要查看help列表,请输入'toybox ls --help'。 +> 系统启动过程中已经通过 alias 为 ls=toybox ls --color=auto 、ll = ls -alF 、 la=ls -A 和 l=ls -CF 赋能,使这几个命令的初始行为就和linux相同(详细效果见输出说明)。所以若要查看help列表,请输入'toybox ls --help'。 ## 参数说明 - **表1** 展示功能参数说明 - -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看ls命令支持的参数列表,使用方式。 | N/A | -| -a | 显示所有文件包括.hidden隐藏类型的文件。 | N/A | -| -b | 转义非图形字符。 | N/A | -| -c | 使用ctime作为文件的时间戳,必须和-l参数一块使用。 | N/A | -| -d | 只显示path名称不显示path所包含的内容。 | N/A | -| -i | 显示文件的节点号。 | N/A | -| -p | 在path名称后放一个"/"。 | N/A | -| -q | 显示不可打印字符比如'?'。 | N/A | -| -s | 统计目录和其成员所占用的内存大小,单位为1024字节。 | N/A | -| -u | 以文件的最后访问时间为时间戳,配合 -l 一起使用。 | N/A | -| -A | 列出所有文件除了.和.. | N/A | -| -H | 跟随命令行符号链接。 | N/A | -| -L | 跟随符号链接。 | N/A | -| -Z | 安全上下文。 | N/A | -| path | path为空时,显示当前目录的内容。
path为无效文件名时,显示失败,提示:
ls error: No such directory。
path为有效目录路径时,会显示对应目录下的内容。 | 1.为空。
2.有效的目录路径 | - - **表2** 输出格式参数说明 - -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -1 | 每行列出一个文件。 | N/A | -| -c | 列,垂直排序。 | N/A | -| -g | 类似于 -l 但没有所有者。 | N/A | -| -h | 统计path目录下文件的总大小,单位为KiB。 | N/A | -| -l | 详细的显示path目录下文件的信息。 | N/A | -| -m | 文件之间添加逗号。 | N/A | -| -n | 类似 -l 数字格式显示uid/gid。 | N/A | -| -o | 类似 -l 但显示列表不包括组。 | N/A | -| -x | 列,水平排序。 | N/A | -| -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** 排序参数说明(默认为按首字母排序) - -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -f | 不排序。 | N/A | -| -r | 按首字母反向排序。 | N/A | -| -t | 按文件的最后修改时间排序,最近时间为排头。 | N/A | -| -S | 按文件大小来排序,大文件为排头。 | N/A | - +**表1** 展示功能参数说明 + +| 参数 | 参数说明 | 取值范围 | +| ------ | ------------------------------------------------------------ | ----------------------------- | +| --help | 查看ls命令支持的参数列表,使用方式。 | N/A | +| -a | 显示所有文件包括.hidden隐藏类型的文件。 | N/A | +| -b | 转义非图形字符。 | N/A | +| -c | 使用ctime作为文件的时间戳,必须和-l参数一块使用。 | N/A | +| -d | 只显示path名称不显示path所包含的内容。 | N/A | +| -i | 显示文件的节点号。 | N/A | +| -p | 在path名称后放一个"/"。 | N/A | +| -q | 显示不可打印字符比如'?'。 | N/A | +| -s | 统计目录和其成员所占用的内存大小,单位为1024字节。 | N/A | +| -u | 以文件的最后访问时间为时间戳,配合 -l 一起使用。 | N/A | +| -A | 列出所有文件除了.和.. | N/A | +| -H | 跟随命令行符号链接。 | N/A | +| -L | 跟随符号链接。 | N/A | +| -Z | 安全上下文。 | N/A | +| path | path为空时,显示当前目录的内容。
path为无效文件名时,显示失败,提示:
ls error: No such directory。
path为有效目录路径时,会显示对应目录下的内容。 | 1.为空。
2.有效的目录路径 | + +**表2** 输出格式参数说明 + +| 参数 | 参数说明 | +| ------- | --------------------------------------- | +| -1 | 每行列出一个文件。 | +| -c | 列,垂直排序。 | +| -g | 类似于 -l 但没有所有者。 | +| -h | 统计path目录下文件的总大小,单位为KiB。 | +| -l | 详细的显示path目录下文件的信息。 | +| -m | 文件之间添加逗号。 | +| -n | 类似 -l 数字格式显示uid/gid。 | +| -o | 类似 -l 但显示列表不包括组。 | +| -x | 列,水平排序。 | +| -ll | 文件的时间属性显示纳秒。 | + +**表3** 排序参数说明(默认为按首字母排序) + +| 参数 | 参数说明 | +| ---- | ------------------------------------------ | +| -f | 不排序。 | +| -r | 按首字母反向排序。 | +| -t | 按文件的最后修改时间排序,最近时间为排头。 | +| -S | 按文件大小来排序,大文件为排头。 | + +**表4** 彩色打印 + +| 参数 | 默认配置 | +| ---- | ------------------------------------------ | +| --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. | ## 使用指南 无 -> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** + +> **须知:** > fatfs的文件节点信息继承其父节点,父节点号为0。故在hi3516dv300开发板上ls -i显示的文件节点号全为0。 +## 特殊说明 + +ls中参数shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -80,18 +88,16 @@ ls [_-ACHLSZacdfhiklmnopqrstux1_] [_--color_[_=auto_]] [_directory..._] ## 输出说明 -**示例1:**ls命令查看当前路径下的内容 +**示例1** ls命令查看当前路径下的内容 - ``` OHOS:/$ ls bin etc nfs sdcard system usr dev lib proc storage userdata vendor ``` -**示例2:**ll命令查看当前路径下的内容 +**示例2** ll命令查看当前路径下的内容 - ``` OHOS:/$ ll total 20 @@ -107,4 +113,4 @@ drwxrwxrwx 1 0 0 2048 2021-11-21 17:52 system/ drwxrwxrwx 1 0 0 2048 2021-11-21 17:52 userdata/ drwxrwxrwx 1 0 0 2048 2021-11-21 17:52 usr/ drwxrwxrwx 1 0 0 2048 2021-11-21 17:52 vendor/ -``` +``` \ No newline at end of file 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 c3d5fb687598b1fa670e95cd6e7fa690a3b16e37..7332604c0d912d7f60b9dfc578f423a326261e11 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 @@ -23,9 +23,8 @@ lsfd命令显示当前已经打开文件的fd号以及文件的名字。 ## 输出说明 -**示例:**lsfd输出说明 +**示例** 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 0686dd2e46f17493d3f465919b1b79663f127c54..42a62a58ed01ce2a2752a9502c1f1a9f96116447 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 @@ -13,24 +13,27 @@ mkdir [_-vp_] [_-m mode_] [_dirname..._] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看mkdir命令支持的参数列表 | N/A | -| -m | 设置即将创建目录的权限。 | N/A | -| -p | 递归逐级创建父子目录。 | N/A | -| -v | 打印创建目录过程中的详细信息。 | N/A | -| directory | 需要创建的目录。 | N/A | +| 参数 | 参数说明 | +| --------- | ------------------------------ | +| --help | 查看mkdir命令支持的参数列表 | +| -m | 设置即将创建目录的权限。 | +| -p | 递归逐级创建父子目录。 | +| -v | 打印创建目录过程中的详细信息。 | +| directory | 需要创建的目录。 | ## 使用指南 -> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** +> **须知:** > fatfs文件系统所有创建的文件和其挂载节点的权限属性保持一致,目前节点的权限只有用户读写权限,group和others权限不生效, -> +> > 且只有读写位可设置,有rw和ro两种,因此mkdir在附加-m参数时,创建的目录权限仅有777和555两种,可执行权限也不生效。 +## 特殊说明 + +shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -45,7 +48,7 @@ mkdir [_-vp_] [_-m mode_] [_dirname..._] ## 输出说明 - + ``` OHOS:/tmp$ mkdir testpath OHOS:/tmp$ ll @@ -53,9 +56,9 @@ total 2 drwxrwxrwx 1 0 0 2048 1979-12-31 00:00 testpath/ ``` -示例 2 创建指定mode的目录 +**示例2** 创建指定mode的目录 + - ``` OHOS:/tmp$ mkdir -m 777 testpath OHOS:/tmp$ ll @@ -63,9 +66,9 @@ total 2 drwxrwxrwx 1 0 0 2048 1979-12-31 00:00 testpath/ ``` -示例 3 逐级创建目录 +**示例3** 逐级创建目录 + - ``` OHOS:/tmp$ mkdir -pv testpath01/testpath02/testpath03 mkdir: created directory 'testpath01' @@ -80,4 +83,4 @@ drwxrwxrwx 1 0 0 2048 1979-12-31 00:00 testpath02/ OHOS:/tmp$ ll testpath01/testpath02/ total 2 drwxrwxrwx 1 0 0 2048 1979-12-31 00:00 testpath03/ -``` +``` \ No newline at end of file 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 d2ddc4f1aad519df0ef512c263727c8b1bfd9b29..2c148f024169377a923e15c98ee85dc6762a9da7 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 @@ -13,22 +13,25 @@ mount [_-f_] [_-t TYPE_] [_-o OPTION,_] [[_DEVICE_] _DIR_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看mount命令支持的参数列表。 | N/A | -| -f | 佯装挂载动作(实际不做挂载)。 | N/A | -| -t | 文件系统的种类。 | TYPE:vfat, yaffs, jffs, ramfs, nfs,procfs, romfs. | -| -o | 挂载选项。 | N/A | -| DEVICE | 要挂载的设备(格式为设备所在路径)。 | 系统拥有的设备。 | -| DIR | 指定目录。
用户必须具有指定目录中的执行(搜索)许可权。 | N/A | +| 参数 | 参数说明 | 取值范围 | +| ------ | ----------------------------------------------------------- | ------------------------------------------------------------ | +| --help | 查看mount命令支持的参数列表。 | N/A | +| -f | 佯装挂载动作(实际不做挂载)。 | N/A | +| -t | 文件系统的种类。 | TYPE:vfat, yaffs, jffs, ramfs, nfs,procfs, romfs. | +| -o | 挂载选项。 | N/A | +| DEVICE | 要挂载的设备(格式为设备所在路径)。 | 系统拥有的设备。 | +| DIR | 指定目录。
用户必须具有指定目录中的执行(搜索)许可权。 | N/A | ## 使用指南 mount后加需要挂载的设备信息、指定目录以及设备文件格式,就能成功挂载文件系统到指定目录。 +## 特殊说明 + +shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -37,9 +40,9 @@ mount后加需要挂载的设备信息、指定目录以及设备文件格式, ## 输出说明 -**示例:**将服务器端nfs目录192.168.1.3:/nfs挂载到当前系统下新建的/nfs目录: +**示例** 将服务器端nfs目录192.168.1.3:/nfs挂载到当前系统下新建的/nfs目录: + - ``` OHOS:/$ mkdir nfs OHOS:/$ mount -t nfs 192.168.1.3:/nfs nfs @@ -49,4 +52,4 @@ OHOS:/$ ls nfs/ 16d.xml gpio_test ohos_test.txt userfs_vfat.img OHOS_Image.bin hello rootfs_vfat.img dev_tools mksh_rootfs_vfat.img test_demo -``` +``` \ No newline at end of file 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 f3d42a9f3526ca00aef505034e10d8e6d86881c3..49126c582f469d5c53cd2839fc9d3aff89b2307e 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 @@ -13,22 +13,22 @@ mv [_-fivn_] _SOURCE... DEST_ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -help | 使用帮助。 | N/A | -| -f | 通过删除目标文件强制复制。 | N/A | -| -i | 若指定移动的源目录或文件与目标中目录或文件同名,则会先询问是否覆盖旧文件,输入 y 直接覆盖,输入 n 取消该操作。 | N/A | -| -n | 不要覆盖任何已存在的文件或目录。 | N/A | -| -v | 目前本参数toybox官方最新代码虽然支持,但同样也不生效。 | N/A | -| SOURCE | 源文件路径。 | 目前只支持文件,不支持目录;支持多文件同时移动。 | -| DEST | 目的文件路径。 | 支持目录以及文件。 | +| 参数 | 参数说明 | 取值范围 | +| ------ | ------------------------------------------------------------ | ----------------------------------------------- | +| -help | 使用帮助。 | N/A | +| -f | 通过删除目标文件强制复制。 | N/A | +| -i | 若指定移动的源目录或文件与目标中目录或文件同名,则会先询问是否覆盖旧文件,输入 y 直接覆盖,输入 n 取消该操作。 | N/A | +| -n | 不要覆盖任何已存在的文件或目录。 | N/A | +| -v | 目前本参数toybox官方最新代码虽然支持,但同样也不生效。 | N/A | +| SOURCE | 源文件路径。 | 目前只支持文件,不支持目录;支持多文件同时移动。 | +| DEST | 目的文件路径。 | 支持目录以及文件。 | ## 使用指南 -- 源文件路径支持“\*”和“?”通配符,“\*”代表任意多个字符,“?”代表任意单个字符。目的路径不支持通配符。当源路径可匹配多个文件时,目的路径必须为目录。 +- 源文件路径支持“\*”和“?”通配符,“\*”代表任意多个字符,“?”代表任意单个字符。目的路径不支持通配符。当源路径可匹配多个文件时,目的路径必须为目录。 - 目的路径为目录时,该目录必须存在。此时目的文件以源文件命名。 @@ -36,6 +36,9 @@ mv [_-fivn_] _SOURCE... DEST_ - 目的文件已存在则会覆盖。 +## 特殊说明 + +shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -48,9 +51,9 @@ mv [_-fivn_] _SOURCE... DEST_ ## 输出说明 -**示例 1** 显示结果如下 +**示例1** 显示结果如下 + - ``` OHOS:/$ touch test.txt OHOS:/$ mkdir testpath @@ -71,9 +74,9 @@ bin etc proc storage test.txt userdata vendor dev lib sdcard system testpath usr ``` -**示例 2** 通配符使用 +**示例2** 通配符使用 + - ``` OHOS:/$ ls bin etc proc storage test.txt testA.txt testpath usr @@ -84,4 +87,4 @@ bin etc proc storage test.txt userdata vendor dev lib sdcard system testpath usr OHOS:/$ ls testpath/ test.txt test3.txt testA.txt test_.txt -``` +``` \ No newline at end of file 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 30013e2e9bb817d1e224f7320131dbc749f82d9a..b26e4142c11e827a6ba6c36e9baf6116225f2c34 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 @@ -32,9 +32,9 @@ partinfo <_dev_inodename_> ## 输出说明 -**示例**:查看系统分区信息 +**示例** 查看系统分区信息 + - ``` OHOS # partinfo /dev/mmcblk0p0 part info : 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 7e57659bf2be360b01ccefd018e18be50083b860..8223fc6918c131da6c3cd05af8819879d76cc747 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 @@ -13,7 +13,7 @@ pwd ## 参数说明 -无。 +无 ## 使用指南 @@ -28,9 +28,9 @@ 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 19d5bac19ba2aa389c410c0bf71181d1bc54c0ef..ce6c6dd7b55a047db5f566e80ae13ec47fbb4be7 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 @@ -13,14 +13,14 @@ rm [_-fv_] _FILE or rm_ [_-rv_] [_PATH_ | _filename_]... ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -r | 删除空目录或非空目录。 | N/A | -| -f | 强制删除:不需要确认,删除不存的文件在也不报错。 | N/A | -| -v | 显示删除的过程。 | N/A | -| PATH/filename | 要删除文件或文件夹的名称,支持输入路径。 | N/A | +| 参数 | 参数说明 | +| ------------- | ------------------------------------------------ | +| -r | 删除空目录或非空目录。 | +| -f | 强制删除:不需要确认,删除不存的文件在也不报错。 | +| -v | 显示删除的过程。 | +| PATH/filename | 要删除文件或文件夹的名称,支持输入路径。 | ## 使用指南 @@ -31,6 +31,9 @@ rm [_-fv_] _FILE or rm_ [_-rv_] [_PATH_ | _filename_]... - 删除不存在的文件会报错。 +## 特殊说明 + +-f -v 参数shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -43,9 +46,9 @@ rm [_-fv_] _FILE or rm_ [_-rv_] [_PATH_ | _filename_]... ## 输出说明 -**示例 1** 用 rm 命令删除文件 testfile +**示例1** 用 rm 命令删除文件 testfile + - ``` OHOS:/$ ls bin etc proc storage testfile usr @@ -56,9 +59,9 @@ bin etc proc storage userdata vendor dev lib sdcard system usr ``` -**示例 2** 用 rm -r 删除非空目录 testpath +**示例2** 用 rm -r 删除非空目录 testpath + - ``` OHOS:/$ ls bin etc proc storage testpath usr @@ -67,4 +70,4 @@ OHOS:/$ rm -r testpath/ OHOS:/$ ls bin etc proc storage userdata vendor dev lib sdcard system usr -``` +``` \ No newline at end of file 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 0318f2a9221697832a928751be4725299ffd7c88..14a13f684b12cd0bcf649d16d451664df5f1ffee 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 @@ -13,7 +13,7 @@ rmdir [_-p_] [_dirname..._] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -39,9 +39,9 @@ rmdir [_-p_] [_dirname..._] ## 输出说明 -**示例:**删除一个名为 dir 的目录 +**示例** 删除一个名为 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 cd875e681672ec126a356327c38dab4cf5f47c4b..191ec684d433578c10017b4e19985b942611cbaf 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 @@ -13,7 +13,7 @@ statfs [_directory_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -31,8 +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 942e3e5b88ede73f6a869a191c5f6ac8866da7f3..5d678a5a617387957101027f1ea55fcf10ad6340 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 @@ -13,7 +13,7 @@ sync ## 参数说明 -无。 +无 ## 使用指南 @@ -30,4 +30,4 @@ 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 5f818737286794ea690a381f2ea7e4d8c62e93cf..97eab28cc5442242192d1623a99800303eccf32f 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 @@ -17,10 +17,10 @@ touch [_filename_] **表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看touch命令支持的参数列表 | N/A | -| filename | 需要创建文件的名称。 | N/A | +| 参数 | 参数说明 | 取值范围 | +| -------- | --------------------------- | -------- | +| --help | 查看touch命令支持的参数列表 | N/A | +| filename | 需要创建文件的名称。 | N/A | ## 使用指南 @@ -28,9 +28,13 @@ touch [_filename_] - touch命令用来创建一个空文件,该文件可读写。 - 使用touch命令允许一次创建多个文件。 + > ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** > 在系统重要资源路径下使用touch命令创建文件,会对系统造成死机等未知影响,如在/dev路径下执行touch uartdev-0,会产生系统卡死现象。 +## 特殊说明 + +--help参数以及同时创建多个文件,shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -45,7 +49,7 @@ touch [_filename_] **示例 1** 创建一个名为 file.c 的文件 - + ``` OHOS:/tmp$ ls OHOS:/tmp$ touch file.c @@ -58,7 +62,7 @@ total 0 **示例 2** 同时创建三个文件 - + ``` *OHOS:/tmp$ OHOS:/tmp$ touch testfile1 testfile2 testfile3 @@ -68,4 +72,4 @@ total 0 -rwxrwxrwx 1 0 0 0 1979-12-31 00:00 testfile2* -rwxrwxrwx 1 0 0 0 1979-12-31 00:00 testfile3* OHOS:/tmp$ -``` +``` \ No newline at end of file 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 de3e13e5605974b836fbe1ac172bcc69031bbb34..ea24abc705e980aed349ed4024cadd2e609edde7 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 @@ -13,20 +13,23 @@ umount [_-a [-t TYPE]_] [_dir_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| --help | 查看umount命令支持的参数列表。 | N/A | -| -a | 卸载所有已挂载的目录。 | N/A | -| -t | 同-a选项一起使用,限制-a的卸载范围,只卸载-t所指定的文件系统类型的挂载目录。 | N/A | -| dir | 需要卸载的文件系统对应的目录。 | 系统已挂载的文件系统的目录 | +| 参数 | 参数说明 | 取值范围 | +| ------ | ------------------------------------------------------------ | -------------------------- | +| --help | 查看umount命令支持的参数列表。 | N/A | +| -a | 卸载所有已挂载的目录。 | N/A | +| -t | 同-a选项一起使用,限制-a的卸载范围,只卸载-t所指定的文件系统类型的挂载目录。 | N/A | +| dir | 需要卸载的文件系统对应的目录。 | 系统已挂载的文件系统的目录 | ## 使用指南 umount后加上需要卸载的指定文件系统的目录,即将指定文件系统卸载。 +## 特殊说明 + +参数shell端暂不支持。切换mksh版本可全支持,方法:cd bin; ./mksh。 ## 使用实例 @@ -41,18 +44,18 @@ umount后加上需要卸载的指定文件系统的目录,即将指定文件 将已在./nfs挂载的文件系统卸载掉 -**示例 1** umount输出示例 +**示例1** umount输出示例 + - ``` OHOS:/$ umount ./nfs/ umount ok ``` -**示例 2** 卸载所有已挂载的nfs类型的目录 +**示例2** 卸载所有已挂载的nfs类型的目录 + - ``` OHOS:/$ umount -a -t nfs umount ok -``` +``` \ No newline at end of file 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 6987c4571e6332e1c495d0cd07408e810f146df0..eae31d2a90879fc9afdc6dd8b21ea5f9b3d2b550 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 @@ -13,12 +13,12 @@ writeproc <_data_> >> /proc/<_filename_> ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| data | 要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。 | N/A | -| filename | data要传入的proc文件。 | N/A | +| 参数 | 参数说明 | +| -------- | ---------------------------------------------------------- | +| data | 要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。 | +| filename | data要传入的proc文件。 | ## 使用指南 @@ -28,6 +28,9 @@ proc文件实现自身的write函数,调用writeproc命令后会将入参传 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > procfs不支持多线程访问。 +## 特殊说明 + +shell端暂不支持。 ## 使用实例 @@ -36,11 +39,13 @@ proc文件实现自身的write函数,调用writeproc命令后会将入参传 ## 输出说明 +``` OHOS \# writeproc test >> /proc/uptime [INFO]write buf is: test test >> /proc/uptime +``` > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。 +> uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。 \ No newline at end of file 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 0b4d2d481d4d800a0516910f2553f368495c7728..730e37083d4632c347c70f542d2a069496094ee0 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 @@ -8,17 +8,18 @@ 在中断有响应的情况下,可以通过魔法键查看task信息中 cpup(CPU占用率)看是哪个任务长时间占用CPU导致系统其他任务无响应(一般为比较高优先级任务一直抢占CPU,导致低优先级任务无响应)。 -## 使用方法 +## 使用配置 + +魔法键依赖于宏LOSCFG_ENABLE_MAGICKEY,在kernel/liteos_a中输入make menuconfig命令。此时会弹出配置项,找到Debug选项并进入,在配置项中开启“Enable MAGIC KEY”: -1. 配置宏LOSCFG_ENABLE_MAGICKEY。 +Debug ---> Enable MAGIC KEY;若关闭该选项,则魔法键失效(默认为选中的)。 - 魔法键依赖于宏LOSCFG_ENABLE_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”: +> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** +> 可以在menuconfig中,将光标移动到LOSCFG_ENABLE_MAGICKEY上,输入“?”,可以查看帮助信息。 - Debug ---> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > 可以在menuconfig中,将光标移动到LOSCFG_ENABLE_MAGICKEY上,输入“?”,查看帮助信息。 +## 使用方法 -2. 输入“ctrl + r”键,打开魔法键检测功能。 +1. 输入“ctrl + r”键,打开魔法键检测功能。 在连接UART或者USB转虚拟串口的情况下,输入“ctrl + r” 键,打开魔法键检测功能,输出 “Magic key on”;再输入一次后,则关闭魔法键检测功能,输出“Magic key off”。魔法键功能如下: @@ -30,5 +31,5 @@ - ctrl + e:系统进行简单完整性内存池检查,检查出错会输出相关错误信息,检查正常会输出“system memcheck over, all passed!”。 - > ![icon-notice.gif](public_sys-resources/icon-notice.gif) **须知:** - > 魔法键检测功能打开情况下,如果需要通过UART或者USB转虚拟串口输入特殊字符需避免与魔法键值重复,否则魔法键会被误触发,而原有设计功能可能出现错误。 + > **须知:** + > 魔法键检测功能打开情况下,如果需要通过UART或者USB转虚拟串口输入特殊字符需避免与魔法键值重复,否则魔法键会被误触发,而原有设计功能可能出现错误。 \ No newline at end of file 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 d8609af2b50f366eb20f65406a02c5660df3fdd0..a4fe65c15c8c30bb415f3591920f65e5845f2d08 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 @@ -17,7 +17,7 @@ arp [_-i IF_] -d _IPADDR_ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -40,15 +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 869fc72a0b4a3ba3c14d3488f477529e906f830e..a58aed0ea7c3d8f3022664ce3b2102ab26e47811 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 @@ -15,13 +15,13 @@ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -h \| --help | 查看dhclient命令支持的参数列表,及使用方式。 | N/A | -| <netif name> | 启动对应网卡的dhcp请求。 | 网卡名字,eth0。 | -| -x <netif name> | 关闭对应网卡的dhcp功能。 | 网卡名字,eth0。 | +| 参数 | 参数说明 | 取值范围 | +| ------------------------------- | -------------------------------------------- | ---------------- | +| -h \| --help | 查看dhclient命令支持的参数列表,及使用方式。 | N/A | +| <netif name> | 启动对应网卡的dhcp请求。 | 网卡名字,eth0。 | +| -x <netif name> | 关闭对应网卡的dhcp功能。 | 网卡名字,eth0。 | ## 使用指南 @@ -32,12 +32,15 @@ - dhclient -x eth0 +## 特殊说明 + +shell端暂不支持。 ## 使用实例 -**示例1:**启动网卡eth0的dhcp请求 +**示例1** 启动网卡eth0的dhcp请求 + - ``` OHOS:/$ dhclient eth0 OHOS:/$ ifconfig @@ -50,10 +53,9 @@ OHOS:/$ ``` -**示例2:**关闭网卡eth0的dhcp请求 +**示例2** 关闭网卡eth0的dhcp请求 - ``` OHOS:/$ dhclient -x eth0 NetifStatusCallback(eth0): nsc event: 0xf0 @@ -63,4 +65,4 @@ lo ip:127.0.0.1 netmask:255.0.0.0 gateway:127.0.0.1 HWaddr 00 MTU:0 Running Link UP eth0 ip:0.0.0.0 netmask:0.0.0.0 gateway:0.0.0.0 HWaddr 42:da:81:bc:58:94 MTU:1500 Running Default Link UP -``` +``` \ No newline at end of file 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 62b3650b5163641da96cc4e79cdc006fd0eedf4c..ef891e579f558726b7e239d653bab2a63d8341f1 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 @@ -27,7 +27,7 @@ option: ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -65,8 +65,8 @@ option: ## 输出说明 -- **示例1:**设置网络参数 - +- **示例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 @@ -79,7 +79,7 @@ option: 输出的各参数说明如下表所示: - **表2** 参数说明 + **表2** 参数说明 | 参数 | 说明 | | -------- | -------- | @@ -92,8 +92,8 @@ option: | Default | 有这项说明此网卡连接到默认网关。 | | Link UP/Down | 网卡连接状态。 | -- **示例2:**获取协议栈统计信息 - +- **示例2** 获取协议栈统计信息 + ``` OHOS # ifconfig -a RX packets:6922 errors:0 ip dropped:4312 link dropped:67 overrun:0 bytes:0 (0.0 B) @@ -104,7 +104,7 @@ option: 输出的各参数说明如下表所示: - **表3** ifconfig -a 参数说明 +**表3** ifconfig -a 参数说明 | 参数 | 说明 | | -------- | -------- | @@ -119,8 +119,8 @@ option: | TX overrun | 暂未使用。 | | TX bytes | IP层已正常发送或者转发的数据包的总长度。 | -- **示例3**:设置IPv6的地址信息 - +- **示例3** 设置IPv6的地址信息 + ``` OHOS:/$ ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d NetifStatusCallback(eth0): nsc event: 0x8 @@ -139,8 +139,8 @@ option: HWaddr 66:2f:e5:bd:24:e6 MTU:1500 Running Default Link UP ``` -- **示例4**:删除IPv6的地址信息 - +- **示例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 20346dea9982f997bb3a421a2079f59204643c8d..e7a612aa23413eceee87b9078a1da132f8f4fae3 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 @@ -18,8 +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 bf466ca6c04f6836245e2fe42432152d4087c2ac..c82043f233624db773288eacfa2d5e0df7711ee0 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 @@ -20,6 +20,9 @@ netstat netstat +## 特殊说明 + +shell端暂不支持。 ## 使用实例 @@ -28,8 +31,8 @@ netstat ## 输出说明 - **示例:**netstat 打印信息 - +**示例** netstat 打印信息 + ``` OHOS # netstat ========== total sockets 128 ====== unused sockets 119 ========== @@ -46,16 +49,16 @@ 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** 输出说明 -| 输出 | 说明 | -| -------- | -------- | -| Proto | 协议类型。 | -| Recv-Q | 未被用户读取的数据量。
对于Listen TCP,此值为已完成三次握手,但是未被用户accept的TCP连接的数量。 | -| Send-Q | 对TCP连接,已发送但未确认的数据量。
对UDP连接,由于IP地址解析未完成而缓存的数据量。 | -| Local Address | 本地地址和端口。 | -| Foreign Address | 远程地址和端口。 | -| State | TCP连接状态,UDP此项无意义。 | +| 输出 | 说明 | +| -------------------- | ------------------------------------------------------------ | +| Proto | 协议类型。 | +| Recv-Q | 未被用户读取的数据量。
对于Listen TCP,此值为已完成三次握手,但是未被用户accept的TCP连接的数量。 | +| Send-Q | 对TCP连接,已发送但未确认的数据量。
对UDP连接,由于IP地址解析未完成而缓存的数据量。 | +| Local Address | 本地地址和端口。 | +| Foreign Address | 远程地址和端口。 | +| State | TCP连接状态,UDP此项无意义。 | > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> 形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 +> 形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 \ No newline at end of file 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 635a4e46aa7a219141f89cc9d7c079715c917ca7..1dc59ea543cdb4561149126d41a2c40d3ce1761c 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 @@ -13,7 +13,7 @@ ntpdate [_SERVER_IP1_] [_SERVER_IP2_]... ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | 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 111cadec60a336585ffdd2a4f700035f7948f6e6..6cb4a25a81fdc35693c14476484deedb72c9e4b3 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 @@ -13,7 +13,7 @@ ping _[-4] [-c cnt] [-f] [-i interval] [-q] [-s size] <IP>_ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -45,8 +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 16a6843b1e363085372cdb7d072e85c18d98003c..65b18a4439fc73337a2b6863ad4eba76342a7d15 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 @@ -13,14 +13,14 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 -| 参数 | 参数说明 | 取值范围 | -| -------- | -------- | -------- | -| -c count | 执行的次数,不带本参数则默认为4次。 | 1~65535 | -| -I interface | 指定网卡执行IPv6 ping操作。 | N/A | -| -I sourceAddress | 指定源IPv6地址执行ping操作。 | N/A | -| destination | 目标主机地址。 | N/A | +| 参数 | 参数说明 | 取值范围 | +| --------------------- | ----------------------------------- | -------- | +| -c count | 执行的次数,不带本参数则默认为4次。 | [1, 65535] | +| -I interface | 指定网卡执行IPv6 ping操作。 | N/A | +| -I sourceAddress | 指定源IPv6地址执行ping操作。 | N/A | +| destination | 目标主机地址。 | N/A | ## 使用指南 @@ -31,6 +31,9 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ - 命令需要启动TCP/IP协议栈后才能使用。 +## 特殊说明 + +shell端暂不支持。 ## 使用实例 @@ -45,8 +48,8 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ ## 输出说明 -1. 输入ping6 2001:a:b:c:d:e:f:b - +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 @@ -58,8 +61,8 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ rtt min/avg/max = 0/0.00/0 ms ``` -2. 输入 ping6 -c 3 2001:a:b:c:d:e:f:b 指定3次进行网络测试 - +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 @@ -70,8 +73,8 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ rtt min/avg/max = 0/0.00/0 ms ``` -3. 输入 ping6 -I eth0 2001:a:b:c:d:e:f:b 使用指定网卡接口eth0测试IPv6。 - +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 @@ -82,8 +85,8 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ 4 packets transmitted, 4 received, 0.00% packet loss, time 30msrtt min/avg/max = 0/2.50/10 ms ``` -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进行测试。 - +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 @@ -92,4 +95,4 @@ ping6 _[-c count] [-I interface / sourceAddress] destination_ 56 bytes from 2001:A:B:C:D:E:F:B : icmp_seq=4 time<1 ms --- 2001:a:b:c:d:e:f:b/64 ping statistics --- 4 packets transmitted, 4 received, 0.00% packet loss, time 20msrtt min/avg/max = 0/0.00/0 ms - ``` + ``` \ No newline at end of file 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 7a72745d7044b98cf4b63d63b89ac78dafcce29c..c55b1d69befb6cdbec749a4c2ac30d4ae0513ef1 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 @@ -13,7 +13,7 @@ telnet [_on | off_] ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | @@ -37,9 +37,9 @@ telnet [_on | off_] ## 输出说明 -**示例:**输入 telnet on +**示例** 输入 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 5772a7a8053d05d21885ed5aff065a463e0d9bfb..8777468a5fdd0873b06cf292d6be04c1c4e7c2a7 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 @@ -15,7 +15,7 @@ tftp命令可以从TFTP服务器上下载文件。 ## 参数说明 - **表1** 参数说明 +**表1** 参数说明 | 参数 | 参数说明 | 取值范围 | | -------- | -------- | -------- | 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 74e963ab7e637de910d6141a8ad45d0f8a40f8d0..26328bad562d2938c03731a4dd9c0f51d013913c 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-trace.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-trace.md @@ -45,7 +45,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - IDENTITY类型UINTPTR,表示事件操作的主体对象。 - Params类型UINTPTR,表示事件的参数。 示例: - + ``` 假设需要新增对文件(fd1、fd2)读写操作的简易插桩, 自定义读操作为type:1, 写操作为type:2,则 @@ -63,7 +63,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - TYPE用于设置具体的事件类型,可以在头文件los_trace.h中的enum LOS_TRACE_TYPE中自定义事件类型。定义方法和规则可以参考其他事件类型。 - IDENTITY和Params的类型及含义同简易插桩。 示例: - + ``` 1.在enum LOS_TRACE_MASK中定义事件掩码,即模块级别的事件类型。 定义规范为TRACE_#MOD#_FLAG,#MOD#表示模块名。 @@ -86,9 +86,9 @@ 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。 + > 预置的Trace事件及参数均可以通过上述方式进行裁剪,参数详见 [kernel\include\los_trace.h](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_trace.h)。 - Trace Mask事件过滤接口LOS_TraceEventMaskSet(UINT32 mask),其入参mask仅高28位生效(对应LOS_TRACE_MASK中某模块的使能位),仅用于模块的过滤,暂不支持针对某个特定事件的细粒度过滤。例如:LOS_TraceEventMaskSet(0x202),则实际设置生效的mask为0x200(TRACE_QUE_FLAG),QUE模块的所有事件均会被采集。一般建议使用的方法为: LOS_TraceEventMaskSet(TRACE_EVENT_FLAG | TRACE_MUX_FLAG | TRACE_SEM_FLAG | TRACE_QUE_FLAG); @@ -100,8 +100,8 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - 针对中断事件的Trace, 提供中断号过滤,用于解决某些场景下特定中断号频繁触发导致其他事件被覆盖的情况,用户可自定义中断过滤的规则, 示例如下: - - ``` + + ```c BOOL Example_HwiNumFilter(UINT32 hwiNum) { if ((hwiNum == TIMER_INT) || (hwiNum == DMA_INT)) { @@ -117,7 +117,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 ### 用户态 -新增trace字符设备,位于"/dev/trace",通过对设备节点的read、write、ioctl,实现用户态trace的读写和控制: +新增trace字符设备,位于"/dev/trace",通过对设备节点的read、write、ioctl,实现用户态trace的读写和控制: - read: 用户态读取Trace记录数据 @@ -125,8 +125,8 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 - ioctl: 用户态Trace控制操作,包括 - -``` + +```c #define TRACE_IOC_MAGIC 'T' #define TRACE_START _IO(TRACE_IOC_MAGIC, 1) #define TRACE_STOP _IO(TRACE_IOC_MAGIC, 2) @@ -148,7 +148,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 开启Trace调测的典型流程如下: 1. 配置Trace模块相关宏。 - 配置Trace控制宏LOSCFG_KERNEL_TRACE,默认关,在kernel/liteos_a目录下执行 make update_config命令配置"Kernel->Enable Hook Feature->Enable Trace Feature"中打开: + 配置Trace控制宏LOSCFG_KERNEL_TRACE,默认关,在 kernel/liteos_a 目录下执行 make update_config 命令配置 "Kernel->Enable Hook Feature->Enable Trace Feature" 中打开: | 配置项 | menuconfig选项 | 含义 | 设置值 | | -------- | -------- | -------- | -------- | @@ -156,7 +156,7 @@ 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_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 | @@ -165,7 +165,7 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 3. (可选)调用LOS_TraceStop停止Trace后,清除缓冲区LOS_TraceReset(系统默认已启动trace)。 -4. (可选)调用LOS_TraceEventMaskSet设置需要追踪的事件掩码(系统默认的事件掩码仅使能中断与任务事件),事件掩码参见los_trace.h 中的LOS_TRACE_MASK定义。 +4. (可选)调用LOS_TraceEventMaskSet设置需要追踪的事件掩码(系统默认的事件掩码仅使能中断与任务事件),事件掩码参见 [los_trace.h](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_trace.h) 中的LOS_TRACE_MASK定义。 5. 在需要记录事件的代码起始点调用LOS_TraceStart。 @@ -203,50 +203,52 @@ LiteOS-A内核的Trace模块提供下面几种功能,接口详细信息可以 ### 内核态示例代码 +该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。 实例代码如下: -``` +```c #include "los_trace.h" UINT32 g_traceTestTaskId; VOID Example_Trace(VOID) -{ - UINT32 ret; +{ + UINT32 ret; LOS_TaskDelay(10); /* 开启trace */ - ret = LOS_TraceStart(); - if (ret != LOS_OK) { - dprintf("trace start error\n"); - return; - } - /* 触发任务切换的事件 */ - LOS_TaskDelay(1); - LOS_TaskDelay(1); - LOS_TaskDelay(1); - /* 停止trace */ - LOS_TraceStop(); + ret = LOS_TraceStart(); + if (ret != LOS_OK) { + dprintf("trace start error\n"); + return; + } + /* 触发任务切换的事件 */ + LOS_TaskDelay(1); + LOS_TaskDelay(1); + LOS_TaskDelay(1); + /* 停止trace */ + LOS_TraceStop(); LOS_TraceRecordDump(FALSE); } -UINT32 Example_Trace_test(VOID){ - UINT32 ret; - TSK_INIT_PARAM_S traceTestTask; - /* 创建用于trace测试的任务 */ - memset(&traceTestTask, 0, sizeof(TSK_INIT_PARAM_S)); - traceTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Trace; - traceTestTask.pcName = "TestTraceTsk"; /* 测试任务名称 */ - traceTestTask.uwStackSize = 0x800; - traceTestTask.usTaskPrio = 5; - traceTestTask.uwResved = LOS_TASK_STATUS_DETACHED; - ret = LOS_TaskCreate(&g_traceTestTaskId, &traceTestTask); - if(ret != LOS_OK){ - dprintf("TraceTestTask create failed .\n"); - return LOS_NOK; - } - /* 系统默认情况下已启动trace, 因此可先关闭trace后清除缓存区后,再重启trace */ - LOS_TraceStop(); - LOS_TraceReset(); - /* 开启任务模块事件记录 */ - LOS_TraceEventMaskSet(TRACE_TASK_FLAG); +UINT32 Example_Trace_test(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S traceTestTask; + /* 创建用于trace测试的任务 */ + memset(&traceTestTask, 0, sizeof(TSK_INIT_PARAM_S)); + traceTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Trace; + traceTestTask.pcName = "TestTraceTsk"; /* 测试任务名称 */ + traceTestTask.uwStackSize = 0x800; // 0x800: trace test task stacksize + traceTestTask.usTaskPrio = 5; // 5: trace test task priority + traceTestTask.uwResved = LOS_TASK_STATUS_DETACHED; + ret = LOS_TaskCreate(&g_traceTestTaskId, &traceTestTask); + if (ret != LOS_OK) { + dprintf("TraceTestTask create failed .\n"); + return LOS_NOK; + } + /* 系统默认情况下已启动trace, 因此可先关闭trace后清除缓存区后,再重启trace */ + LOS_TraceStop(); + LOS_TraceReset(); + /* 开启任务模块事件记录 */ + LOS_TraceEventMaskSet(TRACE_TASK_FLAG); return LOS_OK; } LOS_MODULE_INIT(Example_Trace_test, LOS_INIT_LEVEL_KMOD_EXTENDED); @@ -262,7 +264,7 @@ LOS_MODULE_INIT(Example_Trace_test, LOS_INIT_LEVEL_KMOD_EXTENDED); ***TraceInfo begin*** clockFreq = 50000000 CurEvtIndex = 7 -Index Time(cycles) EventType CurTask Identity params +Index Time(cycles) EventType CurTask Identity params 0 0x366d5e88 0x45 0x1 0x0 0x1f 0x4 0x0 1 0x366d74ae 0x45 0x0 0x1 0x0 0x8 0x1f 2 0x36940da6 0x45 0x1 0xc 0x1f 0x4 0x9 @@ -276,13 +278,13 @@ Index Time(cycles) EventType CurTask Identity params 输出的事件信息包括:发生时间、事件类型、事件发生在哪个任务中、事件操作的主体对象、事件的其他参数。 -- EventType:表示的具体事件可查阅头文件los_trace.h中的enum LOS_TRACE_TYPE。 +- EventType:表示的具体事件可查阅头文件 [los_trace.h](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_trace.h) 中的enum LOS_TRACE_TYPE。 - CurrentTask:表示当前运行在哪个任务中,值为taskid。 -- Identity:表示事件操作的主体对象,可查阅头文件los_trace.h中的\#TYPE\#_PARAMS。 +- Identity:表示事件操作的主体对象,可查阅头文件 [los_trace.h](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_trace.h) 中的\#TYPE\#_PARAMS。 -- params:表示的事件参数可查阅头文件los_trace.h中的\#TYPE\#_PARAMS。 +- params:表示的事件参数可查阅头文件 [los_trace.h](https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_trace.h) 中的\#TYPE\#_PARAMS。 下面以序号为0的输出项为例,进行说明。 @@ -298,7 +300,7 @@ Index Time(cycles) EventType CurTask Identity params - Identity和params的含义需要查看TASK_SWITCH_PARAMS宏定义: -``` +```c #define TASK_SWITCH_PARAMS(taskId, oldPriority, oldTaskStatus, newPriority, newTaskStatus) \ taskId, oldPriority, oldTaskStatus, newPriority, newTaskStatus ``` 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 ea0adcfde4a3b1260845be2ad4cf57ee6c2f4799..7f3ef388df3b35582d3bd6f33c59c7756ae93ff2 100644 --- a/zh-cn/device-dev/kernel/kernel-small-debug-user.md +++ b/zh-cn/device-dev/kernel/kernel-small-debug-user.md @@ -5,7 +5,7 @@ Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、踩内存分析以及backtrace功能等维测手段,可以提高用户态内存相关问题的定位效率。 -采用了对malloc/free接口进行插桩,保存关键节点信息,然后程序在申请和释放内存时进行内存节点完整性校验,最后在程序结束时通过统计节点信息得到内存统计信息并根据统计信息判断内存是否泄漏的设计思想 +采用了对malloc/free接口进行插桩,保存关键节点信息,然后程序在申请和释放内存时进行内存节点完整性校验,最后在程序结束时通过统计节点信息得到内存统计信息并根据统计信息判断内存是否泄漏的设计思想。 ## 运行机制 @@ -28,7 +28,7 @@ Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、 ![zh-cn_image_0000001165890518](figures/zh-cn_image_0000001165890518.png) -其中,TID表示线程ID;PID表示进程ID;ptr表示申请的内存地址;size表示申请的内存大小;lr[n]表示函数调用栈地址,变量n可以根据具体场景的需要进行配置。 +其中,TID表示线程ID;PID表示进程ID;ptr表示申请的内存地址;size表示申请的内存大小;lr[n]表示函数调用栈地址,变量n的大小可以根据具体场景的需要进行配置。 释放内存时,将free等接口的入参指针与node的ptr字段进行匹配,如果相同则删除该内存节点控制块信息。 @@ -46,7 +46,7 @@ Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、 ### 内存完整性检查 -- 使用malloc申请内存(小于等于0x1c000bytes时通过堆分配算法分配) +- 使用malloc申请内存(小于等于0x1c000 bytes时通过堆分配算法分配) 用户程序申请堆内存时,在堆内存节点处添加校验值等信息,如果校验值异常,则很有可能是前一块堆内存使用越界导致的(目前无法识别校验值被野指针破坏的场景)。在内存申请、释放时校验内存节点校验值的正确性,若内存节点被破坏,校验失败时则输出tid、pid及当前被踩节点前一块堆内存申请时保存的调用栈信息,通过addr2line工具可获得具体的代码行信息,辅助用户解决问题。 **图4** node节点头信息添加校验值 @@ -59,7 +59,7 @@ Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、 ![zh-cn_image_0000001165890904](figures/zh-cn_image_0000001165890904.png) -- 使用malloc申请内存(大于0x1c000bytes时通过mmap申请) +- 使用malloc申请内存(大于0x1c000 bytes时通过mmap申请) 当malloc通过mmap申请大块内存时,在返回给用户使用的内存区间头和尾分别多申请一个页,一个页PAGE_SIZE当前为0x1000,这两个页分别通过mprotect接口设置权限为PROT_NONE(无可读可写权限),可以有效防止内存越界读写问题:越界读写数据时由于无读写权限而导致用户程序异常,根据异常调用栈信息可找到相应的代码逻辑。 **图6** malloc通过mmap机制申请内存的内存布局 @@ -119,7 +119,7 @@ Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、 代码功能:显式调用调测模块的相关接口对用户代码进行内存校验。 -``` +```c #include #include #include @@ -127,7 +127,8 @@ Debug版本的musl-libc库为用户提供内存泄漏检测、堆内存统计、 #define MALLOC_LEAK_SIZE 0x300 -void func(void) { +void func(void) +{ char *ptr = malloc(MALLOC_LEAK_SIZE); memset(ptr, '3', MALLOC_LEAK_SIZE); } @@ -158,15 +159,15 @@ $ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > - 本编译示例基于将编译器的路径写入环境变量中,即.bashrc文件中。 -> +> > - 编译用户程序及所需的lib库时,需要添加编译选项-funwind-tables,-rdynamic,-g,用于栈回溯。 -> +> > - -mfloat-abi=softfp,-mcpu=cortex-a7,-mfpu=neon-vfpv4编译选项用于指定具体的芯片架构、浮点数计算优化、fpu,与具体的libc库使用的编译选项保持一致,否则链接时可能出现找不到libc库文件。 -> +> > - -target arm-liteos用于指定编译器相关库文件路径。 -> +> > - --sysroot=/home/<user-name>/directory/out/hispark_taurus/ipcamera_hispark_taurus/sysroot用于指定编译器库文件搜索根目录,假设OpenHarmony工程代码存放路径为/home/<user-name>/directory。其中out/hispark_taurus/ipcamera_hispark_taurus路径为在编译时,hb set命令指定的具体产品,本示例选择的是ipcamera_hispark_taurus产品。 -> +> > - $(clang -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 -target arm-liteos -print-file-name=libunwind.a)用于指定相应的unwind库的路径。 @@ -175,7 +176,7 @@ $ clang -o mem_check mem_check.c -funwind-tables -rdynamic -g -mfloat-abi=softfp ``` OHOS # ./mem_check -OHOS # +OHOS # ==PID:4== Heap memory statistics(bytes): // 堆内存统计信息 [Check point]: // check点调用栈 #00: [0x86c] -> mem_check @@ -293,14 +294,15 @@ kill -37 # 检查堆内存头节点是否完整 代码功能:构造内存问题利用命令行方式进行内存调测。 -``` +```c #include #include #include #define MALLOC_LEAK_SIZE 0x300 -void func(void) { +void func(void) +{ char *ptr = malloc(MALLOC_LEAK_SIZE); memset(ptr, '3', MALLOC_LEAK_SIZE); } @@ -325,9 +327,9 @@ int main() ``` OHOS # ./mem_check --mwatch // 利用task命令可以查到mem_check进程的pid为4 -OHOS # +OHOS # OHOS # kill -35 4 // 查看堆内存统计信息 -OHOS # +OHOS # ==PID:4== Heap memory statistics(bytes): [Check point]: #00: [0x58dfc] -> /lib/libc.so @@ -337,7 +339,7 @@ OHOS # ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) OHOS # kill -36 4 // 检查是否存在堆内存泄漏 -OHOS # +OHOS # ==PID:4== Detected memory leak(s): [Check point]: #00: [0x2da4c] -> /lib/libc.so @@ -355,7 +357,7 @@ OHOS # ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). OHOS # kill -37 4 // 检查堆内存头节点的完整性 -OHOS # +OHOS # Check heap integrity ok! ``` @@ -391,109 +393,109 @@ 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 - + OHOS # cat /storage/pid(4)_check.txt - + ==PID:4== Heap memory statistics(bytes): [Check point]: #00: [0x5973c] -> /lib/libc.so - + [TID: 18, Used: 0x640] - + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) ``` 3. 利用kill -36 <pid>校验内存完整性,该信息将会输出到文件中,使用cat命令查看 - + ``` OHOS # kill -36 4 OHOS # Leak check information saved in /storage/pid(4)_check.txt - + OHOS # cat /storage/pid(4)_check.txt - + ==PID:4== Heap memory statistics(bytes): [Check point]: #00: [0x5973c] -> /lib/libc.so - + [TID: 18, Used: 0x640] - + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) - + ==PID:4== Detected memory leak(s): [Check point]: #00: [0x2e38c] -> /lib/libc.so #01: [0x5973c] -> /lib/libc.so - + [TID:18 Leak:0x320 byte(s)] Allocated from: #00: [0x724] -> mem_check #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so - + [TID:18 Leak:0x320 byte(s)] Allocated from: #00: [0x6ec] -> mem_check #01: [0x740] -> mem_check #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so - + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). ``` 4. 利用kill -9 <pid>杀掉当前进程,进程退出后会默认校验内存完整性,该信息将会输出到文件中,使用cat命令查看 - + ``` OHOS # kill -9 4 OHOS # Leak check information saved in /storage/pid(4)_check.txt - + Check heap integrity ok! - + OHOS # cat /storage/pid(4)_check.txt - OHOS # + OHOS # ==PID:4== Heap memory statistics(bytes): [Check point]: #00: [0x5973c] -> /lib/libc.so - + [TID: 18, Used: 0x640] - + ==PID:4== Total heap: 0x640 byte(s), Peak: 0x640 byte(s) - + ==PID:4== Detected memory leak(s): [Check point]: #00: [0x2e38c] -> /lib/libc.so #01: [0x5973c] -> /lib/libc.so - + [TID:18 Leak:0x320 byte(s)] Allocated from: #00: [0x724] -> mem_check #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so - + [TID:18 Leak:0x320 byte(s)] Allocated from: #00: [0x6ec] -> mem_check #01: [0x740] -> mem_check #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so - + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). - + ==PID:4== Detected memory leak(s): [Check point]: #00: [0x2e38c] -> /lib/libc.so #01: [0x11b2c] -> /lib/libc.so - + [TID:18 Leak:0x320 byte(s)] Allocated from: #00: [0x724] -> mem_check #01: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so - + [TID:18 Leak:0x320 byte(s)] Allocated from: #00: [0x6ec] -> mem_check #01: [0x740] -> mem_check #02: <(null)+0x1fdd231c>[0x2231c] -> /lib/libc.so - + ==PID:4== SUMMARY: 0x640 byte(s) leaked in 2 allocation(s). ``` @@ -504,7 +506,7 @@ Now using addr2line ... ### UAF(Use after free) -- 申请小块内存(不大于0x1c000字节) +- 申请小块内存(不大于0x1c000 bytes) free之后: 读操作:读取free之后的内存大概率是魔术数字(0xFEFEFEFE) @@ -515,7 +517,7 @@ Now using addr2line ... 写操作:无法校验。 -- 申请大块内存(大于0x1c000) +- 申请大块内存(大于0x1c000 bytes) 堆内存由malloc通过调用mmap接口申请,free之后若仍访问该内存,则用户程序异常(该内存区间已被unmap)。 @@ -526,22 +528,23 @@ Double free时,用户程序将会异常退出。 ### 堆内存节点被踩 -- 申请小块内存(不大于0x1c000) +- 申请小块内存(不大于0x1c000 bytes) + 堆内存节点被踩时,用户程序将会异常退出,并输出破坏被踩节点的可能的堆内存申请调用栈,对于野指针踩内存情况无法校验出来。例如用户程序mem_check中存在堆内存越界踩的情况,利用命令行方式可以获得踩内存的可能的具体位置。 - + ``` - OHOS # ./mem_check --mwatch - OHOS # + OHOS # ./mem_check --mwatch + OHOS # ==PID:6== Memory integrity information: [TID:28 allocated addr: 0x272e1ea0, size: 0x120] The possible attacker was allocated from: #00: [0x640e8] -> /lib/libc.so - #01: [0x21d0] -> mem_check + #01: [0x21d0] -> mem_check ``` 可以通过调用栈解析脚本对调用栈信息进行解析。 -- 申请大块内存(大于0x1c000) +- 申请大块内存(大于0x1c000 bytes) 堆内存由malloc通过mmap接口申请,申请得到的堆内存块前后各置一个size为PAGE_SIZE大小的区间,设置无读写权限,读写操作会触发用户程序异常。 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 f818c3bdf349ca14ddf83ba3bf6fdae3ce314436..50f0741d040d86f314f6c58bfb02f3fa74d271a0 100644 --- a/zh-cn/device-dev/kernel/kernel-small-memory-lms.md +++ b/zh-cn/device-dev/kernel/kernel-small-memory-lms.md @@ -3,7 +3,7 @@ ## 基本概念 -LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具。LMS能够实时检测缓冲区溢出(buffer overflow),释放后使用(use after free) 和重复释放(double Free), 在异常发生的第一时间通知操作系统,结合backtrace等定位手段,能准确定位到产生内存问题的代码行,极大提升内存问题定位效率。 +LMS全称为Lite Memory Sanitizer,是一种实时检测内存操作合法性的调测工具。LMS能够实时检测缓冲区溢出(buffer overflow),释放后使用(use after free) 和重复释放(double free), 在异常发生的第一时间通知操作系统,结合backtrace等定位手段,能准确定位到产生内存问题的代码行,极大提升内存问题定位效率。 OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能: @@ -20,7 +20,7 @@ OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能: LMS使用影子内存映射标记系统内存的状态,一共可标记为三个状态:可读写,不可读写,已释放。影子内存存放在内存池的尾部。 -- 内存从堆上申请后,会将数据区的影子内存设置为“可读写”状态,并将头结点区的影子内存设置为“不可读写”状态。 +- 内存从堆上申请后,会将数据区的影子内存设置为“可读写”状态,并将头节点区的影子内存设置为“不可读写”状态。 - 内存在堆上被释放时,会将被释放内存的影子内存设置为“已释放”状态。 @@ -38,12 +38,12 @@ OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信 **表1** LMS模块接口说明 -| 功能分类 | 接口名 | 描述 | +| 功能分类 | 接口名 | 描述 | | -------- | -------- | -------- | -| 添加指定内存池被检测 | LOS_LmsCheckPoolAdd | 将指定内存池的地址范围添加到LMS的内存检测链表上,当访问的地址在链表范围内时,LMS才进行合法性校验;且LOS_MemInit接口会调用该接口,默认将初始化的内存池挂入到检测链表中。 | -| 删除指定内存池不被检测 | LOS_LmsCheckPoolDel | 不检测指定内存池地址范围内的合法性校验。 | -| 使能指定内存段锁保护 | LOS_LmsAddrProtect | 为某段内存地址上锁,设置为不可读写,一旦访问则报错。 | -| 去能指定内存段锁保护 | LOS_LmsAddrDisableProtect | 为某段内存地址解锁,设置为可读写。 | +| 添加指定内存池被检测 | LOS_LmsCheckPoolAdd | 将指定内存池的地址范围添加到LMS的内存检测链表上,当访问的地址在链表范围内时,LMS才进行合法性校验;且LOS_MemInit接口会调用该接口,默认将初始化的内存池挂入到检测链表中。 | +| 删除指定内存池不被检测 | LOS_LmsCheckPoolDel | 不检测指定内存池地址范围内的合法性校验。 | +| 使能指定内存段锁保护 | LOS_LmsAddrProtect | 为某段内存地址上锁,设置为不可读写,一旦访问则报错。 | +| 去能指定内存段锁保护 | LOS_LmsAddrDisableProtect | 为某段内存地址解锁,设置为可读写。 | ### 用户态 @@ -61,19 +61,19 @@ 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 | - | LOSCFG_LMS_LOAD_CHECK | Enable lms read check | LMS内存读检测的裁剪开关 | YES/NO | - | LOSCFG_LMS_STORE_CHECK | Enable lms write check | LMS内存写检测的裁剪开关 | YES/NO | - | LOSCFG_LMS_CHECK_STRICT | Enable lms strict check, byte-by-byte | LMS内存逐字节严格检测的裁剪开关 | YES/NO | + | LOSCFG_KERNEL_LMS | Enable Lms Feature | Lms模块的裁剪开关 | YES/NO | + | LOSCFG_LMS_MAX_RECORD_POOL_NUM | Lms check pool max num | LMS支持的检测内存池最大个数 | INT | + | LOSCFG_LMS_LOAD_CHECK | Enable lms read check | LMS内存读检测的裁剪开关 | YES/NO | + | LOSCFG_LMS_STORE_CHECK | Enable lms write check | LMS内存写检测的裁剪开关 | YES/NO | + | LOSCFG_LMS_CHECK_STRICT | Enable lms strict check, byte-by-byte | LMS内存逐字节严格检测的裁剪开关 | YES/NO | 2. 在被检测模块的编译脚本中,修改编译选项。 增加LMS检测编译选项-fsanitize=kernel-address。为避免编译器优化,增加-O0编译选项。 gcc与clang编译选项存在差异,参照如下示例: - + ``` if ("$ohos_build_compiler_specified" == "gcc") { cflags_c = [ @@ -105,14 +105,15 @@ OpenHarmony LiteOS-A内核的LMS模块提供下面几种功能,接口详细信 2. 构造内存溢出错误和释放后使用错误。 -3. 添加-fsanitize=kernel-address后编译执行,观察输出结果 +3. 添加-fsanitize=kernel-address后编译执行,观察输出结果。 #### 内核态示例代码 + 该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。 实例代码如下: - -``` + +```c #define PAGE_SIZE (0x1000U) #define INDEX_MAX 20 UINT32 g_lmsTestTaskId; @@ -138,31 +139,32 @@ static VOID LmsTestUseAfterFree(VOID) PRINTK("\n######%s start ######\n", __FUNCTION__); UINT32 i; CHAR *str = (CHAR *)LOS_MemAlloc(g_testLmsPool, INDEX_MAX); - LOS_MemFree(g_testLmsPool, str); + (VOID)LOS_MemFree(g_testLmsPool, str); PRINTK("str[%2d]=0x%2x ", 0, str[0]); /* trigger use after free at str[0] */ PRINTK("\n######%s stop ######\n", __FUNCTION__); } VOID LmsTestCaseTask(VOID) -{ +{ testPoolInit(); LmsTestOsmallocOverflow(); LmsTestUseAfterFree(); } -UINT32 Example_Lms_test(VOID){ - UINT32 ret; - TSK_INIT_PARAM_S lmsTestTask; - /* 创建用于lms测试的任务 */ - memset(&lmsTestTask, 0, sizeof(TSK_INIT_PARAM_S)); +UINT32 Example_Lms_test(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S lmsTestTask; + /* 创建用于lms测试的任务 */ + memset(&lmsTestTask, 0, sizeof(TSK_INIT_PARAM_S)); lmsTestTask.pfnTaskEntry = (TSK_ENTRY_FUNC)LmsTestCaseTask; - lmsTestTask.pcName = "TestLmsTsk"; /* 测试任务名称 */ - lmsTestTask.uwStackSize = 0x800; - lmsTestTask.usTaskPrio = 5; - lmsTestTask.uwResved = LOS_TASK_STATUS_DETACHED; - ret = LOS_TaskCreate(&g_lmsTestTaskId, &lmsTestTask); - if(ret != LOS_OK){ - PRINT_ERR("LmsTestTask create failed .\n"); - return LOS_NOK; - } + lmsTestTask.pcName = "TestLmsTsk"; /* 测试任务名称 */ + lmsTestTask.uwStackSize = 0x800; // 0x800: lms test task stack size + lmsTestTask.usTaskPrio = 5; // 5: lms test task priority + lmsTestTask.uwResved = LOS_TASK_STATUS_DETACHED; + ret = LOS_TaskCreate(&g_lmsTestTaskId, &lmsTestTask); + if (ret != LOS_OK) { + PRINT_ERR("LmsTestTask create failed .\n"); + return LOS_NOK; + } return LOS_OK; } LOS_MODULE_INIT(Example_Lms_test, LOS_INIT_LEVEL_KMOD_EXTENDED); @@ -172,7 +174,7 @@ LOS_MODULE_INIT(Example_Lms_test, LOS_INIT_LEVEL_KMOD_EXTENDED); #### 内核态结果验证 输出结果如下: - + ``` ######LmsTestOsmallocOverflow start ###### [ERR][KProcess:LmsTestCaseTask]* Kernel Address Sanitizer Error Detected Start * @@ -257,9 +259,9 @@ str[ 0]=0x 0 ### 用户态开发流程 -在待检测的app编译脚本中,添加如下参数即可, 完整示例可参见/kernel/liteos_a/apps/lms/BUILD.gn。 +在待检测的app编译脚本中,添加如下参数即可, 完整示例可参见 [/kernel/liteos_a/apps/lms/BUILD.gn](https://gitee.com/openharmony/kernel_liteos_a/blob/master/apps/lms/BUILD.gn)。 + - ``` if ("$ohos_build_compiler_specified" == "gcc") { cflags_c = [ @@ -308,14 +310,14 @@ if ("$ohos_build_compiler_specified" == "gcc") { 1. 构造内存溢出错误和释放后使用错误。 -2. 添加对应编译选项后,重新编译执行 +2. 添加对应编译选项后,重新编译执行。 #### 用户态示例代码 实例代码如下: - -``` + +```c static void BufWriteTest(void *buf, int start, int end) { for (int i = start; i <= end; i++) { @@ -332,7 +334,7 @@ static void BufReadTest(void *buf, int start, int end) static void LmsMallocTest(void) { printf("\n-------- LmsMallocTest Start --------\n"); - char *buf = (char *)malloc(16); + char *buf = (char *)malloc(16); // 16: buffer size for test BufReadTest(buf, -1, 16); free(buf); printf("\n-------- LmsMallocTest End --------\n"); @@ -340,7 +342,7 @@ static void LmsMallocTest(void) static void LmsFreeTest(void) { printf("\n-------- LmsFreeTest Start --------\n"); - char *buf = (char *)malloc(16); + char *buf = (char *)malloc(16); // 16: buffer size for test free(buf); BufReadTest(buf, 1, 1); free(buf); @@ -349,7 +351,7 @@ static void LmsFreeTest(void) int main(int argc, char * const * argv) { printf("\n############### Lms Test start ###############\n"); - char *tmp = (char *)malloc(5000); + char *tmp = (char *)malloc(5000); // 5000: temp buffer size LmsMallocTest(); LmsFreeTest(); printf("\n############### Lms Test End ###############\n"); @@ -360,7 +362,7 @@ 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-start-kernel.md b/zh-cn/device-dev/kernel/kernel-small-start-kernel.md index 0606d6136ad377b1f2d1523e0195d5d515419440..4e6910d864289a9438b4da677ad9121f540e9052 100644 --- a/zh-cn/device-dev/kernel/kernel-small-start-kernel.md +++ b/zh-cn/device-dev/kernel/kernel-small-start-kernel.md @@ -3,7 +3,7 @@ ## 内核启动流程 -内核启动流程包含汇编启动阶段和C语言启动阶段2部分,如图1所示。汇编启动阶段完成CPU初始设置,关闭dcache/icache,使能FPU及neon,设置MMU建立虚实地址映射,设置系统栈,清理bss段,调用C语言main函数等。C语言启动阶段包含OsMain函数及开始调度等,其中如上图所示,OsMain函数用于内核基础初始化和架构、板级初始化等,其整体由内核启动框架主导初始化流程,图中右边区域为启动框架中可接受外部模块注册启动的阶段,各个阶段的说明如下表1所示。 +内核启动流程包含汇编启动阶段和C语言启动阶段2部分,如图1所示。汇编启动阶段完成CPU初始设置,关闭dcache/icache,使能FPU及neon,设置MMU建立虚实地址映射,设置系统栈,清理bss段,调用C语言main函数等。C语言启动阶段包含OsMain函数及开始调度等,其中如图1所示,OsMain函数用于内核基础初始化和架构、板级初始化等,其整体由内核启动框架主导初始化流程,图中右边区域为启动框架中可接受外部模块注册启动的阶段,各个阶段的说明如下表1所示。 **图1** 内核启动流程图 @@ -12,59 +12,57 @@ **表1** 启动框架层级 -| 层级 | 说明 | +| 层级 | 说明 | | -------- | -------- | -| 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_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_FINISH | 内核初始化完成 | ## 编程样例 - **实例描述** + **实例描述** 新增一个内核模块,需要在内核初始化时进行该模块的初始化,则通过内核启动框架将该模块的初始化函数注册进内核启动流程中。 +为方便学习,本演示代码直接在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证即可。 **示例代码** - - -``` +```c /* 内核启动框架头文件 */ #include "los_init.h" -...... /* 新增模块的初始化函数 */ unsigned int OsSampleModInit(void) { PRINTK("OsSampleModInit SUCCESS!\n"); - ...... } -...... + /* 在启动框架的目标层级中注册新增模块 */ LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED); ``` - **结果验证** - - ``` + main core booting up... + +/* 根据实际运行环境,过程打印会有差异 */ +...... + +/* 打印测试代码新增模块初始化函数 */ OsSampleModInit SUCCESS! -releasing 1 secondary cores -cpu 1 entering scheduler -cpu 0 entering scheduler ``` @@ -73,5 +71,5 @@ cpu 0 entering scheduler > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** > 启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。 -> +> > 可通过查看系统编译生成文件OHOS_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。 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 dcbd07fbcc501b04214691a8dd92e477da505188..98aae2d70f84c258cdfeb936f131662b20d12ed4 100644 --- a/zh-cn/device-dev/kernel/kernel-small-start-user.md +++ b/zh-cn/device-dev/kernel/kernel-small-start-user.md @@ -15,7 +15,7 @@ 使用链接脚本将如下init启动代码放置到系统镜像指定位置。 -``` +```c #define LITE_USER_SEC_ENTRY __attribute__((section(".user.entry"))) LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args) { @@ -27,6 +27,8 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args) } ``` +> 上述启动代码已在 kernel/liteos_a/kernel/user/src/los_user_init.c 中,g_initPath 根据启动设置的不同,其值为 /dev/shm/init 或 /bin/init。 + 系统启动阶段,OsUserInitProcess启动init进程。具体过程如下: 1. 由内核OsLoadUserInit加载上述代码。 @@ -48,7 +50,7 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args) 用户态程序启动有如下常见方式: - shell命令启动进程。 - + ``` OHOS $ exec helloworld OHOS $ ./helloworld diff --git a/zh-cn/device-dev/website.md b/zh-cn/device-dev/website.md index c82e9d888cd385b902e1d33450283d1d26a351d1..852b698f9577581d0de721b2e9e2b2616fa39350 100644 --- a/zh-cn/device-dev/website.md +++ b/zh-cn/device-dev/website.md @@ -178,6 +178,7 @@ - [异常调测](kernel/kernel-mini-memory-exception.md) - [Trace调测](kernel/kernel-mini-memory-trace.md) - [LMS调测](kernel/kernel-mini-memory-lms.md) + - [SHELL](kernel/kernel-mini-debug-shell.md) - 附录 - [内核编码规范](kernel/kernel-mini-appx-code.md) - [标准库支持](kernel/kernel-mini-appx-lib.md) @@ -217,6 +218,7 @@ - [虚拟文件系统](kernel/kernel-small-bundles-fs-virtual.md) - [支持的文件系统](kernel/kernel-small-bundles-fs-support.md) - [适配新的文件系统](kernel/kernel-small-bundles-fs-new.md) + - [Plimitsfs文件系统](kernel/kernel-small-plimits.md) - 调测与工具 - Shell - [Shell介绍](kernel/kernel-small-debug-shell-overview.md) @@ -286,7 +288,7 @@ - [魔法键使用方法](kernel/kernel-small-debug-shell-magickey.md) - [用户态异常信息说明](kernel/kernel-small-debug-shell-error.md) - [Trace调测](kernel/kernel-small-debug-trace.md) - - [Perf调测](kernel/kernel-mini-memory-perf.md) + - [Perf调测](kernel/kernel-small-debug-perf.md) - [LMS调测](kernel/kernel-small-memory-lms.md) - [进程调测](kernel/kernel-small-debug-process-cpu.md) - 内核态内存调测 @@ -522,7 +524,7 @@ - [xdevice测试调度框架使用指导](device-test/xdevice.md) - 调测工具 - [bytrace使用指导](subsystems/subsys-toolchain-bytrace-guide.md) - - [hdc 使用指导](subsystems/subsys-toolchain-hdc-guide.md) + - [hdc\_std 使用指导](subsystems/subsys-toolchain-hdc-guide.md) - [hiperf 使用指南](subsystems/subsys-toolchain-hiperf.md) - [XTS认证](device-test/xts.md) - 工具