写点什么

深度解读鸿蒙轻内核 CPU 占用率

发布于: 3 小时前

摘要:CPUP(Central Processing Unit Percentage,CPU 占用率)分为系统 CPU 占用率和任务 CPU 占用率。用户通过系统级的 CPU 占用率,判断当前系统负载是否超出设计规格。通过系统中各个任务的 CPU 占用情况,判断各个任务的 CPU 占用率是否符合设计的预期。


本文分享自华为云社区《鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP (1)》,作者:zhushy。

 

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 扩展模块的源码。本文中所涉及的源码,以 OpenHarmonyLiteOS-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 对外接口


我们先分析下外部接口,接口说明如下:



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 扩展模块的源代码。感谢阅读,如有任何问题、建议,都可以博客下留言给我,谢谢。


点击关注,第一时间了解华为云新鲜技术~

发布于: 3 小时前阅读数: 6
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
深度解读鸿蒙轻内核CPU占用率