深度解讀鴻蒙輕內核CPU佔用率

摘要: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擴展模塊的源碼。本文中所涉及的源碼,以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對外接口

我們先分析下外部接口,接口說明如下:

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擴展模塊的源代碼。感謝閱讀,如有任何問題、建議,都可以博客下留言給我,謝謝。

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章