Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
d3855b41
D
Docs
项目概览
OpenHarmony
/
Docs
接近 2 年 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d3855b41
编写于
1月 13, 2023
作者:
W
wangchen
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: A核资料描述和示例代码问题修改
方案描述: 1,按测试沟通的文档问题进行修改 fix #I69MYM Signed-off-by:
N
wangchen
<
wangchen240@huawei.com
>
上级
1dad82b7
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
264 addition
and
434 deletion
+264
-434
zh-cn/device-dev/kernel/Readme-CN.md
zh-cn/device-dev/kernel/Readme-CN.md
+1
-1
zh-cn/device-dev/kernel/kernel-small-apx-library.md
zh-cn/device-dev/kernel/kernel-small-apx-library.md
+32
-52
zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md
zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md
+14
-21
zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md
zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md
+31
-30
zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md
zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md
+25
-20
zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md
...n/device-dev/kernel/kernel-small-basic-trans-semaphore.md
+20
-16
zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md
zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md
+8
-7
zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md
zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md
+52
-39
zh-cn/device-dev/kernel/kernel-small-debug-perf.md
zh-cn/device-dev/kernel/kernel-small-debug-perf.md
+60
-227
zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md
zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md
+11
-8
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
+8
-11
zh-cn/device-dev/kernel/kernel-small-start-user.md
zh-cn/device-dev/kernel/kernel-small-start-user.md
+1
-1
zh-cn/device-dev/website.md
zh-cn/device-dev/website.md
+1
-1
未找到文件。
zh-cn/device-dev/kernel/Readme-CN.md
浏览文件 @
d3855b41
...
@@ -136,7 +136,7 @@
...
@@ -136,7 +136,7 @@
-
[
魔法键使用方法
](
kernel-small-debug-shell-magickey.md
)
-
[
魔法键使用方法
](
kernel-small-debug-shell-magickey.md
)
-
[
用户态异常信息说明
](
kernel-small-debug-shell-error.md
)
-
[
用户态异常信息说明
](
kernel-small-debug-shell-error.md
)
-
[
Trace调测
](
kernel-small-debug-trace.md
)
-
[
Trace调测
](
kernel-small-debug-trace.md
)
-
[
Perf调测
](
kernel-
mini-memory
-perf.md
)
-
[
Perf调测
](
kernel-
small-debug
-perf.md
)
-
[
LMS调测
](
kernel-small-memory-lms.md
)
-
[
LMS调测
](
kernel-small-memory-lms.md
)
-
[
进程调测
](
kernel-small-debug-process-cpu.md
)
-
[
进程调测
](
kernel-small-debug-process-cpu.md
)
-
内核态内存调测
-
内核态内存调测
...
...
zh-cn/device-dev/kernel/kernel-small-apx-library.md
浏览文件 @
d3855b41
...
@@ -24,7 +24,7 @@ musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony
...
@@ -24,7 +24,7 @@ musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony
#### 编程示例
#### 编程示例
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数
testcase 或新建文件由主函数调用
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数
ExamplePosix。
示例代码如下:
示例代码如下:
...
@@ -33,12 +33,6 @@ musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony
...
@@ -33,12 +33,6 @@ musl libc库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony
#include <unistd.h>
#include <unistd.h>
#include <pthread.h>
#include <pthread.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define THREAD_NUM 3
#define THREAD_NUM 3
int g_startNum = 0; /* 启动的线程数 */
int g_startNum = 0; /* 启动的线程数 */
int g_wakenNum = 0; /* 唤醒的线程数 */
int g_wakenNum = 0; /* 唤醒的线程数 */
...
@@ -48,10 +42,8 @@ struct testdata {
...
@@ -48,10 +42,8 @@ struct testdata {
pthread_cond_t cond;
pthread_cond_t cond;
} g_td;
} g_td;
/*
/* 子线程入口函数 */
* 子线程入口函数
static VOID *ChildThreadFunc(VOID *arg)
*/
static void *ChildThreadFunc(void *arg)
{
{
int rc;
int rc;
pthread_t self = pthread_self();
pthread_t self = pthread_self();
...
@@ -59,7 +51,7 @@ static void *ChildThreadFunc(void *arg)
...
@@ -59,7 +51,7 @@ static void *ChildThreadFunc(void *arg)
/* 获取mutex锁 */
/* 获取mutex锁 */
rc = pthread_mutex_lock(&g_td.mutex);
rc = pthread_mutex_lock(&g_td.mutex);
if (rc != 0) {
if (rc != 0) {
printf("ERROR:take mutex lock failed, error code is %d!\n", rc);
d
printf("ERROR:take mutex lock failed, error code is %d!\n", rc);
goto EXIT;
goto EXIT;
}
}
...
@@ -69,7 +61,7 @@ static void *ChildThreadFunc(void *arg)
...
@@ -69,7 +61,7 @@ static void *ChildThreadFunc(void *arg)
/* 等待cond条件变量 */
/* 等待cond条件变量 */
rc = pthread_cond_wait(&g_td.cond, &g_td.mutex);
rc = pthread_cond_wait(&g_td.cond, &g_td.mutex);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: pthread condition wait failed, error code is %d!\n", rc);
d
printf("ERROR: pthread condition wait failed, error code is %d!\n", rc);
(void)pthread_mutex_unlock(&g_td.mutex);
(void)pthread_mutex_unlock(&g_td.mutex);
goto EXIT;
goto EXIT;
}
}
...
@@ -77,7 +69,7 @@ static void *ChildThreadFunc(void *arg)
...
@@ -77,7 +69,7 @@ static void *ChildThreadFunc(void *arg)
/* 尝试获取mutex锁,正常场景,此处无法获取锁 */
/* 尝试获取mutex锁,正常场景,此处无法获取锁 */
rc = pthread_mutex_trylock(&g_td.mutex);
rc = pthread_mutex_trylock(&g_td.mutex);
if (rc == 0) {
if (rc == 0) {
printf("ERROR: mutex gets an abnormal lock!\n");
d
printf("ERROR: mutex gets an abnormal lock!\n");
goto EXIT;
goto EXIT;
}
}
...
@@ -87,14 +79,14 @@ static void *ChildThreadFunc(void *arg)
...
@@ -87,14 +79,14 @@ static void *ChildThreadFunc(void *arg)
/* 释放mutex锁 */
/* 释放mutex锁 */
rc = pthread_mutex_unlock(&g_td.mutex);
rc = pthread_mutex_unlock(&g_td.mutex);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: mutex release failed, error code is %d!\n", rc);
d
printf("ERROR: mutex release failed, error code is %d!\n", rc);
goto EXIT;
goto EXIT;
}
}
EXIT:
EXIT:
return NULL;
return NULL;
}
}
static int
testcase(void
)
static int
ExamplePosix(VOID
)
{
{
int i, rc;
int i, rc;
pthread_t thread[THREAD_NUM];
pthread_t thread[THREAD_NUM];
...
@@ -102,14 +94,14 @@ static int testcase(void)
...
@@ -102,14 +94,14 @@ static int testcase(void)
/* 初始化mutex锁 */
/* 初始化mutex锁 */
rc = pthread_mutex_init(&g_td.mutex, NULL);
rc = pthread_mutex_init(&g_td.mutex, NULL);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: mutex init failed, error code is %d!\n", rc);
d
printf("ERROR: mutex init failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
/* 初始化cond条件变量 */
/* 初始化cond条件变量 */
rc = pthread_cond_init(&g_td.cond, NULL);
rc = pthread_cond_init(&g_td.cond, NULL);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: pthread condition init failed, error code is %d!\n", rc);
d
printf("ERROR: pthread condition init failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
...
@@ -117,10 +109,11 @@ static int testcase(void)
...
@@ -117,10 +109,11 @@ static int testcase(void)
for (i = 0; i < THREAD_NUM; i++) {
for (i = 0; i < THREAD_NUM; i++) {
rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL);
rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: pthread create failed, error code is %d!\n", rc);
d
printf("ERROR: pthread create failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
}
}
dprintf("pthread_create ok\n");
/* 等待所有子线程都完成mutex锁的获取 */
/* 等待所有子线程都完成mutex锁的获取 */
while (g_startNum < THREAD_NUM) {
while (g_startNum < THREAD_NUM) {
...
@@ -130,14 +123,14 @@ static int testcase(void)
...
@@ -130,14 +123,14 @@ static int testcase(void)
/* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */
/* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */
rc = pthread_mutex_lock(&g_td.mutex);
rc = pthread_mutex_lock(&g_td.mutex);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: mutex lock failed, error code is %d\n", rc);
d
printf("ERROR: mutex lock failed, error code is %d\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
/* 释放mutex锁 */
/* 释放mutex锁 */
rc = pthread_mutex_unlock(&g_td.mutex);
rc = pthread_mutex_unlock(&g_td.mutex);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: mutex unlock failed, error code is %d!\n", rc);
d
printf("ERROR: mutex unlock failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
...
@@ -145,7 +138,7 @@ static int testcase(void)
...
@@ -145,7 +138,7 @@ static int testcase(void)
/* 在cond条件变量上广播信号 */
/* 在cond条件变量上广播信号 */
rc = pthread_cond_signal(&g_td.cond);
rc = pthread_cond_signal(&g_td.cond);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: pthread condition failed, error code is %d!\n", rc);
d
printf("ERROR: pthread condition failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
}
}
...
@@ -154,52 +147,42 @@ static int testcase(void)
...
@@ -154,52 +147,42 @@ static int testcase(void)
/* 检查是否所有子线程都已被唤醒 */
/* 检查是否所有子线程都已被唤醒 */
if (g_wakenNum != THREAD_NUM) {
if (g_wakenNum != THREAD_NUM) {
printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum);
d
printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum);
goto ERROROUT;
goto ERROROUT;
}
}
dprintf("all threads awaked\n");
/* join所有子线程,即等待其结束 */
/* join所有子线程,即等待其结束 */
for (i = 0; i < THREAD_NUM; i++) {
for (i = 0; i < THREAD_NUM; i++) {
rc = pthread_join(thread[i], NULL);
rc = pthread_join(thread[i], NULL);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: pthread join failed, error code is %d!\n", rc);
d
printf("ERROR: pthread join failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
}
}
dprintf("all threads join ok\n");
/* 销毁cond条件变量 */
/* 销毁cond条件变量 */
rc = pthread_cond_destroy(&g_td.cond);
rc = pthread_cond_destroy(&g_td.cond);
if (rc != 0) {
if (rc != 0) {
printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc);
d
printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc);
goto ERROROUT;
goto ERROROUT;
}
}
return 0;
return 0;
ERROROUT:
ERROROUT:
return -1;
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标准库差异
## 与Linux标准库差异
...
@@ -217,20 +200,17 @@ int main(int argc, char *argv[])
...
@@ -217,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)。
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进行回收。
其中,参数fd的生命周期实现与Linux glibc存在差异。具体体现在,glibc在成功调用mmap进行映射后,可以立即释放fd句柄。在OpenHarmony内核中,不允许用户在映射成功后立即关闭相关fd,只允许在取消映射munmap后再进行fd的close操作。如果用户不进行fd的close操作,操作系统将在进程退出时对该fd进行回收。
**代码举例**
**h2代码举例**
Linux目前支持的情况如下:
Linux目前支持的情况如下:
```
```
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
{
...
@@ -247,7 +227,7 @@ int main(int argc, char *argv[])
...
@@ -247,7 +227,7 @@ int main(int argc, char *argv[])
perror("mmap");
perror("mmap");
exit(EXIT_FAILURE);
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);
exit(EXIT_SUCCESS);
}
}
...
@@ -255,7 +235,7 @@ int main(int argc, char *argv[])
...
@@ -255,7 +235,7 @@ int main(int argc, char *argv[])
OpenHarmony支持的情况如下:
OpenHarmony支持的情况如下:
```
```
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
{
...
@@ -274,7 +254,7 @@ int main(int argc, char *argv[])
...
@@ -274,7 +254,7 @@ int main(int argc, char *argv[])
}
}
...
...
munmap(addr, length);
munmap(addr, length);
close(fd); /* Close fd after the munmap is canceled. */
close(fd);
/* Close fd after the munmap is canceled. */
exit(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}
}
```
```
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md
浏览文件 @
d3855b41
...
@@ -31,7 +31,7 @@ OpenHarmony LiteOS-A的事件模块提供的事件,具有如下特点:
...
@@ -31,7 +31,7 @@ OpenHarmony LiteOS-A的事件模块提供的事件,具有如下特点:
### 事件控制块
### 事件控制块
```
```
/**
/**
* 事件控制块数据结构
* 事件控制块数据结构
...
@@ -144,21 +144,21 @@ UINT32 g_testTaskId;
...
@@ -144,21 +144,21 @@ UINT32 g_testTaskId;
EVENT_CB_S g_exampleEvent;
EVENT_CB_S g_exampleEvent;
/* 等待的事件类型 */
/* 等待的事件类型 */
#define EVENT_WAIT 0x00000001
#define EVENT_WAIT
0x00000001
#define EVENT_TIMEOUT 500
/* 用例任务入口函数 */
/* 用例任务入口函数 */
VOID Example_Event(VOID)
VOID Example_Event(VOID)
{
{
UINT32 event;
UINT32 event;
/* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */
/* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */
printf("Example_Event wait event 0x%x \n", EVENT_WAIT);
d
printf("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) {
if (event == EVENT_WAIT) {
printf("Example_Event,read event :0x%x\n", event);
d
printf("Example_Event,read event :0x%x\n", event);
} else {
} else {
printf("Example_Event,read event timeout\n");
d
printf("Example_Event,read event timeout\n");
}
}
}
}
...
@@ -170,7 +170,7 @@ UINT32 Example_EventEntry(VOID)
...
@@ -170,7 +170,7 @@ UINT32 Example_EventEntry(VOID)
/* 事件初始化 */
/* 事件初始化 */
ret = LOS_EventInit(&g_exampleEvent);
ret = LOS_EventInit(&g_exampleEvent);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("init event failed .\n");
d
printf("init event failed .\n");
return -1;
return -1;
}
}
...
@@ -182,30 +182,23 @@ UINT32 Example_EventEntry(VOID)
...
@@ -182,30 +182,23 @@ UINT32 Example_EventEntry(VOID)
task1.usTaskPrio = 5;
task1.usTaskPrio = 5;
ret = LOS_TaskCreate(&g_testTaskId, &task1);
ret = LOS_TaskCreate(&g_testTaskId, &task1);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("task create failed.\n");
d
printf("task create failed.\n");
return LOS_NOK;
return LOS_NOK;
}
}
/* 写g_testTaskId 等待事件 */
/* 写g_testTaskId 等待事件 */
printf("Example_TaskEntry write event.\n");
d
printf("Example_TaskEntry write event.\n");
ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT);
ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("event write failed.\n");
d
printf("event write failed.\n");
return LOS_NOK;
return LOS_NOK;
}
}
/* 清标志位 */
/* 清标志位 */
printf("EventMask:%d\n", g_exampleEvent.uwEventID);
d
printf("EventMask:%d\n", g_exampleEvent.uwEventID);
LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID);
LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID);
printf("EventMask:%d\n", g_exampleEvent.uwEventID);
dprintf("EventMask:%d\n", g_exampleEvent.uwEventID);
/* 删除任务 */
ret = LOS_TaskDelete(g_testTaskId);
if (ret != LOS_OK) {
printf("task delete failed.\n");
return LOS_NOK;
}
return LOS_OK;
return LOS_OK;
}
}
...
@@ -216,7 +209,7 @@ UINT32 Example_EventEntry(VOID)
...
@@ -216,7 +209,7 @@ UINT32 Example_EventEntry(VOID)
编译运行得到的结果为:
编译运行得到的结果为:
```
```
Example_Event wait event 0x1
Example_Event wait event 0x1
Example_TaskEntry write event.
Example_TaskEntry write event.
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md
浏览文件 @
d3855b41
...
@@ -104,13 +104,13 @@
...
@@ -104,13 +104,13 @@
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数Example_MutexEntry。
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数Example_MutexEntry。
示例代码如下:
示例代码如下:
```
```
#include <string.h>
#include <string.h>
#include "los_mux.h"
#include "los_mux.h"
/* 互斥锁 */
/* 互斥锁 */
LosMux g_testMux;
LosMux g_testMu
te
x;
/* 任务ID */
/* 任务ID */
UINT32 g_testTaskId01;
UINT32 g_testTaskId01;
UINT32 g_testTaskId02;
UINT32 g_testTaskId02;
...
@@ -118,48 +118,49 @@ UINT32 g_testTaskId02;
...
@@ -118,48 +118,49 @@ UINT32 g_testTaskId02;
VOID Example_MutexTask1(VOID)
VOID Example_MutexTask1(VOID)
{
{
UINT32 ret;
UINT32 ret;
LOS_TaskDelay(50);
printf("task1 try to get mutex, wait 10 ticks.\n");
d
printf("task1 try to get mutex, wait 10 ticks.\n");
/* 申请互斥锁 */
/* 申请互斥锁 */
ret = LOS_MuxLock(&g_testMux, 10);
ret = LOS_MuxLock(&g_testMu
te
x, 10);
if (ret == LOS_OK) {
if (ret == LOS_OK) {
printf("task1 get mutex g_testMux.\n");
d
printf("task1 get mutex g_testMux.\n");
/* 释放互斥锁 */
/* 释放互斥锁 */
LOS_MuxUnlock(&g_testMux);
LOS_MuxUnlock(&g_testMu
te
x);
return;
return;
}
}
if (ret == LOS_ETIMEDOUT
) {
if (ret == LOS_ETIMEDOUT) {
printf("task1 timeout and try to get mutex, wait forever.\n");
d
printf("task1 timeout and try to get mutex, wait forever.\n");
/* 申请互斥锁 */
/* 申请互斥锁 */
ret = LOS_MuxLock(&g_testMu
x, LOS_WAIT_FOREVER);
ret = LOS_MuxLock(&g_testMute
x, LOS_WAIT_FOREVER);
if (ret == LOS_OK) {
if (ret == LOS_OK) {
printf("task1 wait forever, get mutex g_testMux.\n");
d
printf("task1 wait forever, get mutex g_testMux.\n");
/* 释放互斥锁 */
/* 释放互斥锁 */
LOS_MuxUnlock(&g_testMu
x);
LOS_MuxUnlock(&g_testMute
x);
/* 删除互斥锁 */
/* 删除互斥锁 */
LOS_MuxDestroy(&g_testMu
x);
LOS_MuxDestroy(&g_testMute
x);
printf("task1 post and delete mutex g_testMux.\n");
d
printf("task1 post and delete mutex g_testMux.\n");
return;
return;
}
}
}
}
return;
return;
}
}
VOID Example_MutexTask2(VOID)
VOID Example_MutexTask2(VOID)
{
{
printf("task2 try to get mutex, wait forever.\n");
d
printf("task2 try to get mutex, wait forever.\n");
/* 申请互斥锁 */
/* 申请互斥锁 */
(VOID)LOS_MuxLock(&g_testMux, LOS_WAIT_FOREVER);
(VOID)LOS_MuxLock(&g_testMu
te
x, LOS_WAIT_FOREVER);
printf("task2 get mutex g_testMux and suspend 100 ticks.\n");
d
printf("task2 get mutex g_testMux and suspend 100 ticks.\n");
/* 任务休眠100Ticks */
/* 任务休眠100Ticks */
LOS_TaskDelay(100);
LOS_TaskDelay(100);
printf("task2 resumed and post the g_testMux\n");
d
printf("task2 resumed and post the g_testMux\n");
/* 释放互斥锁 */
/* 释放互斥锁 */
LOS_MuxUnlock(&g_testMux);
LOS_MuxUnlock(&g_testMu
te
x);
return;
return;
}
}
...
@@ -170,7 +171,7 @@ UINT32 Example_MutexEntry(VOID)
...
@@ -170,7 +171,7 @@ UINT32 Example_MutexEntry(VOID)
TSK_INIT_PARAM_S task2;
TSK_INIT_PARAM_S task2;
/* 初始化互斥锁 */
/* 初始化互斥锁 */
LOS_MuxInit(&g_testMux, NULL);
LOS_MuxInit(&g_testMu
te
x, NULL);
/* 锁任务调度 */
/* 锁任务调度 */
LOS_TaskLock();
LOS_TaskLock();
...
@@ -183,7 +184,7 @@ UINT32 Example_MutexEntry(VOID)
...
@@ -183,7 +184,7 @@ UINT32 Example_MutexEntry(VOID)
task1.usTaskPrio = 5;
task1.usTaskPrio = 5;
ret = LOS_TaskCreate(&g_testTaskId01, &task1);
ret = LOS_TaskCreate(&g_testTaskId01, &task1);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("task1 create failed.\n");
d
printf("task1 create failed.\n");
return LOS_NOK;
return LOS_NOK;
}
}
...
@@ -195,7 +196,7 @@ UINT32 Example_MutexEntry(VOID)
...
@@ -195,7 +196,7 @@ UINT32 Example_MutexEntry(VOID)
task2.usTaskPrio = 4;
task2.usTaskPrio = 4;
ret = LOS_TaskCreate(&g_testTaskId02, &task2);
ret = LOS_TaskCreate(&g_testTaskId02, &task2);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("task2 create failed.\n");
d
printf("task2 create failed.\n");
return LOS_NOK;
return LOS_NOK;
}
}
...
@@ -210,11 +211,11 @@ UINT32 Example_MutexEntry(VOID)
...
@@ -210,11 +211,11 @@ UINT32 Example_MutexEntry(VOID)
编译运行得到的结果为:
编译运行得到的结果为:
```
```
task1 try to get mutex, wait 10 ticks.
task2 try to get mutex, wait forever.
task2 try to get mutex, wait forever.
task2 get mutex g_testMux and suspend 100 ticks.
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.
task1 timeout and try to get mutex, wait forever.
task2 resumed and post the g_testMux
task2 resumed and post the g_testMux
task1 wait forever, get mutex g_testMux.
task1 wait forever, get mutex g_testMux.
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md
浏览文件 @
d3855b41
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
### 队列控制块
### 队列控制块
```
```
/**
/**
* 队列控制块数据结构
* 队列控制块数据结构
...
@@ -137,7 +137,9 @@ typedef struct {
...
@@ -137,7 +137,9 @@ typedef struct {
### 编程示例
### 编程示例
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExampleQueue。
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数ExampleQueue,
为方便用户观察,建议调用ExampleQueue前先调用 LOS_Msleep(5000) 进行短时间延时,避免其他打印过多。
示例代码如下:
示例代码如下:
...
@@ -155,7 +157,7 @@ VOID SendEntry(VOID)
...
@@ -155,7 +157,7 @@ VOID SendEntry(VOID)
ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0);
ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0);
if(ret != LOS_OK) {
if(ret != LOS_OK) {
printf("send message failure, error: %x\n", ret);
d
printf("send message failure, error: %x\n", ret);
}
}
}
}
...
@@ -165,30 +167,36 @@ VOID RecvEntry(VOID)
...
@@ -165,30 +167,36 @@ VOID RecvEntry(VOID)
CHAR readBuf[BUFFER_LEN] = {0};
CHAR readBuf[BUFFER_LEN] = {0};
UINT32 readLen = BUFFER_LEN;
UINT32 readLen = BUFFER_LEN;
//休眠1s
LOS_Msleep(1000);
usleep(1000000);
ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0);
ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0);
if(ret != LOS_OK) {
if(ret != LOS_OK) {
printf("recv message failure, error: %x\n", ret);
d
printf("recv message failure, error: %x\n", ret);
}
}
printf("recv message: %s\n", readBuf);
d
printf("recv message: %s\n", readBuf);
ret = LOS_QueueDelete(g_queue);
ret = LOS_QueueDelete(g_queue);
if(ret != LOS_OK) {
if(ret != LOS_OK) {
printf("delete the queue failure, error: %x\n", ret);
d
printf("delete the queue failure, error: %x\n", ret);
}
}
printf("delete the queue success!\n");
d
printf("delete the queue success!\n");
}
}
UINT32 ExampleQueue(VOID)
UINT32 ExampleQueue(VOID)
{
{
printf("start queue example\n");
d
printf("start queue example\n");
UINT32 ret = 0;
UINT32 ret = 0;
UINT32 task1, task2;
UINT32 task1, task2;
TSK_INIT_PARAM_S initParam = {0};
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.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry;
initParam.usTaskPrio = 9;
initParam.usTaskPrio = 9;
initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
...
@@ -197,7 +205,8 @@ UINT32 ExampleQueue(VOID)
...
@@ -197,7 +205,8 @@ UINT32 ExampleQueue(VOID)
LOS_TaskLock();
LOS_TaskLock();
ret = LOS_TaskCreate(&task1, &initParam);
ret = LOS_TaskCreate(&task1, &initParam);
if(ret != LOS_OK) {
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;
return ret;
}
}
...
@@ -205,17 +214,13 @@ UINT32 ExampleQueue(VOID)
...
@@ -205,17 +214,13 @@ UINT32 ExampleQueue(VOID)
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry;
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry;
ret = LOS_TaskCreate(&task2, &initParam);
ret = LOS_TaskCreate(&task2, &initParam);
if(ret != LOS_OK) {
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;
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_TaskUnlock();
LOS_Msleep(5000);
return ret;
return ret;
}
}
```
```
...
@@ -225,9 +230,9 @@ UINT32 ExampleQueue(VOID)
...
@@ -225,9 +230,9 @@ UINT32 ExampleQueue(VOID)
编译运行得到的结果为:
编译运行得到的结果为:
```
```
start
test
example
start
queue
example
create the queue success!
create the queue success!
recv message: test message
recv message: test message
delete the queue success!
delete the queue success!
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md
浏览文件 @
d3855b41
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
**信号量控制块**
**信号量控制块**
```
```
/**
/**
* 信号量控制块数据结构
* 信号量控制块数据结构
...
@@ -129,7 +129,8 @@ static UINT32 g_testTaskId01;
...
@@ -129,7 +129,8 @@ static UINT32 g_testTaskId01;
static UINT32 g_testTaskId02;
static UINT32 g_testTaskId02;
/* 测试任务优先级 */
/* 测试任务优先级 */
#define TASK_PRIO_TEST 5
#define TASK_PRIO_LOW 5
#define TASK_PRIO_HI 4
/* 信号量结构体id */
/* 信号量结构体id */
static UINT32 g_semId;
static UINT32 g_semId;
...
@@ -138,11 +139,10 @@ VOID ExampleSemTask1(VOID)
...
@@ -138,11 +139,10 @@ VOID ExampleSemTask1(VOID)
{
{
UINT32 ret;
UINT32 ret;
printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n");
d
printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n");
/* 定时阻塞模式申请信号量,定时时间为10ticks */
/* 定时阻塞模式申请信号量,定时时间为10ticks */
ret = LOS_SemPend(g_semId, 10);
ret = LOS_SemPend(g_semId, 10);
/* 申请到信号量 */
/* 申请到信号量 */
if (ret == LOS_OK) {
if (ret == LOS_OK) {
LOS_SemPost(g_semId);
LOS_SemPost(g_semId);
...
@@ -150,12 +150,13 @@ VOID ExampleSemTask1(VOID)
...
@@ -150,12 +150,13 @@ VOID ExampleSemTask1(VOID)
}
}
/* 定时时间到,未申请到信号量 */
/* 定时时间到,未申请到信号量 */
if (ret == LOS_ERRNO_SEM_TIMEOUT) {
if (ret == LOS_ERRNO_SEM_TIMEOUT) {
printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n");
d
printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n");
/*永久阻塞模式申请信号量*/
/*永久阻塞模式申请信号量*/
ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER);
ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER);
printf("ExampleSemTask1 wait_forever and get sem g_semId.\n");
d
printf("ExampleSemTask1 wait_forever and get sem g_semId.\n");
if (ret == LOS_OK) {
if (ret == LOS_OK) {
dprintf("ExampleSemTask1 post sem g_semId.\n");
LOS_SemPost(g_semId);
LOS_SemPost(g_semId);
return;
return;
}
}
...
@@ -165,19 +166,18 @@ VOID ExampleSemTask1(VOID)
...
@@ -165,19 +166,18 @@ VOID ExampleSemTask1(VOID)
VOID ExampleSemTask2(VOID)
VOID ExampleSemTask2(VOID)
{
{
UINT32 ret;
UINT32 ret;
printf("ExampleSemTask2 try get sem g_semId wait forever.\n");
d
printf("ExampleSemTask2 try get sem g_semId wait forever.\n");
/* 永久阻塞模式申请信号量 */
/* 永久阻塞模式申请信号量 */
ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER);
ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER);
if (ret == LOS_OK) {
if (ret == LOS_OK) {
printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n");
d
printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n");
}
}
/* 任务休眠20 ticks */
/* 任务休眠20 ticks */
LOS_TaskDelay(20);
LOS_TaskDelay(20);
printf("ExampleSemTask2 post sem g_semId.\n");
d
printf("ExampleSemTask2 post sem g_semId.\n");
/* 释放信号量 */
/* 释放信号量 */
LOS_SemPost(g_semId);
LOS_SemPost(g_semId);
return;
return;
...
@@ -200,10 +200,10 @@ UINT32 ExampleSem(VOID)
...
@@ -200,10 +200,10 @@ UINT32 ExampleSem(VOID)
task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1;
task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1;
task1.pcName = "TestTask1";
task1.pcName = "TestTask1";
task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
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);
ret = LOS_TaskCreate(&g_testTaskId01, &task1);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("task1 create failed .\n");
d
printf("task1 create failed .\n");
return LOS_NOK;
return LOS_NOK;
}
}
...
@@ -212,16 +212,19 @@ UINT32 ExampleSem(VOID)
...
@@ -212,16 +212,19 @@ UINT32 ExampleSem(VOID)
task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2;
task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2;
task2.pcName = "TestTask2";
task2.pcName = "TestTask2";
task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
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);
ret = LOS_TaskCreate(&g_testTaskId02, &task2);
if (ret != LOS_OK) {
if (ret != LOS_OK) {
printf("task2 create failed.\n");
d
printf("task2 create failed.\n");
return LOS_NOK;
return LOS_NOK;
}
}
/* 解锁任务调度 */
/* 解锁任务调度 */
LOS_TaskUnlock();
LOS_TaskUnlock();
/* 任务休眠400 ticks */
LOS_TaskDelay(400);
ret = LOS_SemPost(g_semId);
ret = LOS_SemPost(g_semId);
/* 任务休眠400 ticks */
/* 任务休眠400 ticks */
...
@@ -238,12 +241,13 @@ UINT32 ExampleSem(VOID)
...
@@ -238,12 +241,13 @@ UINT32 ExampleSem(VOID)
编译运行得到的结果为:
编译运行得到的结果为:
```
```
ExampleSemTask2 try get sem g_semId wait forever.
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 try get sem g_semId, timeout 10 ticks.
ExampleSemTask1 timeout and try get sem g_semId wait forever.
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.
ExampleSemTask2 post sem g_semId.
ExampleSemTask1 wait_forever and get sem g_semId.
ExampleSemTask1 wait_forever and get sem g_semId.
ExampleSemTask1 post sem g_semId.
```
```
zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md
浏览文件 @
d3855b41
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
## 功能配置
## 功能配置
LOSCFG_MEM_WATERLINE:开关宏,默认关闭;若需要打开这个功能,可以在配置项中开启“Debug-
>
Enable memory pool waterline or not”。如需获取内存水线,需要打开该配置。
LOSCFG_MEM_WATERLINE:开关宏,默认关闭;若需要打开这个功能,可以在配置项中开启“Debug-
>
Enable
MEM Debug-
>
Enable
memory pool waterline or not”。如需获取内存水线,需要打开该配置。
## 开发指导
## 开发指导
...
@@ -55,8 +55,9 @@ typedef struct {
...
@@ -55,8 +55,9 @@ typedef struct {
**示例代码**
**示例代码**
该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。
本演示代码在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证,在TestTaskEntry中调用验证入口函数MemTest。
代码实现如下:
代码实现如下:
```
c
```
c
#include <stdio.h>
#include <stdio.h>
...
@@ -69,14 +70,14 @@ void MemInfoTaskFunc(void)
...
@@ -69,14 +70,14 @@ void MemInfoTaskFunc(void)
{
{
LOS_MEM_POOL_STATUS
poolStatus
=
{
0
};
LOS_MEM_POOL_STATUS
poolStatus
=
{
0
};
/* pool为要统计信息的内存地址,此处以OS_SYS_MEM_ADDR为例 */
/* pool为要统计信息的内存地址,此处以OS_SYS_MEM_ADDR为例 */
void
*
pool
=
OS_SYS_MEM_ADDR
;
void
*
pool
=
OS_SYS_MEM_ADDR
;
LOS_MemInfoGet
(
pool
,
&
poolStatus
);
LOS_MemInfoGet
(
pool
,
&
poolStatus
);
/* 算出内存池当前的碎片率百分比 */
/* 算出内存池当前的碎片率百分比 */
unsigned
char
fragment
=
100
-
poolStatus
.
maxFreeNodeSize
*
100
/
poolStatus
.
totalFreeSize
;
unsigned
char
fragment
=
100
-
poolStatus
.
maxFreeNodeSize
*
100
/
poolStatus
.
totalFreeSize
;
/* 算出内存池当前的使用率百分比 */
/* 算出内存池当前的使用率百分比 */
unsigned
char
usage
=
LOS_MemTotalUsedGet
(
pool
)
*
100
/
LOS_MemPoolSizeGet
(
pool
);
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
);
d
printf
(
"usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d
\n
"
,
usage
,
fragment
,
poolStatus
.
maxFreeNodeSize
,
poolStatus
.
totalFreeSize
,
poolStatus
.
usageWaterLine
);
}
}
int
MemTest
(
void
)
int
MemTest
(
void
)
...
@@ -90,7 +91,7 @@ int MemTest(void)
...
@@ -90,7 +91,7 @@ int MemTest(void)
taskStatus
.
usTaskPrio
=
10
;
taskStatus
.
usTaskPrio
=
10
;
ret
=
LOS_TaskCreate
(
&
taskID
,
&
taskStatus
);
ret
=
LOS_TaskCreate
(
&
taskID
,
&
taskStatus
);
if
(
ret
!=
LOS_OK
)
{
if
(
ret
!=
LOS_OK
)
{
printf
(
"task create failed
\n
"
);
d
printf
(
"task create failed
\n
"
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
return
LOS_OK
;
return
LOS_OK
;
...
@@ -103,7 +104,7 @@ int MemTest(void)
...
@@ -103,7 +104,7 @@ int MemTest(void)
编译运行输出的结果如下:
编译运行输出的结果如下:
根据实际运行环境,数据会有差异
```
```
usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414
usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414
...
...
zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md
浏览文件 @
d3855b41
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
## 功能配置
## 功能配置
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
\*
)字节数的内存。
2.
LOS_RECORD_LR_CNT:记录的LR层数,默认3层;每层LR消耗sizeof(void
\*
)字节数的内存。
...
@@ -61,8 +61,10 @@ node size LR[0] LR[1] LR[2]
...
@@ -61,8 +61,10 @@ 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
该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试.
代码实现如下:
代码实现如下:
```
c
```
c
...
@@ -71,12 +73,24 @@ node size LR[0] LR[1] LR[2]
...
@@ -71,12 +73,24 @@ node size LR[0] LR[1] LR[2]
#include "los_memory.h"
#include "los_memory.h"
#include "los_config.h"
#include "los_config.h"
#define TEST_NEW_POOL_SIZE 2000
#define TEST_MALLOC_SIZE 8
void
MemLeakTest
(
void
)
void
MemLeakTest
(
void
)
{
{
OsMemUsedNodeShow
(
LOSCFG_SYS_HEAP_ADDR
);
VOID
*
pool
=
NULL
;
void
*
ptr1
=
LOS_MemAlloc
(
LOSCFG_SYS_HEAP_ADDR
,
8
);
void
*
ptr2
=
LOS_MemAlloc
(
LOSCFG_SYS_HEAP_ADDR
,
8
);
/* 由于原内存池分配过多, 为了方便展示, 创建新的内存池 */
OsMemUsedNodeShow
(
LOSCFG_SYS_HEAP_ADDR
);
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
);
}
}
```
```
...
@@ -87,51 +101,50 @@ void MemLeakTest(void)
...
@@ -87,51 +101,50 @@ void MemLeakTest(void)
编译运行输出log如下:
编译运行输出log如下:
```
```
node size LR[0] LR[1] LR[2]
/* 第一次OsMemUsedNodeShow打印,由于该内存池未分配,所以无内存节点 */
0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc
node LR[0] LR[1] LR[2]
0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc
0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e
0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a
/* 第二次OsMemUsedNodeShow打印,有两个新的内存节点 */
0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220
node LR[0] LR[1] LR[2]
0x00402e0d90: 0x004009f040 0x0040037614 0x0040005480
node size LR[0] LR[1] LR[2]
0x00402e0db0: 0x004009f04c 0x0040037614 0x0040005480
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
```
```
对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块:
对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块:
```
```
0x
20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x
00402e0d90: 0x004009f040 0x0040037614 0x0040005480
0x
20003ae0: 0x1d 0x080041ee 0x08000cc2 0x0000000
0
0x
00402e0db0: 0x004009f04c 0x0040037614 0x004000548
0
```
```
部分汇编文件如下:
部分汇编文件如下:
```
```
MemLeakTest:
4009f014: 7d 1e a0 e3 mov r1, #2000
0x80041d4: 0xb510 PUSH {R4, LR}
4009f018: 00 00 90 e5 ldr r0, [r0]
0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart
4009f01c: 67 7a fe eb bl #-398948 <LOS_MemAlloc>
0x80041d8: 0x0020 MOVS R0, R4
4009f020: 7d 1e a0 e3 mov r1, #2000
0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a
4009f024: 00 40 a0 e1 mov r4, r0
0x80041de: 0x2108 MOVS R1, #8
4009f028: c7 79 fe eb bl #-399588 <LOS_MemInit>
0x80041e0: 0x0020 MOVS R0, R4
4009f02c: 04 00 a0 e1 mov r0, r4
0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998
4009f030: 43 78 fe eb bl #-401140 <OsMemUsedNodeShow>
0x80041e6: 0x2108 MOVS R1, #8
4009f034: 04 00 a0 e1 mov r0, r4
0x80041e8: 0x0020 MOVS R0, R4
4009f038: 08 10 a0 e3 mov r1, #8
0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998
4009f03c: 5f 7a fe eb bl #-398980 <LOS_MemAlloc>
0x80041ee: 0x0020 MOVS R0, R4
4009f040: 04 00 a0 e1 mov r0, r4
0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a
4009f044: 08 10 a0 e3 mov r1, #8
0x80041f4: 0xbd10 POP {R4, PC}
4009f048: 5c 7a fe eb bl #-398992 <LOS_MemAlloc>
0x80041f6: 0x0000 MOVS R0, R0
4009f04c: 04 00 a0 e1 mov r0, r4
4009f050: 3b 78 fe eb bl #-401172 <OsMemUsedNodeShow>
4009f054: 3c 00 9f e5 ldr r0, [pc, #60]
4009f058: 40 b8 fe eb bl #-335616 <dprintf>
4009f05c: 04 00 a0 e1 mov r0, r4
4009f060: 2c 7a fe eb bl #-399184 <LOS_MemDeInit>
```
```
其中,通过查找0x
080041ee
,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。
其中,通过查找0x
4009f040
,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。
zh-cn/device-dev/kernel/kernel-
mini-memory
-perf.md
→
zh-cn/device-dev/kernel/kernel-
small-debug
-perf.md
浏览文件 @
d3855b41
...
@@ -17,9 +17,6 @@ Perf提供2种工作模式,计数模式和采样模式。
...
@@ -17,9 +17,6 @@ Perf提供2种工作模式,计数模式和采样模式。
## 接口说明
## 接口说明
### 内核态
OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细信息可以查看
[
API
](
https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_perf.h
)
参考。
OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细信息可以查看
[
API
](
https://gitee.com/openharmony/kernel_liteos_a/blob/master/kernel/include/los_perf.h
)
参考。
**表1**
Perf模块接口说明
**表1**
Perf模块接口说明
...
@@ -63,30 +60,6 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细
...
@@ -63,30 +60,6 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细
刷cache接口视具体的平台自行配置。
刷cache接口视具体的平台自行配置。
### 用户态
新增perf字符设备,位于"/dev/perf",通过对设备节点的read
\w
rite
\i
octl,实现用户态perf的读写和控制:
-
read: 用户态读取perf记录数据
-
write: 用户态采样事件配置
-
ioctl: 用户态Perf控制操作,包括
```
c
#define PERF_IOC_MAGIC 'T'
#define PERF_START _IO(PERF_IOC_MAGIC, 1)
#define PERF_STOP _IO(PERF_IOC_MAGIC, 2)
```
分别对应Perf启动(LOS_PerfStart)、停止(LOS_PerfStop)
具体的使用方法参见
[
用户态编程实例
](
#用户态编程实例
)
。
## 开发指导
## 开发指导
...
@@ -140,14 +113,33 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细
...
@@ -140,14 +113,33 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细
#### 内核态示例代码
#### 内核态示例代码
前提条件:在menuconfig菜单中完成perf模块的配置。
前提条件:在menuconfig菜单中完成perf模块的配置
, 并勾选Enable Hook Feature,Enable Software Events for Sampling
。
该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试
。
为方便学习,本演示代码直接在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证即可
。
实例代码如下:
实例代码如下:
```
c
```
c
#include "los_perf.h"
#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
)
STATIC
VOID
OsPrintBuff
(
const
CHAR
*
buf
,
UINT32
num
)
{
{
UINT32
i
=
0
;
UINT32
i
=
0
;
...
@@ -167,12 +159,18 @@ STATIC VOID perfTestHwEvent(VOID)
...
@@ -167,12 +159,18 @@ STATIC VOID perfTestHwEvent(VOID)
UINT32
ret
;
UINT32
ret
;
CHAR
*
buf
=
NULL
;
CHAR
*
buf
=
NULL
;
UINT32
len
;
UINT32
len
;
//LOS_PerfInit(NULL, 0);
PerfConfigAttr
attr
=
{
PerfConfigAttr
attr
=
{
.
eventsCfg
=
{
.
eventsCfg
=
{
.
type
=
PERF_EVENT_TYPE_
H
W
,
.
type
=
PERF_EVENT_TYPE_
S
W
,
.
events
=
{
.
events
=
{
[
0
]
=
{
PERF_COUNT_HW_CPU_CYCLES
,
0xFFFF
},
[
0
]
=
{
PERF_COUNT_SW_TASK_SWITCH
,
0xff
},
/* 抓取调度 */
[
1
]
=
{
PERF_COUNT_HW_BRANCH_INSTRUCTIONS
,
0xFFFFFF00
},
[
1
]
=
{
PERF_COUNT_SW_MEM_ALLOC
,
0xff
},
/* 抓取内存分配 */
PERF_COUNT_SW_TASK_SWITCH
},
},
.
eventsNr
=
2
,
.
eventsNr
=
2
,
.
predivided
=
1
,
/* cycle counter increase every 64 cycles */
.
predivided
=
1
,
/* cycle counter increase every 64 cycles */
...
@@ -207,20 +205,20 @@ STATIC VOID perfTestHwEvent(VOID)
...
@@ -207,20 +205,20 @@ STATIC VOID perfTestHwEvent(VOID)
OsPrintBuff
(
buf
,
len
);
/* print data */
OsPrintBuff
(
buf
,
len
);
/* print data */
(
VOID
)
LOS_MemFree
(
m_aucSysMem1
,
buf
);
(
VOID
)
LOS_MemFree
(
m_aucSysMem1
,
buf
);
}
}
UINT32
Example_Perf_test
(
VOID
)
UINT32
Example_Perf_test
(
VOID
)
{
{
UINT32
ret
;
UINT32
ret
;
TSK_INIT_PARAM_S
perfTestTask
;
TSK_INIT_PARAM_S
perfTestTask
=
{
0
};
UINT32
taskID
;
/* 创建用于perf测试的任务 */
/* 创建用于perf测试的任务 */
memset
(
&
perfTestTask
,
0
,
sizeof
(
TSK_INIT_PARAM_S
));
perfTestTask
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
perfTestHwEvent
;
perfTestTask
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
perfTestHwEvent
;
perfTestTask
.
pcName
=
"TestPerfTsk"
;
/* 测试任务名称 */
perfTestTask
.
pcName
=
"TestPerfTsk"
;
/* 测试任务名称 */
perfTestTask
.
uwStackSize
=
0x
8
00
;
// 0x8000: perf test task stack size
perfTestTask
.
uwStackSize
=
0x
10
00
;
// 0x8000: perf test task stack size
perfTestTask
.
usTaskPrio
=
5
;
// 5: perf test task priority
perfTestTask
.
usTaskPrio
=
5
;
// 5: perf test task priority
perfTestTask
.
uwResved
=
LOS_TASK_STATUS_DETACHED
;
ret
=
LOS_TaskCreate
(
&
taskID
,
&
perfTestTask
);
ret
=
LOS_TaskCreate
(
&
g_perfTestTaskId
,
&
perfTestTask
);
if
(
ret
!=
LOS_OK
)
{
if
(
ret
!=
LOS_OK
)
{
PRINT_ERR
(
"PerfTestTask create failed.
\n
"
);
PRINT_ERR
(
"PerfTestTask create failed.
0x%x
\n
"
,
ret
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
return
LOS_OK
;
return
LOS_OK
;
...
@@ -234,13 +232,29 @@ LOS_MODULE_INIT(perfTestHwEvent, LOS_INIT_LEVEL_KMOD_EXTENDED);
...
@@ -234,13 +232,29 @@ LOS_MODULE_INIT(perfTestHwEvent, LOS_INIT_LEVEL_KMOD_EXTENDED);
输出结果如下:
输出结果如下:
```
```
--------count mode----------
type: 2
[EMG] [cycles] eventType: 0xff: 5466989440
events[0]: 1, 0xff
[EMG] [branches] eventType: 0xc: 602166445
events[1]: 3, 0xff
------- sample mode----------
predivided: 1
[EMG] dump section data, addr: 0x8000000 length: 0x800000
sampleType: 0x60
num: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ...
needSample: 0
hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08 00 00 00 6b 65 72 6e 65 6c 00 00 01 00 00 00 cc 55 30 40 08 00 00 00 6b 65 72 6e 65 6c 00 00
------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后会打印:
-
针对计数模式,系统在perf stop后会打印:
...
@@ -254,184 +268,3 @@ hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08
...
@@ -254,184 +268,3 @@ hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08
用户可以通过JTAG口导出该片内存,再使用IDE线下工具解析。
用户可以通过JTAG口导出该片内存,再使用IDE线下工具解析。
或者通过LOS_PerfDataRead将数据读到指定地址,进行查看或进一步处理。示例中OsPrintBuff为测试接口,其按字节打印Read到的采样数据,num表示第几个字节,hex表示该字节中的数值。
或者通过LOS_PerfDataRead将数据读到指定地址,进行查看或进一步处理。示例中OsPrintBuff为测试接口,其按字节打印Read到的采样数据,num表示第几个字节,hex表示该字节中的数值。
### 用户态开发流程
通过在menuconfig配置"Driver-
>
Enable PERF DRIVER",开启Perf驱动。该配置仅在内核Enable Perf Feature后,才可在Driver的选项中可见。
1.
打开“/dev/perf”字符文件,进行读写和IOCTL操作;
2.
系统提供用户态的perf命令,该命令位于/bin目录下,cd bin 后可执行如下命令:
-
./perf start [id] 启动perf采样, id 为可选项,默认值为0
-
./perf stop 停止perf采样
-
./perf read
<
nBytes
>
从采样缓冲区中读取nBytes数据并打印内容
-
./perf list 罗列-e支持的具体事件
-
./perf stat/record [option]
<
command
>
计数/采样模式命令
-
option可选如下:
-
-e,配置采样事件。可使用./perf list 中罗列的同类型事件。
-
-p,配置事件采样周期。
-
-o,指定perf采样数据结果保存的文件路径。
-
-t,任务Id过滤(白名单),只采取指定任务中的上下文。如果不指定改参数,则默认采集所有的任务。
-
-s,配置采样的具体上下文类型,可查阅los_perf.h中定义的PerfSampleType。
-
-P,进程Id过滤(白名单),只采取指定进程中的上下文。如果不指定改参数,则默认采集所有进程。
-
-d,是否进行分频(事件每发生64次累计+1),该选项仅在硬件cycle事件上生效。
-
command 为待统计的子程序。
用户态命令行的典型使用方法如下:
./perf list 查看可使用的事件列表, 输出如下:
```
cycles [Hardware event]
instruction [Hardware event]
dcache [Hardware event]
dcache-miss [Hardware event]
icache [Hardware event]
icache-miss [Hardware event]
branch [Hardware event]
branch-miss [Hardware event]
clock [Timed event]
task-switch [Software event]
irq-in [Software event]
mem-alloc [Software event]
mux-pend [Software event]
```
./perf stat -e cycles os_dump, 输出如下:
```
type: 0
events[0]: 255, 0xffff
predivided: 0
sampleType: 0x0
needSample: 0
usage os_dump [--help | -l | SERVICE]
--help: shows this help
-l: only list services, do not dump them
SERVICE: dumps only service SERVICE
time used: 0.058000(s)
[cycles] eventType: 0xff [core 0]: 21720647
[cycles] eventType: 0xff [core 1]: 13583830
```
./perf record -e cycles os_dump, 输出如下:
```
type: 0
events[0]: 255, 0xffff
predivided: 0
sampleType: 0x60
needSample: 1
usage os_dump [--help | -l | SERVICE]
--help: shows this help
-l: only list services, do not dump them
SERVICE: dumps only service SERVICE
dump perf data, addr: 0x408643d8 length: 0x5000
time used: 0.059000(s)
save perf data success at /storage/data/perf.data
```
>  **说明:**
> 在进行./perf stat/record命令后,用户可多次执行./perf start 和 ./perf stop进行采样, 采样的事件配置为最近一次执行./perfstat/record 中设置的参数。
#### 用户态编程实例
本实例实现如下功能:
1.
打开perf字符设备。
2.
写perf配置事件。
3.
启动perf。
4.
停止perf。
5.
读取perf采样数据。
#### 用户态示例代码
实例代码如下:
```
c
#include "fcntl.h"
#include "user_copy.h"
#include "sys/ioctl.h"
#include "fs/driver.h"
#include "los_dev_perf.h"
#include "los_perf.h"
#include "los_init.h"
/* perf ioctl */
#define PERF_IOC_MAGIC 'T'
#define PERF_START _IO(PERF_IOC_MAGIC, 1)
#define PERF_STOP _IO(PERF_IOC_MAGIC, 2)
int
main
(
int
argc
,
char
**
argv
)
{
char
*
buf
=
NULL
;
ssize_t
len
;
int
fd
=
open
(
"/dev/perf"
,
O_RDWR
);
if
(
fd
==
-
1
)
{
printf
(
"Perf open failed.
\n
"
);
exit
(
EXIT_FAILURE
);
}
PerfConfigAttr
attr
=
{
.
eventsCfg
=
{
#ifdef LOSCFG_PERF_HW_PMU
.
type
=
PERF_EVENT_TYPE_HW
,
.
events
=
{
[
0
]
=
{
PERF_COUNT_HW_CPU_CYCLES
,
0xFFFF
},
},
#elif defined LOSCFG_PERF_TIMED_PMU
.
type
=
PERF_EVENT_TYPE_TIMED
,
.
events
=
{
[
0
]
=
{
PERF_COUNT_CPU_CLOCK
,
100
},
},
#elif defined LOSCFG_PERF_SW_PMU
.
type
=
PERF_EVENT_TYPE_SW
,
.
events
=
{
[
0
]
=
{
PERF_COUNT_SW_TASK_SWITCH
,
1
},
},
#endif
.
eventsNr
=
1
,
/* 1 event */
.
predivided
=
0
,
},
.
taskIds
=
{
0
},
.
taskIdsNr
=
0
,
.
processIds
=
{
0
},
.
processIdsNr
=
0
,
.
needSample
=
1
,
.
sampleType
=
PERF_RECORD_IP
|
PERF_RECORD_CALLCHAIN
,
};
(
void
)
write
(
fd
,
&
attr
,
sizeof
(
PerfConfigAttr
));
/* perf config */
ioctl
(
fd
,
PERF_START
,
NULL
);
/* perf start */
test
();
ioctl
(
fd
,
PERF_STOP
,
NULL
);
/* perf stop */
buf
=
(
char
*
)
malloc
(
LOSCFG_PERF_BUFFER_SIZE
);
if
(
buf
==
NULL
)
{
printf
(
"no memory for read perf 0x%x
\n
"
,
LOSCFG_PERF_BUFFER_SIZE
);
return
-
1
;
}
len
=
read
(
fd
,
buf
,
LOSCFG_PERF_BUFFER_SIZE
);
OsPrintBuff
(
buf
,
len
);
/* print data */
free
(
buf
);
close
(
fd
);
return
0
;
}
```
#### 用户态结果验证
输出结果如下
```
[EMG] dump section data, addr: 0x8000000 length: 0x800000
num: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ...
hex: 00 ef ef ef 00 00 00 00 14 00 00 00 60 00 00 00 00 00 00 00 70 88 36 40 08 00 00 00 6b 65 72 6e 65 6c 00 00 01 00 00 00 cc 55 30 40 08 00 00 00 6b 65 72 6e 65 6c 00 00
```
zh-cn/device-dev/kernel/kernel-small-debug-process-cpu.md
浏览文件 @
d3855b41
...
@@ -103,7 +103,7 @@ CPU占用率的典型开发流程:
...
@@ -103,7 +103,7 @@ CPU占用率的典型开发流程:
**示例代码**
**示例代码**
该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试
。
本演示代码在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证,在TestTaskEntry中调用验证入口函数CpupTest
。
代码实现如下:
代码实现如下:
...
@@ -114,12 +114,13 @@ CPU占用率的典型开发流程:
...
@@ -114,12 +114,13 @@ CPU占用率的典型开发流程:
UINT32
g_cpuTestTaskID
;
UINT32
g_cpuTestTaskID
;
VOID
ExampleCpup
(
VOID
)
VOID
ExampleCpup
(
VOID
)
{
{
printf
(
"entry cpup test example
\n
"
);
int
i
=
0
;
while
(
1
)
{
dprintf
(
"entry cpup test example
\n
"
);
for
(
i
=
0
;
i
<
10
;
i
++
)
{
usleep
(
100
);
// 100: delay for 100ms
usleep
(
100
);
// 100: delay for 100ms
}
}
}
}
UINT32
It
CpupTest
(
VOID
)
UINT32
CpupTest
(
VOID
)
{
{
UINT32
ret
;
UINT32
ret
;
UINT32
cpupUse
;
UINT32
cpupUse
;
...
@@ -138,12 +139,12 @@ UINT32 ItCpupTest(VOID)
...
@@ -138,12 +139,12 @@ UINT32 ItCpupTest(VOID)
usleep
(
100
);
// 100: delay for 100ms
usleep
(
100
);
// 100: delay for 100ms
/* 获取当前系统历史CPU占用率 */
/* 获取当前系统历史CPU占用率 */
cpupUse
=
LOS_HistorySysCpuUsage
(
CPU
_LESS_THAN_1
S
);
cpupUse
=
LOS_HistorySysCpuUsage
(
CPU
P_LAST_ONE_SECOND
S
);
printf
(
"the history system cpu usage in all time:%u.%u
\n
"
,
d
printf
(
"the history system cpu usage in all time:%u.%u
\n
"
,
cpupUse
/
LOS_CPUP_PRECISION_MULT
,
cpupUse
%
LOS_CPUP_PRECISION_MULT
);
cpupUse
/
LOS_CPUP_PRECISION_MULT
,
cpupUse
%
LOS_CPUP_PRECISION_MULT
);
/* 获取指定任务的CPU占用率,该测试例程中指定的任务为以上创建的cpup测试任务 */
/* 获取指定任务的CPU占用率,该测试例程中指定的任务为以上创建的cpup测试任务 */
cpupUse
=
LOS_HistoryTaskCpuUsage
(
g_cpuTestTaskID
,
CPU
_LESS_THAN_1
S
);
cpupUse
=
LOS_HistoryTaskCpuUsage
(
g_cpuTestTaskID
,
CPU
P_LAST_ONE_SECOND
S
);
printf
(
"cpu usage of the cpupTestTask in all time:
\n
TaskID: %d
\n
usage: %u.%u
\n
"
,
d
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
);
g_cpuTestTaskID
,
cpupUse
/
LOS_CPUP_PRECISION_MULT
,
cpupUse
%
LOS_CPUP_PRECISION_MULT
);
return
LOS_OK
;
return
LOS_OK
;
}
}
...
@@ -158,4 +159,6 @@ UINT32 ItCpupTest(VOID)
...
@@ -158,4 +159,6 @@ UINT32 ItCpupTest(VOID)
entry cpup test example
entry cpup test example
the history system cpu usage in all time: 3.0
the history system cpu usage in all time: 3.0
cpu usage of the cpupTestTask in all time: TaskID:10 usage: 0.0
cpu usage of the cpupTestTask in all time: TaskID:10 usage: 0.0
根据实际运行环境,打印会有差异
```
```
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
浏览文件 @
d3855b41
...
@@ -34,38 +34,35 @@
...
@@ -34,38 +34,35 @@
新增一个内核模块,需要在内核初始化时进行该模块的初始化,则通过内核启动框架将该模块的初始化函数注册进内核启动流程中。
新增一个内核模块,需要在内核初始化时进行该模块的初始化,则通过内核启动框架将该模块的初始化函数注册进内核启动流程中。
为方便学习,本演示代码直接在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证即可。
**示例代码**
**示例代码**
```
c
```
c
/* 内核启动框架头文件 */
/* 内核启动框架头文件 */
#include "los_init.h"
#include "los_init.h"
......
/* 新增模块的初始化函数 */
/* 新增模块的初始化函数 */
unsigned
int
OsSampleModInit
(
void
)
unsigned
int
OsSampleModInit
(
void
)
{
{
PRINTK
(
"OsSampleModInit SUCCESS!
\n
"
);
PRINTK
(
"OsSampleModInit SUCCESS!
\n
"
);
......
}
}
......
/* 在启动框架的目标层级中注册新增模块 */
/* 在启动框架的目标层级中注册新增模块 */
LOS_MODULE_INIT
(
OsSampleModInit
,
LOS_INIT_LEVEL_KMOD_EXTENDED
);
LOS_MODULE_INIT
(
OsSampleModInit
,
LOS_INIT_LEVEL_KMOD_EXTENDED
);
```
```
**结果验证**
**结果验证**
```
```
main core booting up...
main core booting up...
/* 根据实际运行环境,过程打印会有差异 */
......
/* 打印测试代码新增模块初始化函数 */
OsSampleModInit SUCCESS!
OsSampleModInit SUCCESS!
releasing 1 secondary cores
cpu 1 entering scheduler
cpu 0 entering scheduler
```
```
...
...
zh-cn/device-dev/kernel/kernel-small-start-user.md
浏览文件 @
d3855b41
...
@@ -27,7 +27,7 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
...
@@ -27,7 +27,7 @@ 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。
> 上述启动代码
已
在 kernel/liteos_a/kernel/user/src/los_user_init.c 中,g_initPath 根据启动设置的不同,其值为 /dev/shm/init 或 /bin/init。
系统启动阶段,OsUserInitProcess启动init进程。具体过程如下:
系统启动阶段,OsUserInitProcess启动init进程。具体过程如下:
...
...
zh-cn/device-dev/website.md
浏览文件 @
d3855b41
...
@@ -290,7 +290,7 @@
...
@@ -290,7 +290,7 @@
-
[
魔法键使用方法
](
kernel/kernel-small-debug-shell-magickey.md
)
-
[
魔法键使用方法
](
kernel/kernel-small-debug-shell-magickey.md
)
-
[
用户态异常信息说明
](
kernel/kernel-small-debug-shell-error.md
)
-
[
用户态异常信息说明
](
kernel/kernel-small-debug-shell-error.md
)
-
[
Trace调测
](
kernel/kernel-small-debug-trace.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
)
-
[
LMS调测
](
kernel/kernel-small-memory-lms.md
)
-
[
进程调测
](
kernel/kernel-small-debug-process-cpu.md
)
-
[
进程调测
](
kernel/kernel-small-debug-process-cpu.md
)
-
内核态内存调测
-
内核态内存调测
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录