1、“回调”与“钩子”

什么是回调函数?什么又是钩子函数?目前对于这两个概念的定义可能难以理解,在编程的过程中也是有点难区别,因为他们本质上都是属于函数,只是说是函数的一种应用的形式不同罢了,既然我们这里谈到这个话题那就好好分析分析。

钩子方法Java java钩子函数和回调函数_钩子方法Java

不管是钩子函数还是回调函数为了保持程序的灵活性,大部分都会采用函数指针的方式进行设计,所以一般小伙伴都直接认为是函数指针的一种应用,如果从语法的角度来看,确实是这么回事,可是我们需要换一个角度去看待一个事物,就像我们之前谈面向对象编程,如果你用面向过程的思维方式去理解面向对象的设计是难以理解的,所以这里的两个概念也是一样的。

 

2、回调函数

应该很多小伙伴在编程中或者阅读别人的代码的时候都会看到callback的字样,是的,回调函数的英文就是callback Fuction,从字面上来理解 : 反过来调用的函数,那我们就需要知道它本来要去哪里,它又返回到什么地方执行,好,下面作者给个简单的demo:

Demo:

#include <stdio.h>
#include <stdlib.h>

typedef int (*Ptr_call_back)(int ,int );
/****************************************** 
 * Fuction : 加法
 * Author  : (公众号:最后一个bug) 
 ******************************************/
int Add(int param1,int param2)
{
    return (param1 + param2);
} 
/****************************************** 
 * Fuction : 减法 
 * Author  : (公众号:最后一个bug) 
 ******************************************/
int Sub(int param1,int param2)
{
    return (param1 - param2);
} 
/****************************************** 
 * Fuction : 计算函数 
 * Author  : (公众号:最后一个bug) 
 ******************************************/
int Cal(int param1,int param2, Ptr_call_back call_back)
{
    return call_back(param1,param2);
} 
/****************************************** 
 * Fuction : 回调函数 
 * Author  : (公众号:最后一个bug) 
 ******************************************/
int main(int argc, char *argv[]) {
    int Val1 = 1;
    int Val2 = 2;
    //调用计算方法 
    printf (" Cal = %d\n",Cal(Val1,Val2, Add));
    printf (" Cal = %d\n",Cal(Val1,Val2, Sub));
    return 0;
}

最后输出结果:

钩子方法Java java钩子函数和回调函数_服务器_02

其实从形式上看来确实没有什么特别的就是函数指针的应用,不过我们换一个角度,用分层的设计角度再对回调函数进行理解,把Cal函数认为是底层函数(也可以说是库函数),把main看成是上层应用函数,而add和sub认为是上层的方法,现在main要让底层Cal去进行计算了,而我们的Cal函数再执行过程中发现不知道用什么方法进行计算,于是他又打道回府去拿到计算的方法,然后获得最后的结果返回给main,那么这里的Sub和Add都认为是回调函数。

钩子方法Java java钩子函数和回调函数_linux_03

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

3、钩子函数

一看到钩子(Hook)我们首先想到的动作就是挂钩,作者这里举个例子:今天要吃鱼,去河边钓鱼,于是我们准备好钓鱼竿,终于有鱼上钩了,一看原来是条小鱼,于是便放了,继续钓鱼,接着钓了条大鱼,于是收工回去吃大餐。

钩子方法Java java钩子函数和回调函数_回调函数_04

所以钩子函数看来就相当于一个监测器,在消息传递的过程中,捕获自己感兴趣的内容,然后去处理,钩子函数这个概念在消息机制中经常会提到的,它也是一个函数,一般是通过函数指针进行灵活的注册,这样一说,完了,分不清楚了,首先我们还是要选择好角度,不确定角度真的说不清。

大家可能会发现钩子函数也是用户定义的,是不是也可以理解为一个回调函数呢?形式上确实可以认为钩子函数也是一种回调函数,不过这样没有什么意义,我还可以说他们都是函数呢?还是要从函数的功能上区分,回调函数更多的是目的处理 ,而钩子函数更多的是过程监控 ,对于钩子函数的应用在rt-thread或者FreeRtos中都使用得非常多。

RT-Thread中截取的钩子函数代码参考:

钩子方法Java java钩子函数和回调函数_linux_05

钩子方法Java java钩子函数和回调函数_钩子方法Java_06

RT-Thread通过一个宏定义来让用户决定是否开启钩子函数功能,上面每次进入中断都会调用对应的钩子函数,具体钩子函数根据自身需求进行设计,比如统计或者监控等等功能。