鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP

embedded/2024/9/25 11:09:45/

往期知识点记录:

  • 鸿蒙(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数加上每个tickcycle数。⑹处计算当前任务的运行的总时间,然后把开始时间置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 taskintSave = 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

图片
在这里插入图片描述


http://www.ppmy.cn/embedded/111526.html

相关文章

GraphRAG源码解读:基于知识图谱构建的检索增强生成系统

1. 引言 GraphRAG&#xff0c;微软开源的一个新的基于知识图谱构建的检索增强生成&#xff08;RAG&#xff09;系统&#xff0c;该框架旨在利用大型语言模型&#xff08;LLMs&#xff09;从非结构化文本中提取结构化数据, 构建具有标签的知识图谱&#xff0c;以支持数据集问题…

实战 Transformers 模型微调之数据集处理库 Hugging Face Datasets

在深度学习中&#xff0c;数据处理是模型训练的关键环节之一。Hugging Face Datasets 库提供了一套强大的工具来简化这一过程&#xff0c;使数据集的管理和预处理变得高效且直观。本文将详细介绍 Hugging Face Datasets 库的基本用法和数据预处理策略&#xff0c;并结合实际代码…

远程控制如何赋能制造业?可视化产线设备运维降本增效

随着如今制造业智能化程度的不断提升&#xff0c;传统制造业对于远程控制方案的需求也越来越紧迫。 在引入远程控制技术之前&#xff0c;无论是日常办公还是产线设备运维&#xff0c;都存在一定的运维资源浪费&#xff0c;效率低下等问题。 那么作为专业的远程控制解决方案品牌…

JS获取页面中video标签视频的封面和时长

从HTML中提取Video信息 /*** 从html字符串中提取video标签* 入参&#xff1a; {String} htmlString* 出参&#xff1a;{Array} 数组*/ function extractVideosFromHTML(htmlString) {const dom new DOMParser().parseFromString(htmlString, text/html);const videos Arr…

微信小程序 本地文件获取原始名称问题

微信版本&#xff1a;8.0.50 结论&#xff1a;图片&#xff0c;视频类文件&#xff0c;获取不到真实名称&#xff0c;文本类文件&#xff0c;压缩包&#xff0c;安装包&#xff0c;可以从chooseMessageFile中获取 具体细节理解&#xff1a;微信文件处理与命名机制分析&#xff…

【Unity】Unity Shader样例:顶点根据时间放大缩小

文章目录 案例说明效果展示适用模型范围代码示例 案例说明 本案例提供一个单独的Shader&#xff0c;使得模型顶点&#xff08;仅渲染&#xff09;根据时间放大缩小&#xff0c;往复循环。 效果展示 适用模型范围 全部 代码示例 Shader "Unlit/Sha_TestScale" {P…

基于UDP的简易网络通信程序

目录 0.前言 1.前置知识 网络通信的大致流程 IP地址 端口号&#xff08;port&#xff09; 客户端如何得知服务器端的IP地址和端口号&#xff1f; 服务器端如何得知客户端的IP地址和端口号&#xff1f; 2.实现代码 代码模块的设计 服务器端代码 成员说明 成员实现 U…

使用Spring Boot集成Nacos进行配置管理

引言 随着微服务架构的普及&#xff0c;服务之间的解耦以及服务治理成为了软件开发中的重要组成部分。一个强大的服务治理平台不仅能够帮助我们更好地管理各个服务实例&#xff0c;还能有效地处理服务间的依赖关系&#xff0c;提升系统的可维护性和扩展性。Nacos&#xff08;原…