鴻蒙輕內(nèi)核M核源碼分析系列十五CPU使用率CPUP
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
CPUP(Central Processing Unit Percentage,CPU占用率)分為系統(tǒng)CPU占用率和任務(wù)CPU占用率。用戶通過系統(tǒng)級的CPU占用率,判斷當(dāng)前系統(tǒng)負(fù)載是否超出設(shè)計(jì)規(guī)格。通過系統(tǒng)中各個(gè)任務(wù)的CPU占用情況,判斷各個(gè)任務(wù)的CPU占用率是否符合設(shè)計(jì)的預(yù)期。
系統(tǒng)CPU占用率是指周期時(shí)間內(nèi)系統(tǒng)的CPU占用率,用于表示系統(tǒng)一段時(shí)間內(nèi)的閑忙程度,也表示CPU的負(fù)載情況。系統(tǒng)CPU占用率的有效表示范圍為0~100,其精度(可通過配置調(diào)整)為百分比。100表示系統(tǒng)滿負(fù)荷運(yùn)轉(zhuǎn)。
任務(wù)CPU占用率指單個(gè)任務(wù)的CPU占用率,用于表示單個(gè)任務(wù)在一段時(shí)間內(nèi)的閑忙程度。任務(wù)CPU占用率的有效表示范圍為0~100,其精度(可通過配置調(diào)整)為百分比。100表示在一段時(shí)間內(nèi)系統(tǒng)一直在運(yùn)行該任務(wù)。
本文通過分析鴻蒙輕內(nèi)核CPUP擴(kuò)展模塊的源碼。
CPUP模塊用任務(wù)級記錄的方式,在任務(wù)切換時(shí),記錄任務(wù)啟動(dòng)時(shí)間,任務(wù)切出或者退出時(shí)間,每次當(dāng)任務(wù)退出時(shí),系統(tǒng)會(huì)累加整個(gè)任務(wù)的占用時(shí)間。接下來,我們看下CPUP模塊支持的常見操作的源代碼。
1、CPUP結(jié)構(gòu)體定義和常用宏定義
1.1 CPUP結(jié)構(gòu)體定義
在文件components\cpup\los_cpup.h定義的CPUP控制塊結(jié)構(gòu)體為OsCpupCB,結(jié)構(gòu)體源代碼如下,allTime記錄該任務(wù)自系統(tǒng)啟動(dòng)以來運(yùn)行的cycle數(shù),startTime記錄任務(wù)開始運(yùn)行的時(shí)間,historyTime[]歷史運(yùn)行時(shí)間數(shù)組的10個(gè)元素記錄最近10秒中每一秒中每個(gè)任務(wù)自系統(tǒng)啟動(dòng)以來運(yùn)行的cycle數(shù),其他結(jié)構(gòu)體成員的解釋見注釋部分。
- typedef struct {
- UINT32 cpupID; /**< 任務(wù)編號 */
- UINT16 status; /**< 任務(wù)狀態(tài) */
- UINT64 allTime; /**< 總共運(yùn)行的時(shí)間 */
- UINT64 startTime; /**< 任務(wù)開始時(shí)間 */
- UINT64 historyTime[OS_CPUP_HISTORY_RECORD_NUM]; /**< 歷史運(yùn)行時(shí)間數(shù)組,其中OS_CPUP_HISTORY_RECORD_NUM為10 */
- } OsCpupCB;
另外,還定義了一個(gè)結(jié)構(gòu)體CPUP_INFO_S,如下:
- typedef struct tagCpupInfo {
- UINT16 usStatus; /**< 保存當(dāng)前運(yùn)行任務(wù)狀態(tài) */
- UINT32 uwUsage; /**< 使用情況,值范圍為 [0,1000]. */
- } CPUP_INFO_S;
1.2 CPUP枚舉定義
CPUP頭文件components\cpup\los_cpup.h中還提供了相關(guān)的枚舉,CPUP占用率類型CPUP_TYPE_E,及CPUP統(tǒng)計(jì)時(shí)間間隔模式CPUP_MODE_E。
- typedef enum {
- SYS_CPU_USAGE = 0, /* 系統(tǒng)CPUP */
- TASK_CPU_USAGE, /* 任務(wù)CPUP */
- } CPUP_TYPE_E;
- typedef enum {
- CPUP_IN_10S = 0, /* CPUP統(tǒng)計(jì)周期10s */
- CPUP_IN_1S, /* CPUP統(tǒng)計(jì)周期1s */
- CPUP_LESS_THAN_1S, /* CPUP統(tǒng)計(jì)周期<1s */
- } CPUP_MODE_E;
2、CPUP初始化
CPUP默認(rèn)關(guān)閉,用戶可以通過宏LOSCFG_BASE_CORE_CPUP進(jìn)行開啟。開啟CPUP的情況下,在系統(tǒng)啟動(dòng)時(shí),在kernel\src\los_init.c中調(diào)用OsCpupInit()進(jìn)行CPUP模塊初始化。下面,我們分析下CPUP初始化的代碼。
⑴處計(jì)算CPUP結(jié)構(gòu)體池需要的內(nèi)存大小,然后為CPUP申請內(nèi)存,如果申請失敗,則返回錯(cuò)誤。⑵處初始化成功后,設(shè)置初始化標(biāo)記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內(nèi)部接口
我們先分析下內(nèi)部接口,這些接口會(huì)被LOS_開頭的外部接口調(diào)用。
3.1.1 OsTskCycleStart記錄任務(wù)開始時(shí)間
CPUP模塊對外接口執(zhí)行后期會(huì)調(diào)用該內(nèi)部接口,設(shè)置下一個(gè)任務(wù)的開始運(yùn)行時(shí)間。
⑴處先判斷CPUP是否已經(jīng)初始化,如果沒有初始化過,退出該函數(shù)的執(zhí)行。⑵處獲取新任務(wù)的任務(wù)編號。⑶處設(shè)置該任務(wù)對應(yīng)的CPUP結(jié)構(gòu)體的任務(wù)編號和開始時(shí)間。
- 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記錄任務(wù)結(jié)束時(shí)間
CPUP模塊對外接口執(zhí)行前期會(huì)調(diào)用該內(nèi)部接口,獲取當(dāng)前任務(wù)的結(jié)束時(shí)間,并統(tǒng)計(jì)當(dāng)前任務(wù)的運(yùn)行總時(shí)間。
⑴處先判斷CPUP是否已經(jīng)初始化,如果沒有初始化過,退出該函數(shù)的執(zhí)行。⑵處獲取當(dāng)前任務(wù)的任務(wù)編號。⑶處如果該任務(wù)的開始時(shí)間為0,退出函數(shù)執(zhí)行。⑷處獲取系統(tǒng)的當(dāng)前cycle數(shù)。⑸如果獲取的小于任務(wù)CPUP開始時(shí)間,則把獲取的cycle數(shù)加上每個(gè)tick的cycle數(shù)。⑹處計(jì)算當(dāng)前任務(wù)的運(yùn)行的總時(shí)間,然后把開始時(shí)間置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任務(wù)切換時(shí)更新任務(wù)歷史運(yùn)行時(shí)間
該函數(shù)在任務(wù)調(diào)度切換時(shí)會(huì)被執(zhí)行,計(jì)算當(dāng)前運(yùn)行任務(wù)的運(yùn)行總時(shí)間,記錄新任務(wù)的開始時(shí)間,并更新所有任務(wù)的歷史運(yùn)行時(shí)間。函數(shù)的示意圖如下:

