SylixOS钩子函数浅析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SylixOS钩子函数浅析相关的知识,希望对你有一定的参考价值。

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钩子函数浅析的主要内容,如果未能解决你的问题,请参考以下文章

SylixOS线程私有数据浅析

SylixOS的信号屏蔽浅析

SylixOS的RMS浅析

SylixOS 用户进程加载浅析

SylixOS SPI 总线框架浅析

SylixOS 启动浅析