Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
68cead99
D
Docs
项目概览
OpenHarmony
/
Docs
大约 1 年 前同步成功
通知
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看板
未验证
提交
68cead99
编写于
1月 18, 2023
作者:
O
openharmony_ci
提交者:
Gitee
1月 18, 2023
浏览文件
操作
浏览文件
下载
差异文件
!13578 A核资料描述和示例代码问题修改
Merge pull request !13578 from wangchen/0113_docs_a
上级
66b2c7b1
d3855b41
变更
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
浏览文件 @
68cead99
...
...
@@ -136,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
)
-
内核态内存调测
...
...
zh-cn/device-dev/kernel/kernel-small-apx-library.md
浏览文件 @
68cead99
...
...
@@ -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
#include <unistd.h>
#include <pthread.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define THREAD_NUM 3
int g_startNum = 0; /* 启动的线程数 */
int g_wakenNum = 0; /* 唤醒的线程数 */
...
...
@@ -48,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();
...
...
@@ -59,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);
d
printf("ERROR:take mutex lock failed, error code is %d!\n", rc);
goto EXIT;
}
...
...
@@ -69,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);
d
printf("ERROR: pthread condition wait failed, error code is %d!\n", rc);
(void)pthread_mutex_unlock(&g_td.mutex);
goto EXIT;
}
...
...
@@ -77,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");
d
printf("ERROR: mutex gets an abnormal lock!\n");
goto EXIT;
}
...
...
@@ -87,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);
d
printf("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];
...
...
@@ -102,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);
d
printf("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);
d
printf("ERROR: pthread condition init failed, error code is %d!\n", rc);
goto ERROROUT;
}
...
...
@@ -117,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);
d
printf("ERROR: pthread create failed, error code is %d!\n", rc);
goto ERROROUT;
}
}
dprintf("pthread_create ok\n");
/* 等待所有子线程都完成mutex锁的获取 */
while (g_startNum < THREAD_NUM) {
...
...
@@ -130,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);
d
printf("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);
d
printf("ERROR: mutex unlock failed, error code is %d!\n", rc);
goto ERROROUT;
}
...
...
@@ -145,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);
d
printf("ERROR: pthread condition failed, error code is %d!\n", rc);
goto ERROROUT;
}
}
...
...
@@ -154,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);
d
printf("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);
d
printf("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);
d
printf("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标准库差异
...
...
@@ -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)。
其中,参数fd的生命周期实现与Linux glibc存在差异。具体体现在,glibc在成功调用mmap进行映射后,可以立即释放fd句柄。在OpenHarmony内核中,不允许用户在映射成功后立即关闭相关fd,只允许在取消映射munmap后再进行fd的close操作。如果用户不进行fd的close操作,操作系统将在进程退出时对该fd进行回收。
**h2代码举例**
**代码举例**
Linux目前支持的情况如下:
```
int main(int argc, char *argv[])
{
...
...
@@ -247,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);
}
...
...
@@ -255,7 +235,7 @@ int main(int argc, char *argv[])
OpenHarmony支持的情况如下:
```
int main(int argc, char *argv[])
{
...
...
@@ -274,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);
}
```
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-event.md
浏览文件 @
68cead99
...
...
@@ -31,7 +31,7 @@ OpenHarmony LiteOS-A的事件模块提供的事件,具有如下特点:
### 事件控制块
```
/**
* 事件控制块数据结构
...
...
@@ -144,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);
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) {
printf("Example_Event,read event :0x%x\n", event);
d
printf("Example_Event,read event :0x%x\n", event);
} else {
printf("Example_Event,read event timeout\n");
d
printf("Example_Event,read event timeout\n");
}
}
...
...
@@ -170,7 +170,7 @@ UINT32 Example_EventEntry(VOID)
/* 事件初始化 */
ret = LOS_EventInit(&g_exampleEvent);
if (ret != LOS_OK) {
printf("init event failed .\n");
d
printf("init event failed .\n");
return -1;
}
...
...
@@ -182,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");
d
printf("task create failed.\n");
return LOS_NOK;
}
/* 写g_testTaskId 等待事件 */
printf("Example_TaskEntry write event.\n");
d
printf("Example_TaskEntry write event.\n");
ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT);
if (ret != LOS_OK) {
printf("event write failed.\n");
d
printf("event write failed.\n");
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);
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;
}
...
...
@@ -216,7 +209,7 @@ UINT32 Example_EventEntry(VOID)
编译运行得到的结果为:
```
Example_Event wait event 0x1
Example_TaskEntry write event.
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-mutex.md
浏览文件 @
68cead99
...
...
@@ -104,13 +104,13 @@
本演示代码在./kernel/liteos_a/testsuites/kernel/src/osTest.c中编译验证,在TestTaskEntry中调用验证入口函数Example_MutexEntry。
示例代码如下:
```
#include <string.h>
#include "los_mux.h"
/* 互斥锁 */
LosMux g_testMux;
LosMux g_testMu
te
x;
/* 任务ID */
UINT32 g_testTaskId01;
UINT32 g_testTaskId02;
...
...
@@ -118,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");
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) {
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;
}
if (ret == LOS_ETIMEDOUT
) {
printf("task1 timeout and try to get mutex, wait forever.\n");
/* 申请互斥锁 */
ret = LOS_MuxLock(&g_testMu
x, LOS_WAIT_FOREVER);
if (ret == LOS_OK) {
printf("task1 wait forever, get mutex g_testMux.\n");
/* 释放互斥锁 */
LOS_MuxUnlock(&g_testMu
x);
/* 删除互斥锁 */
LOS_MuxDestroy(&g_testMu
x);
printf("task1 post and delete mutex g_testMux.\n");
return;
}
}
if (ret == LOS_ETIMEDOUT) {
d
printf("task1 timeout and try to get mutex, wait forever.\n");
/* 申请互斥锁 */
ret = LOS_MuxLock(&g_testMute
x, LOS_WAIT_FOREVER);
if (ret == LOS_OK) {
d
printf("task1 wait forever, get mutex g_testMux.\n");
/* 释放互斥锁 */
LOS_MuxUnlock(&g_testMute
x);
/* 删除互斥锁 */
LOS_MuxDestroy(&g_testMute
x);
d
printf("task1 post and delete mutex g_testMux.\n");
return;
}
}
return;
}
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 */
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;
}
...
...
@@ -170,7 +171,7 @@ UINT32 Example_MutexEntry(VOID)
TSK_INIT_PARAM_S task2;
/* 初始化互斥锁 */
LOS_MuxInit(&g_testMux, NULL);
LOS_MuxInit(&g_testMu
te
x, NULL);
/* 锁任务调度 */
LOS_TaskLock();
...
...
@@ -183,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");
d
printf("task1 create failed.\n");
return LOS_NOK;
}
...
...
@@ -195,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");
d
printf("task2 create failed.\n");
return LOS_NOK;
}
...
...
@@ -210,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.
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-queue.md
浏览文件 @
68cead99
...
...
@@ -31,7 +31,7 @@
### 队列控制块
```
/**
* 队列控制块数据结构
...
...
@@ -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)
ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0);
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)
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);
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);
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)
{
printf("start queue example\n");
d
printf("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;
...
...
@@ -197,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;
}
...
...
@@ -205,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;
}
```
...
...
@@ -225,9 +230,9 @@ UINT32 ExampleQueue(VOID)
编译运行得到的结果为:
```
start
test
example
start
queue
example
create the queue success!
recv message: test message
delete the queue success!
...
...
zh-cn/device-dev/kernel/kernel-small-basic-trans-semaphore.md
浏览文件 @
68cead99
...
...
@@ -22,7 +22,7 @@
**信号量控制块**
```
/**
* 信号量控制块数据结构
...
...
@@ -129,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;
...
...
@@ -138,11 +139,10 @@ VOID ExampleSemTask1(VOID)
{
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 */
ret = LOS_SemPend(g_semId, 10);
/* 申请到信号量 */
if (ret == LOS_OK) {
LOS_SemPost(g_semId);
...
...
@@ -150,12 +150,13 @@ VOID ExampleSemTask1(VOID)
}
/* 定时时间到,未申请到信号量 */
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);
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) {
dprintf("ExampleSemTask1 post sem g_semId.\n");
LOS_SemPost(g_semId);
return;
}
...
...
@@ -165,19 +166,18 @@ VOID ExampleSemTask1(VOID)
VOID ExampleSemTask2(VOID)
{
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);
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 */
LOS_TaskDelay(20);
printf("ExampleSemTask2 post sem g_semId.\n");
d
printf("ExampleSemTask2 post sem g_semId.\n");
/* 释放信号量 */
LOS_SemPost(g_semId);
return;
...
...
@@ -200,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");
d
printf("task1 create failed .\n");
return LOS_NOK;
}
...
...
@@ -212,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");
d
printf("task2 create failed.\n");
return LOS_NOK;
}
/* 解锁任务调度 */
LOS_TaskUnlock();
/* 任务休眠400 ticks */
LOS_TaskDelay(400);
ret = LOS_SemPost(g_semId);
/* 任务休眠400 ticks */
...
...
@@ -238,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.
```
zh-cn/device-dev/kernel/kernel-small-debug-memory-info.md
浏览文件 @
68cead99
...
...
@@ -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 {
**示例代码**
该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。
代码实现如下:
本演示代码在 . kernel /liteos_a/testsuites /kernel /src /osTest.c中编译验证,在TestTaskEntry中调用验证入口函数MemTest。
代码实现如下:
```
c
#include <stdio.h>
...
...
@@ -69,14 +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
);
d
printf
(
"usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d
\n
"
,
usage
,
fragment
,
poolStatus
.
maxFreeNodeSize
,
poolStatus
.
totalFreeSize
,
poolStatus
.
usageWaterLine
);
}
int
MemTest
(
void
)
...
...
@@ -90,7 +91,7 @@ int MemTest(void)
taskStatus
.
usTaskPrio
=
10
;
ret
=
LOS_TaskCreate
(
&
taskID
,
&
taskStatus
);
if
(
ret
!=
LOS_OK
)
{
printf
(
"task create failed
\n
"
);
d
printf
(
"task create failed
\n
"
);
return
LOS_NOK
;
}
return
LOS_OK
;
...
...
@@ -103,7 +104,7 @@ int MemTest(void)
编译运行输出的结果如下:
根据实际运行环境,数据会有差异
```
usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414
...
...
zh-cn/device-dev/kernel/kernel-small-debug-memory-leak.md
浏览文件 @
68cead99
...
...
@@ -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
\*
)字节数的内存。
...
...
@@ -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
...
...
@@ -71,12 +73,24 @@ node size LR[0] LR[1] LR[2]
#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
);
}
```
...
...
@@ -87,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,差异如下,这些内存节点就是疑似泄漏的内存块:
```
0x
20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6
0x
20003ae0: 0x1d 0x080041ee 0x08000cc2 0x0000000
0
0x
00402e0d90: 0x004009f040 0x0040037614 0x0040005480
0x
00402e0db0: 0x004009f04c 0x0040037614 0x004000548
0
```
部分汇编文件如下:
```
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 <LOS_MemAlloc>
4009f020: 7d 1e a0 e3 mov r1, #2000
4009f024: 00 40 a0 e1 mov r4, r0
4009f028: c7 79 fe eb bl #-399588 <LOS_MemInit>
4009f02c: 04 00 a0 e1 mov r0, r4
4009f030: 43 78 fe eb bl #-401140 <OsMemUsedNodeShow>
4009f034: 04 00 a0 e1 mov r0, r4
4009f038: 08 10 a0 e3 mov r1, #8
4009f03c: 5f 7a fe eb bl #-398980 <LOS_MemAlloc>
4009f040: 04 00 a0 e1 mov r0, r4
4009f044: 08 10 a0 e3 mov r1, #8
4009f048: 5c 7a fe eb bl #-398992 <LOS_MemAlloc>
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
浏览文件 @
68cead99
...
...
@@ -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
)
参考。
**表1**
Perf模块接口说明
...
...
@@ -63,30 +60,6 @@ OpenHarmony LiteOS-A内核的Perf模块提供下面几种功能,接口详细
刷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模块提供下面几种功能,接口详细
#### 内核态示例代码
前提条件:在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
#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
;
...
...
@@ -167,12 +159,18 @@ STATIC VOID perfTestHwEvent(VOID)
UINT32
ret
;
CHAR
*
buf
=
NULL
;
UINT32
len
;
//LOS_PerfInit(NULL, 0);
PerfConfigAttr
attr
=
{
.
eventsCfg
=
{
.
type
=
PERF_EVENT_TYPE_
H
W
,
.
type
=
PERF_EVENT_TYPE_
S
W
,
.
events
=
{
[
0
]
=
{
PERF_COUNT_HW_CPU_CYCLES
,
0xFFFF
},
[
1
]
=
{
PERF_COUNT_HW_BRANCH_INSTRUCTIONS
,
0xFFFFFF00
},
[
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 */
...
...
@@ -207,20 +205,20 @@ STATIC VOID perfTestHwEvent(VOID)
OsPrintBuff
(
buf
,
len
);
/* print data */
(
VOID
)
LOS_MemFree
(
m_aucSysMem1
,
buf
);
}
UINT32
Example_Perf_test
(
VOID
)
{
UINT32
ret
;
TSK_INIT_PARAM_S
perfTestTask
;
TSK_INIT_PARAM_S
perfTestTask
=
{
0
};
UINT32
taskID
;
/* 创建用于perf测试的任务 */
memset
(
&
perfTestTask
,
0
,
sizeof
(
TSK_INIT_PARAM_S
));
perfTestTask
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
perfTestHwEvent
;
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
.
uwResved
=
LOS_TASK_STATUS_DETACHED
;
ret
=
LOS_TaskCreate
(
&
g_perfTestTaskId
,
&
perfTestTask
);
ret
=
LOS_TaskCreate
(
&
taskID
,
&
perfTestTask
);
if
(
ret
!=
LOS_OK
)
{
PRINT_ERR
(
"PerfTestTask create failed.
\n
"
);
PRINT_ERR
(
"PerfTestTask create failed.
0x%x
\n
"
,
ret
);
return
LOS_NOK
;
}
return
LOS_OK
;
...
...
@@ -234,13 +232,29 @@ LOS_MODULE_INIT(perfTestHwEvent, LOS_INIT_LEVEL_KMOD_EXTENDED);
输出结果如下:
```
--------count mode----------
[EMG] [cycles] eventType: 0xff: 5466989440
[EMG] [branches] eventType: 0xc: 602166445
------- sample mode----------
[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
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后会打印:
...
...
@@ -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线下工具解析。
或者通过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
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 在进行./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
浏览文件 @
68cead99
...
...
@@ -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占用率的典型开发流程:
UINT32
g_cpuTestTaskID
;
VOID
ExampleCpup
(
VOID
)
{
printf
(
"entry cpup test example
\n
"
);
while
(
1
)
{
int
i
=
0
;
dprintf
(
"entry cpup test example
\n
"
);
for
(
i
=
0
;
i
<
10
;
i
++
)
{
usleep
(
100
);
// 100: delay for 100ms
}
}
UINT32
It
CpupTest
(
VOID
)
UINT32
CpupTest
(
VOID
)
{
UINT32
ret
;
UINT32
cpupUse
;
...
...
@@ -138,12 +139,12 @@ UINT32 ItCpupTest(VOID)
usleep
(
100
);
// 100: delay for 100ms
/* 获取当前系统历史CPU占用率 */
cpupUse
=
LOS_HistorySysCpuUsage
(
CPU
_LESS_THAN_1
S
);
printf
(
"the history system cpu usage in all time:%u.%u
\n
"
,
cpupUse
=
LOS_HistorySysCpuUsage
(
CPU
P_LAST_ONE_SECOND
S
);
d
printf
(
"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_1
S
);
printf
(
"cpu usage of the cpupTestTask in all time:
\n
TaskID: %d
\n
usage: %u.%u
\n
"
,
cpupUse
=
LOS_HistoryTaskCpuUsage
(
g_cpuTestTaskID
,
CPU
P_LAST_ONE_SECOND
S
);
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
);
return
LOS_OK
;
}
...
...
@@ -158,4 +159,6 @@ 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
根据实际运行环境,打印会有差异
```
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
浏览文件 @
68cead99
...
...
@@ -34,38 +34,35 @@
新增一个内核模块,需要在内核初始化时进行该模块的初始化,则通过内核启动框架将该模块的初始化函数注册进内核启动流程中。
为方便学习,本演示代码直接在 . 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
```
...
...
zh-cn/device-dev/kernel/kernel-small-start-user.md
浏览文件 @
68cead99
...
...
@@ -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进程。具体过程如下:
...
...
zh-cn/device-dev/website.md
浏览文件 @
68cead99
...
...
@@ -290,7 +290,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
)
-
内核态内存调测
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录