⑴處先判斷CPUP是否已經(jīng)初始化,如果沒有初始化過,退出該函數(shù)的執(zhí)行。
⑵處獲取當(dāng)前任務(wù)的任務(wù)編號,然后獲取系統(tǒng)的當(dāng)前cycle數(shù)。
⑶處如果當(dāng)前任務(wù)的開始時(shí)間不為0,則計(jì)算當(dāng)前任務(wù)的運(yùn)行的總時(shí)間,然后把開始時(shí)間置0。
⑷處獲取新任務(wù)的任務(wù)編號。
⑸處設(shè)置該任務(wù)對應(yīng)的CPUP結(jié)構(gòu)體的任務(wù)編號和開始時(shí)間。
⑹處如果記錄間隔大于系統(tǒng)時(shí)鐘(即每秒的cycle數(shù)),更新上次記錄時(shí)間。這意味著每個(gè)任務(wù)的historyTime[]數(shù)組中的每個(gè)元素表示1s多的周期內(nèi)該任務(wù)的運(yùn)行cycle數(shù)量,并不是非常精確的。然后執(zhí)行⑺,記錄每一個(gè)任務(wù)對應(yīng)的CPUP的歷史運(yùn)行時(shí)間。⑻處更新歷史運(yùn)行時(shí)間數(shù)組的當(dāng)前索引值。
- 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獲取歷史運(yùn)行時(shí)間數(shù)組上一索引位置
代碼比較簡單,如果傳入?yún)?shù)curPos為0,則返回?cái)?shù)組的最后一個(gè)索引位置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獲取歷史運(yùn)行時(shí)間數(shù)組的當(dāng)前及上一索引位置
根據(jù)CPUP統(tǒng)計(jì)時(shí)間間隔模式,獲取歷史運(yùn)行時(shí)間數(shù)組的當(dāng)前及上一索引位置。
⑴處獲取歷史運(yùn)行時(shí)間數(shù)組的當(dāng)前索引位置,⑵如果時(shí)間間隔模式為1秒,當(dāng)前索引curPos位置為g_hisPos的上一索引位置,上一索引位置prePos需要繼續(xù)上前一位。⑶如果時(shí)間間隔模式小于1秒,當(dāng)前索引curPos位置為g_hisPos的上一索引位置,上一索引位置prePos為0。如果時(shí)間間隔模式是10秒,當(dāng)前索引curPos位置就等于g_hisPos,上一索引位置prePos為0。⑷處設(shè)置傳出參數(shù)。
- 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
該函數(shù)會(huì)統(tǒng)計(jì)當(dāng)前系統(tǒng)CPU占用率,返回值基于千分率計(jì)算,取值范圍為[0,1000]。函數(shù)的示意圖如下:

⑴處先判斷CPUP是否已經(jīng)初始化,如果沒有初始化過,返回錯(cuò)誤碼。
⑵處調(diào)用函數(shù)OsTskCycleEnd()獲取當(dāng)前任務(wù)的結(jié)束時(shí)間,并計(jì)算出運(yùn)行總時(shí)間。
⑶處統(tǒng)計(jì)所有任務(wù)的運(yùn)行總時(shí)間,如果總時(shí)間不為0,執(zhí)行⑷計(jì)算出系統(tǒng)的任務(wù)CPU占用率。
⑸處調(diào)用函數(shù)OsTskCycleStart()設(shè)置新任務(wù)的CPUP統(tǒng)計(jì)的開始時(shí)間。
- 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
該函數(shù)獲取系統(tǒng)歷史CPU占用率,對于歷史CPU占用率,需要傳入時(shí)間間隔模式參數(shù),支持10秒、1秒、小于1秒三種。
⑴處先判斷CPUP是否已經(jīng)初始化,如果沒有初始化過,返回錯(cuò)誤碼。⑵處調(diào)用函數(shù)OsTskCycleEnd()獲取當(dāng)前任務(wù)的結(jié)束時(shí)間,并計(jì)算出運(yùn)行總時(shí)間。⑶處調(diào)用函數(shù)OsGetPositions()計(jì)算出歷史運(yùn)行時(shí)間數(shù)組索引位置。⑷處計(jì)算出各個(gè)任務(wù)的周期內(nèi)運(yùn)行總時(shí)間,如果時(shí)間間隔模式為1秒,取值兩個(gè)歷史運(yùn)行時(shí)間之差,即為1秒內(nèi)任務(wù)的運(yùn)行時(shí)間數(shù)。對于時(shí)間間隔模式為10秒,historyTime[curPos]表示10秒前的自系統(tǒng)啟動(dòng)以來的任務(wù)運(yùn)行的時(shí)間數(shù),計(jì)算出來的差值即為10秒內(nèi)任務(wù)的運(yùn)行時(shí)間數(shù)。對于時(shí)間間隔模式為小于1秒,historyTime[curPos]表示上一秒前的自系統(tǒng)啟動(dòng)以來的任務(wù)運(yùn)行的時(shí)間數(shù),計(jì)算出來的差值即為小于1秒內(nèi)任務(wù)的運(yùn)行時(shí)間數(shù)。⑸處計(jì)算空閑任務(wù)周期內(nèi)運(yùn)行總時(shí)間。⑹處如果總時(shí)間不為0,計(jì)算出系統(tǒng)的任務(wù)歷史CPU占用率。最后,調(diào)用函數(shù)OsTskCycleStart()設(shè)置新任務(wù)的CPUP統(tǒng)計(jì)的開始時(shí)間。可以參考示意圖進(jìn)行理解:

