往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- 轻内核M核源码分析系列一 数据结构-双向循环链表
- 轻内核M核源码分析系列二 数据结构-任务就绪队列
- 鸿蒙轻内核M核源码分析系列三 数据结构-任务排序链表
- 轻内核M核源码分析系列四 中断Hwi
- 轻内核M核源码分析系列五 时间管理
- 轻内核M核源码分析系列六 任务及任务调度(1)任务栈
- 轻内核M核源码分析系列六 任务及任务调度(2)任务模块
- 轻内核M核源码分析系列六 任务及任务调度(3)任务调度模块
- 轻内核M核源码分析系列七 动态内存Dynamic Memory
- 轻内核M核源码分析系列八 静态内存MemoryBox
- 轻内核M核源码分析系列九 互斥锁Mutex
- 轻内核M核源码分析系列十 软件定时器Swtmr
- 轻内核M核源码分析系列十一 (1)信号量Semaphore
- 轻内核M核源码分析系列十一 (2)信号量Semaphore
- 轻内核M核源码分析系列十二 事件Event
- 轻内核M核源码分析系列十三 消息队列Queue
- 轻内核M核源码分析系列十四 软件定时器Swtmr
- 轻内核M核源码分析系列十五 CPU使用率CPUP
- 轻内核M核源码分析系列十六 MPU内存保护单元
- 轻内核M核源码分析系列十七(1) 异常钩子函数类型介绍
- 轻内核M核源码分析系列十七(2) 异常钩子函数的注册操作
- 轻内核M核源码分析系列十七(3) 异常信息ExcInfo
- 轻内核M核源码分析系列十八 Fault异常处理
- 轻内核M核源码分析系列十九 Musl LibC
- 轻内核M核源码分析系列二十 Newlib C
- 持续更新中……
CPUP(Central Processing Unit Percentage,CPU占用率)分为系统CPU占用率和任务CPU占用率。用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。通过系统中各个任务的CPU占用情况,判断各个任务的CPU占用率是否符合设计的预期。
系统CPU占用率是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系统CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示系统满负荷运转。
任务CPU占用率指单个任务的CPU占用率,用于表示单个任务在一段时间内的闲忙程度。任务CPU占用率的有效表示范围为0~100,其精度(可通过配置调整)为百分比。100表示在一段时间内系统一直在运行该任务。
本文通过分析鸿蒙轻内核CPUP扩展模块的源码。本文中所涉及的源码,以OpenHarmony LiteOS-M
内核为例,均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_m 获取。
CPUP
模块用任务级记录的方式,在任务切换时,记录任务启动时间,任务切出或者退出时间,每次当任务退出时,系统会累加整个任务的占用时间。接下来,我们看下CPUP
模块支持的常见操作的源代码。
1、CPUP结构体定义和常用宏定义
1.1 CPUP结构体定义
在文件components\cpup\los_cpup.h
定义的CPUP控制块结构体为OsCpupCB
,结构体源代码如下,allTime
记录该任务自系统启动以来运行的cycle
数,startTime
记录任务开始运行的时间,historyTime[]
历史运行时间数组的10个元素记录最近10秒中每一秒中每个任务自系统启动以来运行的cycle
数,其他结构体成员的解释见注释部分。
typedef struct {
UINT32 cpupID; /**< 任务编号 */
UINT16 status; /**< 任务状态 */
UINT64 allTime; /**< 总共运行的时间 */
UINT64 startTime; /**< 任务开始时间 */
UINT64 historyTime[OS_CPUP_HISTORY_RECORD_NUM]; /**< 历史运行时间数组,其中OS_CPUP_HISTORY_RECORD_NUM为10 */
} OsCpupCB;
另外,还定义了一个结构体CPUP_INFO_S
,如下:
typedef struct tagCpupInfo {
UINT16 usStatus; /**< 保存当前运行任务状态 */
UINT32 uwUsage; /**< 使用情况,值范围为 [0,1000]. */
} CPUP_INFO_S;
1.2 CPUP枚举定义
CPUP头文件components\cpup\los_cpup.h
中还提供了相关的枚举,CPUP
占用率类型CPUP_TYPE_E
,及CPUP
统计时间间隔模式CPUP_MODE_E
。
typedef enum {
SYS_CPU_USAGE = 0, /* 系统CPUP */
TASK_CPU_USAGE, /* 任务CPUP */
} CPUP_TYPE_E;
typedef enum {
CPUP_IN_10S = 0, /* CPUP统计周期10s */
CPUP_IN_1S, /* CPUP统计周期1s */
CPUP_LESS_THAN_1S, /* CPUP统计周期<1s */
} CPUP_MODE_E;
2、CPUP初始化
CPUP默认关闭,用户可以通过宏LOSCFG_BASE_CORE_CPUP
进行开启。开启CPUP的情况下,在系统启动时,在kernel\src\los_init.c
中调用OsCpupInit()
进行CPUP
模块初始化。下面,我们分析下CPUP
初始化的代码。
⑴处计算CPUP结构体池需要的内存大小,然后为CPUP申请内存,如果申请失败,则返回错误。⑵处初始化成功后,设置初始化标记g_cpupInitFlg
。
LITE_OS_SEC_TEXT_INIT UINT32 OsCpupInit()
{
UINT32 size;
size = g_taskMaxNum * sizeof(OsCpupCB);
⑴ g_cpup = (OsCpupCB *)LOS_MemAlloc(m_aucSysMem0, size);
if (g_cpup == NULL) {
return LOS_ERRNO_CPUP_NO_MEMORY;
}
(VOID)memset_s(g_cpup, size, 0, size);
⑵ g_cpupInitFlg = 1;
return LOS_OK;
}
3、CPUP常用操作
3.1 CPUP内部接口
我们先分析下内部接口,这些接口会被LOS_开头的外部接口调用。
3.1.1 OsTskCycleStart记录任务开始时间
CPUP
模块对外接口执行后期会调用该内部接口,设置下一个任务的开始运行时间。
⑴处先判断CPUP
是否已经初始化,如果没有初始化过,退出该函数的执行。⑵处获取新任务的任务编号。⑶处设置该任务对应的CPUP
结构体的任务编号和开始时间。
LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleStart(VOID)
{
UINT32 taskID;
⑴ if (g_cpupInitFlg == 0) {
return;
}
⑵ taskID = g_losTask.newTask->taskID;
⑶ g_cpup[taskID].cpupID = taskID;
g_cpup[taskID].startTime = LOS_SysCycleGet();
return;
}
3.1.2 OsTskCycleEnd记录任务结束时间
CPUP
模块对外接口执行前期会调用该内部接口,获取当前任务的结束时间,并统计当前任务的运行总时间。
⑴处先判断CPUP
是否已经初始化,如果没有初始化过,退出该函数的执行。⑵处获取当前任务的任务编号。⑶处如果该任务的开始时间为0,退出函数执行。⑷处获取系统的当前cycle
数。⑸如果获取的小于任务CPUP
开始时间,则把获取的cycle
数加上每个tick
的cycle
数。⑹处计算当前任务的运行的总时间,然后把开始时间置0。
LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEnd(VOID)
{
UINT32 taskID;
UINT64 cpuCycle;
⑴ if (g_cpupInitFlg == 0) {
return;
}
⑵ taskID = g_losTask.runTask->taskID;
⑶ if (g_cpup[taskID].startTime == 0) {
return;
}
⑷ cpuCycle = LOS_SysCycleGet();
⑸ if (cpuCycle < g_cpup[taskID].startTime) {
cpuCycle += g_cyclesPerTick;
}
⑹ g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime);
g_cpup[taskID].startTime = 0;
return;
}
3.1.3 OsTskCycleEndStart任务切换时更新任务历史运行时间
该函数在任务调度切换时会被执行,计算当前运行任务的运行总时间,记录新任务的开始时间,并更新所有任务的历史运行时间。函数的示意图如下:
⑴处先判断CPUP
是否已经初始化,如果没有初始化过,退出该函数的执行。⑵处获取当前任务的任务编号,然后获取系统的当前cycle
数。⑶处如果当前任务的开始时间不为0,则计算当前任务的运行的总时间,然后把开始时间置0。
⑷处获取新任务的任务编号,⑸处设置该任务对应的CPUP
结构体的任务编号和开始时间。⑹处如果记录间隔大于系统时钟(即每秒的cycle数),更新上次记录时间。这意味着每个任务的historyTime[]
数组中的每个元素表示1s多的周期内该任务的运行cycle数量,并不是非常精确的。然后执行⑺,记录每一个任务对应的CPUP
的历史运行时间。⑻处更新历史运行时间数组的当前索引值。
LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEndStart(VOID)
{
UINT32 taskID;
UINT64 cpuCycle;
UINT16 loopNum;
⑴ if (g_cpupInitFlg == 0) {
return;
}
⑵ taskID = g_losTask.runTask->taskID;
cpuCycle = LOS_SysCycleGet();
⑶ if (g_cpup[taskID].startTime != 0) {
if (cpuCycle < g_cpup[taskID].startTime) {
cpuCycle += g_cyclesPerTick;
}
g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime);
g_cpup[taskID].startTime = 0;
}
⑷ taskID = g_losTask.newTask->taskID;
⑸ g_cpup[taskID].cpupID = taskID;
g_cpup[taskID].startTime = cpuCycle;
⑹ if ((cpuCycle - g_lastRecordTime) > OS_CPUP_RECORD_PERIOD) {
g_lastRecordTime = cpuCycle;
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
⑺ g_cpup[loopNum].historyTime[g_hisPos] = g_cpup[loopNum].allTime;
}
⑻ if (g_hisPos == (OS_CPUP_HISTORY_RECORD_NUM - 1)) {
g_hisPos = 0;
} else {
g_hisPos++;
}
}
return;
}
3.1.4 OsGetPrePos获取历史运行时间数组上一索引位置
代码比较简单,如果传入参数curPos
为0,则返回数组的最后一个索引位置OS_CPUP_HISTORY_RECORD_NUM - 1
。否则返回减1返回。
LITE_OS_SEC_TEXT_MINOR static inline UINT16 OsGetPrePos(UINT16 curPos)
{
return (curPos == 0) ? (OS_CPUP_HISTORY_RECORD_NUM - 1) : (curPos - 1);
}
3.1.5 OsGetPositions获取历史运行时间数组的当前及上一索引位置
根据CPUP
统计时间间隔模式,获取历史运行时间数组的当前及上一索引位置。
⑴处获取历史运行时间数组的当前索引位置
⑵如果时间间隔模式为1秒,当前索引curPos
位置为g_hisPos
的上一索引位置,上一索引位置prePos
需要继续上前一位。
⑶如果时间间隔模式小于1秒,当前索引curPos
位置为g_hisPos
的上一索引位置,上一索引位置prePos
为0。如果时间间隔模式是10秒,当前索引curPos
位置就等于g_hisPos
,上一索引位置prePos
为0。⑷处设置传出参数。
LITE_OS_SEC_TEXT_MINOR static VOID OsGetPositions(UINT16 mode, UINT16* curPosAddr, UINT16* prePosAddr)
{
UINT16 curPos;
UINT16 prePos = 0;
⑴ curPos = g_hisPos;
⑵ if (mode == CPUP_IN_1S) {
curPos = OsGetPrePos(curPos);
prePos = OsGetPrePos(curPos);
⑶ } else if (mode == CPUP_LESS_THAN_1S) {
curPos = OsGetPrePos(curPos);
}
⑷ *curPosAddr = curPos;
*prePosAddr = prePos;
}
3.2 CPUP对外接口
我们先分析下外部接口,接口说明如下:
接口名称 | 功能描述 |
---|---|
LOS_SysCpuUsage | 获取当前系统CPU占用率 |
LOS_HistorySysCpuUsage | 获取系统历史CPU占用率 |
LOS_TaskCpuUsage | 获取指定任务CPU占用率 |
LOS_HistoryTaskCpuUsage | 获取指定任务历史CPU占用率 |
LOS_AllTaskCpuUsage | 获取所有任务CPU占用率 |
LOS_CpupUsageMonitor | 输出任务历史CPU占用率 |
3.2.1 LOS_SysCpuUsage
该函数会统计当前系统CPU占用率,返回值基于千分率计算,取值范围为[0,1000]。函数的示意图如下:
⑴处先判断CPUP
是否已经初始化,如果没有初始化过,返回错误码。
⑵处调用函数OsTskCycleEnd()
获取当前任务的结束时间,并计算出运行总时间。
⑶处统计所有任务的运行总时间,如果总时间不为0,执行
⑷计算出系统的任务CPU占用率。
⑸处调用函数OsTskCycleStart()
设置新任务的CPUP
统计的开始时间。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_SysCpuUsage(VOID)
{
UINT64 cpuCycleAll = 0;
UINT32 cpupRet = 0;
UINT16 loopNum;
UINT32 intSave;
⑴ if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
intSave = LOS_IntLock();
⑵ OsTskCycleEnd();
⑶ for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
cpuCycleAll += g_cpup[loopNum].allTime;
}
⑷ if (cpuCycleAll) {
cpupRet = LOS_CPUP_PRECISION - (UINT32)((LOS_CPUP_PRECISION *
g_cpup[g_idleTaskID].allTime) / cpuCycleAll);
}
⑸ OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.2 LOS_HistorySysCpuUsage
该函数获取系统历史CPU占用率,对于历史CPU占用率,需要传入时间间隔模式参数,支持10秒、1秒、小于1秒三种。
⑴处先判断CPUP
是否已经初始化,如果没有初始化过,返回错误码。
⑵处调用函数OsTskCycleEnd()
获取当前任务的结束时间,并计算出运行总时间。
⑶处调用函数OsGetPositions()
计算出历史运行时间数组索引位置。
⑷处计算出各个任务的周期内运行总时间,如果时间间隔模式为1秒,取值两个历史运行时间之差,即为1秒内任务的运行时间数。对于时间间隔模式为10秒,historyTime[curPos]
表示10秒前的自系统启动以来的任务运行的时间数,计算出来的差值即为10秒内任务的运行时间数。对于时间间隔模式为小于1秒,historyTime[curPos]
表示上一秒前的自系统启动以来的任务运行的时间数,计算出来的差值即为小于1秒内任务的运行时间数。
⑸处计算空闲任务周期内运行总时间。
⑹处如果总时间不为0,计算出系统的任务历史CPU占用率。最后,调用函数OsTskCycleStart()
设置新任务的CPUP
统计的开始时间。可以参考示意图进行理解:
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistorySysCpuUsage(UINT16 mode)
{
UINT64 cpuCycleAll = 0;
UINT64 idleCycleAll = 0;
UINT32 cpupRet = 0;
UINT16 loopNum;
UINT16 curPos;
UINT16 prePos = 0;
UINT32 intSave;
⑴ if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
// get end time of current task
intSave = LOS_IntLock();
⑵ OsTskCycleEnd();
⑶ OsGetPositions(mode, &curPos, &prePos);
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
⑷ if (mode == CPUP_IN_1S) {
cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
}
⑸ if (mode == CPUP_IN_1S) {
idleCycleAll += g_cpup[g_idleTaskID].historyTime[curPos] -
g_cpup[g_idleTaskID].historyTime[prePos];
} else {
idleCycleAll += g_cpup[g_idleTaskID].allTime - g_cpup[g_idleTaskID].historyTime[curPos];
}
⑹ if (cpuCycleAll) {
cpupRet = (LOS_CPUP_PRECISION - (UINT32)((LOS_CPUP_PRECISION * idleCycleAll) / cpuCycleAll));
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.3 LOS_TaskCpuUsage
该函数会统计指定任务的CPU占用率,和函数LOS_SysCpuUsage()
代码相似度高,可以参考上文对该函数的讲解。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuUsage(UINT32 taskID)
{
UINT64 cpuCycleAll = 0;
UINT16 loopNum;
UINT32 intSave;
UINT32 cpupRet = 0;
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
return LOS_ERRNO_CPUP_TSK_ID_INVALID;
}
if (g_cpup[taskID].cpupID != taskID) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
intSave = LOS_IntLock();
OsTskCycleEnd();
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) {
continue;
}
cpuCycleAll += g_cpup[loopNum].allTime;
}
if (cpuCycleAll) {
cpupRet = (UINT32)((LOS_CPUP_PRECISION * g_cpup[taskID].allTime) / cpuCycleAll);
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.4 LOS_HistoryTaskCpuUsage
该函数获取指定任务的历史CPU占用率,和函数LOS_HistorySysCpuUsage()
代码相似度高,可以参考上文对该函数的讲解。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskID, UINT16 mode)
{
UINT64 cpuCycleAll = 0;
UINT64 cpuCycleCurTsk = 0;
UINT16 loopNum, curPos;
UINT16 prePos = 0;
UINT32 intSave;
UINT32 cpupRet = 0;
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
return LOS_ERRNO_CPUP_TSK_ID_INVALID;
}
if (g_cpup[taskID].cpupID != taskID) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
intSave = LOS_IntLock();
OsTskCycleEnd();
OsGetPositions(mode, &curPos, &prePos);
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) {
continue;
}
if (mode == CPUP_IN_1S) {
cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
}
if (mode == CPUP_IN_1S) {
cpuCycleCurTsk += g_cpup[taskID].historyTime[curPos] - g_cpup[taskID].historyTime[prePos];
} else {
cpuCycleCurTsk += g_cpup[taskID].allTime - g_cpup[taskID].historyTime[curPos];
}
if (cpuCycleAll) {
cpupRet = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll);
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.5 LOS_AllTaskCpuUsage
该函数获取全部任务的CPU占用率,获取的CPU占用率信息保存在传出参数结构体CPUP_INFO_S *cpupInfo
指向的内存区域里,需要注意这个内存区域的大小需要等于sizeof(CPUP_INFO_S) * g_taskMaxNum
。还需要传入时间间隔模式参数,支持10秒、1秒、小于1秒三种。
⑴处先判断CPUP
是否已经初始化,如果没有初始化过,返回错误码。传出参数cpupInfo
指针不能为空,否则返回错误码。⑵处调用函数OsTskCycleEnd()
获取当前任务的结束时间,并计算出运行总时间。⑶处调用函数OsGetPositions()
计算出历史运行时间数组索引位置。⑷处计算出各个任务的周期内运行总时间,如果时间间隔模式为1秒,取值两个历史运行时间之差,否则取值XX。⑸处设置每一个任务的状态,然后计算出每一个任务的CPU占用率。最后,调用函数OsTskCycleStart()
设置新任务的CPUP
统计的开始时间。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_AllTaskCpuUsage(CPUP_INFO_S *cpupInfo, UINT16 mode)
{
UINT16 loopNum;
UINT16 curPos;
UINT16 prePos = 0;
UINT32 intSave;
UINT64 cpuCycleAll = 0;
UINT64 cpuCycleCurTsk = 0;
⑴ if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (cpupInfo == NULL) {
return LOS_ERRNO_CPUP_TASK_PTR_NULL;
}
intSave = LOS_IntLock();
⑵ OsTskCycleEnd();
⑶ OsGetPositions(mode, &curPos, &prePos);
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) ||
(g_cpup[loopNum].status == 0)) {
continue;
}
if (mode == CPUP_IN_1S) {
cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
}
⑷ for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) ||
(g_cpup[loopNum].status == 0)) {
continue;
}
if (mode == CPUP_IN_1S) {
cpuCycleCurTsk += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleCurTsk += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
⑸ cpupInfo[loopNum].usStatus = g_cpup[loopNum].status;
if (cpuCycleAll) {
cpupInfo[loopNum].uwUsage = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll);
}
cpuCycleCurTsk = 0;
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return LOS_OK;
}
3.2.6 LOS_CpupUsageMonitor
该函数获取历史CPU占用率并打印输出,传入参数有三个:CPU
占用率类型,CPUP
时间周期模式,指定的任务编号。对于任务CPU占用率,才需要指定有效的任务编号。
⑴处处理CPU
占用率类型为系统CPU占用率的情况
⑵处打印使用的CPUP
时间周期模式。
⑶处通过调用函数LOS_HistorySysCpuUsage()
获取系统历史CPU占用率,然后执行
⑷打印输出CPU占用率结果,输出结果范围为[0,100]。
⑸处处理CPU
占用率类型为指定任务CPU占用率的情况,首先判断下任务编号的有效性,校验任务是否创建等。
⑹处打印使用的CPUP
时间周期模式。
⑺处通过调用函数LOS_HistoryTaskCpuUsage()
获取指定任务的历史CPU占用率,然后执行
⑻打印输出CPU占用率结果,输出结果范围为[0,100]。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CpupUsageMonitor(CPUP_TYPE_E type, CPUP_MODE_E mode, UINT32 taskID)
{
UINT32 ret;
LosTaskCB *taskCB = NULL;
switch (type) {
⑴ case SYS_CPU_USAGE:
⑵ if (mode == CPUP_IN_10S) {
PRINTK("\nSysCpuUsage in 10s: ");
} else if (mode == CPUP_IN_1S) {
PRINTK("\nSysCpuUsage in 1s: ");
} else {
PRINTK("\nSysCpuUsage in <1s: ");
}
⑶ ret = LOS_HistorySysCpuUsage(mode);
⑷ PRINTK("%d.%d", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
break;
⑸ case TASK_CPU_USAGE:
if (taskID > LOSCFG_BASE_CORE_TSK_LIMIT) {
PRINT_ERR("\nThe taskid is invalid.\n");
return OS_ERROR;
}
taskCB = OS_TCB_FROM_TID(taskID);
if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED)) {
PRINT_ERR("\nThe taskid is invalid.\n");
return OS_ERROR;
}
⑹ if (mode == CPUP_IN_10S) {
PRINTK("\nCPUusage of taskID %d in 10s: ", taskID);
} else if (mode == CPUP_IN_1S) {
PRINTK("\nCPUusage of taskID %d in 1s: ", taskID);
} else {
PRINTK("\nCPUusage of taskID %d in <1s: ", taskID);
}
⑺ ret = LOS_HistoryTaskCpuUsage(taskID, mode);
⑻ PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
break;
default:
PRINT_ERR("\nThe type is invalid.\n");
return OS_ERROR;
}
return LOS_OK;
}
小结
本文带领大家一起剖析了鸿蒙轻内核的CPUP扩展模块的源代码。
经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?
为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview
OpenHarmony 开发环境搭建
《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
- 系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……
OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview