解讀鴻蒙輕核心的監控器:異常鉤子函式

此賬號為華為雲開發者社群官方運營賬號,提供全面深入的雲計算前景分析、豐富的技術乾貨、程式樣例,分享華為雲前沿資訊動態

本文分享自華為雲社群《鴻蒙輕核心M核原始碼分析系列十七(1) 異常鉤子函式型別介紹》,作者:zhushy 。

ExcHook異常鉤子模組是OpenHarmonyLiteOS-M核心的一個可選元件,提供註冊鉤子函式LOS_RegExcHook、解除註冊鉤子函式LOS_UnRegExcHook等操作介面。發生系統時,支援儲存異常上下文、任務資訊、佇列資訊、中斷暫存器狀態、任務切換資訊、記憶體分配等資訊。由於異常鉤子模組內容較多,我們分為幾篇進行分析原始碼,分別介紹異常鉤子函式的型別,如何註冊和解除註冊鉤子函式,如何轉儲異常資訊等。本篇先介紹下支援的異常鉤子函式的型別,異常鉤子函式的註冊、執行等內部操作API介面,並介紹下使用異常鉤子函式的操作介面。異常鉤子函式的註冊、執行,異常鉤子型別定義在utils\los_debug。h|。c。

本文中所涉及的原始碼,以OpenHarmonyLiteOS-M核心為例,均可以在開源站點https://gitee。com/openharmony/kernel_liteos_m 獲取。鴻蒙輕核心異常鉤子模組程式碼主要在components\exchook目錄下。

1、異常鉤子型別列舉EXC_TYPE

在檔案utils\los_debug。h定義異常鉤子型別列舉EXC_TYPE。EXC_REBOOT用於標記系統重啟時的鉤子函式,發生重啟時呼叫註冊的重啟鉤子函式;EXC_ASSERT用於標記斷言函式,發生斷言時呼叫註冊的斷言鉤子函式;EXC_STACKOVERFLOW用於標記任務棧溢位鉤子函式,發生任務棧溢位時呼叫註冊的任務棧溢位鉤子函式;EXC_INTERRUPT用於標記中斷異常時的鉤子函式,發生中斷異常時呼叫註冊的中斷異常鉤子函式。

typedef enum { EXC_REBOOT, EXC_ASSERT, EXC_STACKOVERFLOW, EXC_INTERRUPT, EXC_TYPE_END} EXC_TYPE;

2、如何註冊和執行異常鉤子函式

本節我們先看下如何呼叫和註冊異常鉤子函式,異常鉤子函式的註冊和呼叫的函式API定義在utils\los_debug。c,程式碼如下。⑴處定義的函式OsExcHookRegister用於註冊異常鉤子函式到全域性變數g_excHook。它的傳入的引數ExcHookFnexcHookFn是個異常鉤子函式,這個鉤子函式是定義在檔案components\exchook\los_exchook。c中的STATICVOID DoExcHook(EXC_TYPE excType)

後文會詳細分析。另外,從程式碼上可以看出異常鉤子函式只有一個,也只能註冊一次。⑵處定義的異常鉤子執行函式OsDoExcHook,根據傳入的列舉型別EXC_TYPE來判斷執行什麼型別的異常鉤子函式。

可以看出這2個函式都是內部函式,用函式OsExcHookRegister註冊的也是全域性的異常鉤子函式,它實質上對應的其實是個異常鉤子函式陣列。後文會分析如何透過定義在components\exchook\los_exchook。c的LOS_RegExcHook函式如何分別註冊不同型別的異常鉤子函式。下文也會詳細分析其他對外函式如何呼叫OsDoExcHook來處理異常。

⑴ VOID OsExcHookRegister(ExcHookFn excHookFn) { UINT32 intSave = LOS_IntLock(); if (!g_excHook) { g_excHook = excHookFn; } LOS_IntRestore(intSave); }⑵ VOID OsDoExcHook(EXC_TYPE excType) { UINT32 intSave = LOS_IntLock(); if (g_excHook) { g_excHook(excType); } LOS_IntRestore(intSave); }

3、使用異常鉤子函式的操作

我們從上文知道,註冊的全域性異常鉤子函式只有一個,那就是全域性異常鉤子函式變數g_excHook,它根據不同的異常鉤子型別來分別處理。我們看下具體如何異常鉤子函式的,關於全域性異常鉤子函式底層的細節後文會詳細分析。

3。1 重啟

LOS_Reboot該函式可以在發生系統重啟異常時呼叫,程式僵死在此處等待看門狗watchdog等。⑴處根據引數型別EXC_REBOOT呼叫對應的重啟異常鉤子函式。需要在系統初始化時執行LOS_RegExcHook(EXC_REBOOT,(ExcHookFn)YourRebootFunction)註冊異常鉤子函式,才能執行重啟異常鉤子函式。YourRebootFunction需要自行定義實現在系統重啟異常時執行什麼操作。如果沒有註冊過重啟鉤子函式則跳過不執行任何操作。