- 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
該函數(shù)會(huì)統(tǒng)計(jì)指定任務(wù)的CPU占用率,和函數(shù)LOS_SysCpuUsage()代碼相似度高,可以參考上文對該函數(shù)的講解。
- 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
該函數(shù)獲取指定任務(wù)的歷史CPU占用率,和函數(shù)LOS_HistorySysCpuUsage()代碼相似度高,可以參考上文對該函數(shù)的講解。
- 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
該函數(shù)獲取全部任務(wù)的CPU占用率,獲取的CPU占用率信息保存在傳出參數(shù)結(jié)構(gòu)體CPUP_INFO_S *cpupInfo指向的內(nèi)存區(qū)域里,需要注意這個(gè)內(nèi)存區(qū)域的大小需要等于sizeof(CPUP_INFO_S) * g_taskMaxNum。還需要傳入時(shí)間間隔模式參數(shù),支持10秒、1秒、小于1秒三種。
⑴處先判斷CPUP是否已經(jīng)初始化,如果沒有初始化過,返回錯(cuò)誤碼。傳出參數(shù)cpupInfo指針不能為空,否則返回錯(cuò)誤碼。⑵處調(diào)用函數(shù)OsTskCycleEnd()獲取當(dāng)前任務(wù)的結(jié)束時(shí)間,并計(jì)算出運(yùn)行總時(shí)間。⑶處調(diào)用函數(shù)OsGetPositions()計(jì)算出歷史運(yùn)行時(shí)間數(shù)組索引位置。⑷處計(jì)算出各個(gè)任務(wù)的周期內(nèi)運(yùn)行總時(shí)間,如果時(shí)間間隔模式為1秒,取值兩個(gè)歷史運(yùn)行時(shí)間之差,否則取值XX。⑸處設(shè)置每一個(gè)任務(wù)的狀態(tài),然后計(jì)算出每一個(gè)任務(wù)的CPU占用率。最后,調(diào)用函數(shù)OsTskCycleStart()設(shè)置新任務(wù)的CPUP統(tǒng)計(jì)的開始時(shí)間。
- 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
該函數(shù)獲取歷史CPU占用率并打印輸出,傳入?yún)?shù)有三個(gè):CPU占用率類型,CPUP時(shí)間周期模式,指定的任務(wù)編號。對于任務(wù)CPU占用率,才需要指定有效的任務(wù)編號。
⑴處處理CPU占用率類型為系統(tǒng)CPU占用率的情況。
⑵處打印使用的CPUP時(shí)間周期模式。
⑶處通過調(diào)用函數(shù)LOS_HistorySysCpuUsage()獲取系統(tǒng)歷史CPU占用率,然后執(zhí)行⑷打印輸出CPU占用率結(jié)果,輸出結(jié)果范圍為[0,100]。
⑸處理CPU占用率類型為指定任務(wù)CPU占用率的情況,首先判斷下任務(wù)編號的有效性,校驗(yàn)任務(wù)是否創(chuàng)建等。
⑹處打印使用的CPUP時(shí)間周期模式。
⑺處通過調(diào)用函數(shù)LOS_HistoryTaskCpuUsage()獲取指定任務(wù)的歷史CPU占用率,然后執(zhí)行⑻打印輸出CPU占用率結(jié)果,輸出結(jié)果范圍為[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;
- }
小結(jié)
本文帶領(lǐng)大家一起剖析了鴻蒙輕內(nèi)核的CPUP擴(kuò)展模塊的源代碼。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)