1. 程式人生 > >SylixOS鉤子函數淺析

SylixOS鉤子函數淺析

intent 周期 ack 同時 break 結束 空閑 cto 系統

1 使用背景
對定時器做相關配置,使得每隔時間T,觸發定時器中斷,可以在定時器中斷處理函數處理算法,這樣就可以周期性的執行特定的任務。但如果不想在定時器中斷處理函數中添加算法,比如說用戶只想在應用程序裏面執行他們的任務,那麽鉤子函數就是一個不錯的選擇。
2 鉤子函數的原理
本章以定時器中斷為例說明SylixOS鉤子的使用方法。
2.1 API_InterVectorIsr函數
函數原型如程序清單 2.1
程序清單 2.1
#include <SylixOS>
irqreturn_t API_InterVectorIsr (ULONG ulVector);
API_InterVectorIsr該內核接口是向量中斷的總服務入口,根據中斷號得到對應的中斷服務函數鏈表,找到具體中斷服務函數。流程圖如圖 2.1 所示。
技術分享圖片
圖 2.1 中斷向量處理流程
從流程圖可以看到,該函數入口處調用LW_CPU_INT_ENTER_HOOK。該宏的定義如程序清單 2.2所示。這就是鉤子函數的調用流程,其實就是調用一個函數指針指向的函數。
程序清單 2.2
#define
LW_CPU_INT_ENTER_HOOK(ulVector, ulNesting) \
if (_K_hookKernel.HOOK_CpuIntEnter) { \
_K_hookKernel.HOOK_CpuIntEnter(ulVector, ulNesting); \
}

2.2 鉤子的設置函數
SylixOS內核提供了鉤子的設置接口API_KernelHookSet,函數的實現如程序清單 2.3所示。

程序清單 2.3
LW_API
ULONG API_KernelHookSet (LW_HOOK_FUNC hookfuncPtr, ULONG ulOpt)
{
INTREG iregInterLevel;

iregInterLevel = __KERNEL_ENTER_IRQ();                              /*  進入內核同時關閉中斷        */

switch (ulOpt) {

case LW_OPTION_THREAD_CREATE_HOOK:                                  /*  線程建立鉤子                */
    _K_hookKernel.HOOK_ThreadCreate = hookfuncPtr;
    break;

case LW_OPTION_THREAD_DELETE_HOOK:                                  /*  線程刪除鉤子                */
    _K_hookKernel.HOOK_ThreadDelete = hookfuncPtr;
    break;

case LW_OPTION_THREAD_SWAP_HOOK:                                    /*  線程切換鉤子                */
    _K_hookKernel.HOOK_ThreadSwap = hookfuncPtr;
    break;

case LW_OPTION_THREAD_TICK_HOOK:                                    /*  系統時鐘中斷鉤子            */
    _K_hookKernel.HOOK_ThreadTick = hookfuncPtr;
    break;

case LW_OPTION_THREAD_INIT_HOOK:                                    /*  線程初始化鉤子              */
    _K_hookKernel.HOOK_ThreadInit = hookfuncPtr;
    break;

case LW_OPTION_THREAD_IDLE_HOOK:                                    /*  空閑線程鉤子                */
    _K_hookKernel.HOOK_ThreadIdle = hookfuncPtr;
    break;

case LW_OPTION_KERNEL_INITBEGIN:                                    /*  內核初始化開始鉤子          */
    _K_hookKernel.HOOK_KernelInitBegin = hookfuncPtr;
    break;

case LW_OPTION_KERNEL_INITEND:                                      /*  內核初始化結束鉤子          */
    _K_hookKernel.HOOK_KernelInitEnd = hookfuncPtr;
    break;

case LW_OPTION_KERNEL_REBOOT:                                       /*  內核重新啟動鉤子            */
    _K_hookKernel.HOOK_KernelReboot = hookfuncPtr;
    break;

case LW_OPTION_WATCHDOG_TIMER:                                      /*  看門狗定時器鉤子            */
    _K_hookKernel.HOOK_WatchDogTimer = hookfuncPtr;
    break;

case LW_OPTION_OBJECT_CREATE_HOOK:                                  /*  創建內核對象鉤子            */
    _K_hookKernel.HOOK_ObjectCreate = hookfuncPtr;
    break;

case LW_OPTION_OBJECT_DELETE_HOOK:                                  /*  刪除內核對象鉤子            */
    _K_hookKernel.HOOK_ObjectDelete = hookfuncPtr;
    break;

case LW_OPTION_FD_CREATE_HOOK:                                      /*  文件描述符創建鉤子          */
    _K_hookKernel.HOOK_FdCreate = hookfuncPtr;
    break;

case LW_OPTION_FD_DELETE_HOOK:                                      /*  文件描述符刪除鉤子          */
    _K_hookKernel.HOOK_FdDelete = hookfuncPtr;
    break;

case LW_OPTION_CPU_IDLE_ENTER:                                      /*  CPU 進入空閑模式            */
    _K_hookKernel.HOOK_CpuIdleEnter = hookfuncPtr;
    break;

case LW_OPTION_CPU_IDLE_EXIT:                                       /*  CPU 退出空閑模式            */
    _K_hookKernel.HOOK_CpuIdleExit = hookfuncPtr;
    break;

case LW_OPTION_CPU_INT_ENTER:                                       /*  CPU 進入中斷(異常)模式      */
    _K_hookKernel.HOOK_CpuIntEnter = hookfuncPtr;
    break;

case LW_OPTION_CPU_INT_EXIT:                                        /*  CPU 退出中斷(異常)模式      */
    _K_hookKernel.HOOK_CpuIntExit = hookfuncPtr;
    break;

case LW_OPTION_STACK_OVERFLOW_HOOK:                                 /*  堆棧溢出                    */
    _K_hookKernel.HOOK_StkOverflow = hookfuncPtr;
    break;

case LW_OPTION_FATAL_ERROR_HOOK:                                    /*  致命錯誤                    */
    _K_hookKernel.HOOK_FatalError = hookfuncPtr;
    break;

case LW_OPTION_VPROC_CREATE_HOOK:                                   /*  進程建立鉤子                */
    _K_hookKernel.HOOK_VpCreate = hookfuncPtr;
    break;

case LW_OPTION_VPROC_DELETE_HOOK:                                   /*  進程刪除鉤子                */
    _K_hookKernel.HOOK_VpDelete = hookfuncPtr;
    break;

default:
    __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出內核同時打開中斷        */
    _ErrorHandle(ERROR_KERNEL_OPT_NULL);
    return  (ERROR_KERNEL_OPT_NULL);
}

__KERNEL_EXIT_IRQ(iregInterLevel);                                  /*  退出內核同時打開中斷        */
return  (ERROR_NONE);

}
該函數可以設置各種類型鉤子函數,由此可見,只要調用API_KernelHookSet設置中斷相關的鉤子函數,當進入中斷入口的函數的入口時都會調用鉤子。
2.3 鉤子函數的定義
假設設置了中斷的鉤子函數,那麽任何中斷都會調用這個鉤子函數。現在只關心定時器中斷,因此需要用中斷號來過濾不關心的中斷。例程如程序清單 2.4所示。
程序清單 2.4
#define TIMER_INTVECTOR 69
void HookFun(ULONG ulVector,ULONG ulnest)
{
if(TIMER_INTVECTOR != ulVector)
{
return;
}

/* 用戶在此添加自己算法*/
/* 註意:不要調用中斷上下文不能執行的語句,比如sleep,printf等*/    

}
這樣,系統會周期性的進入定時器中斷,處理 HookFun函數。只要知道中斷號,就可以不用知曉定時器驅動的實現機制,直接掛接想要處理的任務。
3 參考資料
《SylixOS_driver_usermanual》

SylixOS鉤子函數淺析