LITE_OS_SEC_TEXT_INIT VOID LOS_Reboot(VOID){⑴ OsDoExcHook(EXC_REBOOT); HalSysExit();}

3。2 斷言

LOS_ASSERT該函式可以用於驗證函式的引數合法性,該函式宏定義在檔案utils\los_debug。h。可以看出,如果設定的列印級別數值太低,時不支援斷言功能的。如⑴處程式碼所示,該函式宏需要一個引數judge。如果引數為假時會執行⑵處的程式碼,根據引數型別EXC_ASSERT呼叫對應的斷言異常鉤子函式。需要在系統初始化時執行LOS_RegExcHook(EXC_ASSERT,(ExcHookFn)YourAssertFunction)註冊異常鉤子函式,才能執行斷言異常鉤子函式。YourAssertFunction需要自行定義實現在斷言異常時執行什麼操作。如果沒有註冊過斷言鉤子函式則跳過不執行任何操作。LOS_ASSERT後續的⑶處的程式碼會關閉中斷,列印斷言錯誤資訊ASSERTERROR。。。。

#if PRINT_LEVEL < LOG_ERR_LEVEL#define LOS_ASSERT(judge)#else#define LOS_ASSERT(judge) \ do { \⑴ if ((judge) == 0) { \⑵ OsDoExcHook(EXC_ASSERT); \⑶ (VOID)LOS_IntLock(); \ PRINT_ERR(“ASSERT ERROR! %s, %d, %s\n”, __FILE__, __LINE__, __func__); \ while (1) { } \ } \ } while (0)#endif

3。3 任務棧溢位

OsDoExcHook(EXC_STACKOVERFLOW)任務棧溢位OsDoExcHook(EXC_STACKOVERFLOW)被

OsHandleRunTaskStackOverflow函式和OsHandleNewTaskStackOverflow函式呼叫,這2個函式定義在檔案kernel\src\los_task。c,分別在當前執行任務,要排程執行的新任務發生任務棧溢位時呼叫。當執行到⑴、⑵處的程式碼時,根據引數型別EXC_STACKOVERFLOW呼叫對應的異常鉤子函式。需要在系統初始化時執行LOS_RegExcHook(EXC_STACKOVERFLOW,(ExcHookFn)YourStackOverflowFunction)註冊異常鉤子函式,才能執行異常鉤子函式。YourStackOverflowFunction需要自行定義實現在任務棧溢位異常時執行什麼操作。如果沒有註冊過鉤子函式則跳過不執行任何操作。

LITE_OS_SEC_TEXT STATIC VOID OsHandleRunTaskStackOverflow(VOID){ PRINT_ERR(“CURRENT task ID: %s:%d stack overflow!\n”, g_losTask。runTask->taskName, g_losTask。runTask->taskID);⑴ OsDoExcHook(EXC_STACKOVERFLOW);}……LITE_OS_SEC_TEXT STATIC VOID OsHandleNewTaskStackOverflow(VOID){ …… tmp = g_losTask。runTask; g_losTask。runTask = g_losTask。newTask;⑵ OsDoExcHook(EXC_STACKOVERFLOW); g_losTask。runTask = tmp;}

3。4 中斷異常

HalExcHandleEntry該函式在發生中斷異常時彙編程式碼中呼叫執行,用於處於系統異常,該函式宏定義在不同晶片架構實現的檔案los_interrupt。c中,如kernel\arch\arm\cortex-m7\gcc\los_interrupt。c。處理系統中斷異常時,執行到⑴處程式碼時,會根據引數型別EXC_INTERRUPT呼叫對應的異常鉤子函式。和上述幾個異常型別的鉤子函式不一樣,中斷異常鉤子函式不需要使用者來註冊,核心已經註冊了中斷異常鉤子函式。相應的程式碼在檔案components\exchook\los_exc_info。c中,註冊程式碼語句為(VOID)LOS_RegExcHook(EXC_INTERRUPT,(ExcHookFn)OsExcMsgDump);,當發生系統中斷異常時會呼叫(ExcHookFn)OsExcMsgDump函式,後文會詳細分析都包含哪些異常資訊。

LITE_OS_SEC_TEXT_INIT VOID HalExcHandleEntry(UINT32 excType, UINT32 faultAddr, UINT32 pid, EXC_CONTEXT_S *excBufAddr){ ……⑴ OsDoExcHook(EXC_INTERRUPT); OsExcInfoDisplay(&g_excInfo); HalSysExit();}

小結

本文介紹了異常鉤子函式的註冊函式OsExcHookRegister和異常鉤子函式的呼叫函式OsDoExcHook,以及介紹了支援的異常鉤子函式型別等。

點選關注,第一時間瞭解華為雲新鮮技術~華為雲部落格_大資料部落格_AI部落格_雲計算部落格_開發者中心-華為雲