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

devtools/2025/1/15 17:27:50/

往期知识点记录:

  • 鸿蒙(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/devtools/108568.html

相关文章

认识爬虫技术

爬虫目的 网络爬虫&#xff0c;主要目的是代替人工收集网络数据。 应用场景主要包括两个方面&#xff1a; 网页收集的数据量少&#xff0c;但重复操作频率高&#xff1b; 通过网页搜集数据的量大。 只要满足以上两个应用场景&#xff0c;其实都可以考虑使用爬虫技术降低人…

JavaScript 知识点(从基础到进阶)

&#x1f30f;个人博客主页&#xff1a;心.c ​ 前言&#xff1a;JavaScript已经学完了&#xff0c;和大家分享一下我的笔记&#xff0c;希望大家可以有所收获&#xff0c;花不多说&#xff0c;开干&#xff01;&#xff01;&#xff01; &#x1f525;&#x1f525;&#x1f5…

828华为云征文|基于华为云Flexus云服务器X实例部搭建Halo博客平台

华为云征文&#xff5c;基于华为云Flexus云服务器X实例部搭建Halo博客平台 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、Halo介绍2.1 Halo 简介2.2 Halo 特点 三、本次实践介绍3.1 本次实践简…

macos 使用port查询并安装python2, python3多版本, 设置默认python版本方法

不管是新版macos还是旧版本的macos都可以使用macport这个包管理工具简单方便的在mac上面安装并存多个版本的python, 还可以利用port select --set python python3 来设置默认的python版本等. port search查询可用python安装包 命令 port search --name --line --regex ^pytho…

探索 Zed 编辑器:速度与协作的巅峰之作

Zed 是一款备受瞩目的代码编辑器,专为现代开发者打造。本文将深入介绍 Zed 的独特优势,以及如何快速上手使用这款编辑器,助你在编程工作中大幅提升效率。 一:Zed 编辑器的优势 Zed 是近年来崭露头角的一款代码编辑器,迅速赢得了众多开发者的青睐。以下是 Zed 的几大核心优…

Java爬虫开发:Jsoup库在图片URL提取中的实战应用

在当今的互联网时代&#xff0c;数据的获取和处理变得尤为重要。对于网站内容的自动化抓取&#xff0c;爬虫技术扮演着不可或缺的角色。Java作为一种广泛使用的编程语言&#xff0c;拥有丰富的库支持网络爬虫的开发。其中&#xff0c;Jsoup库以其简洁、高效的特点&#xff0c;成…

[数据集][目标检测]井盖丢失未盖破损检测数据集VOC+YOLO格式2890张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2890 标注数量(xml文件个数)&#xff1a;2890 标注数量(txt文件个数)&#xff1a;2890 标注…

【解压即玩】PC版《最终幻想9》重制版 高清宽屏,怀旧经典

《最终幻想IX》&#xff08;日语&#xff1a;ファイナルファンタジーIX&#xff0c;英语&#xff1a;Final Fantasy IX&#xff0c;台港澳旧译为“太空战士IX”&#xff09;是由史克威尔&#xff08;现为史克威尔艾尼克斯&#xff09;为索尼PlayStation游戏机开发并发行的一款角…