浅析什么是HOOK

首先明确一点:hook是一个编程机制,与语言无关。个人的简单理解hook就是钩子,之所以说是钩子,是因为你可以往钩子上挂任何东西,程序执行到hook的时候,你预先挂上/勾上(hook)的是什么,就执行什么。

比如 Mesa defines hooks for the parts where drivers may need to do hardware specific stuff, for example in the implementation of glDrawArrays().

贴一段维基百科中对钩子的定义:

钩子编程(hooking),也称作“挂钩”,是计算机程序设计术语,指通过拦截软件模块间的函数调用、消息传递、事件传递来修改或扩展操作系统、应用程序或其他软件组件的行为的各种技术处理被拦截的函数调用、事件、消息的代码,被称为钩子(hook)。

Hook原意是指钩子,它表示的就是在某个函数的上下文做自定义的处理来实现我们想要的黑科技

生搬硬套的理解HOOK,其实容易一知半解。要想要比较好的理解HOOK,最好是结合相应的语言/技术栈。

在很多技术领域都存在的这种Hook技术,比如下面这些:

    • PythonWeb框架中,如DjangoFlask都存在这种Hook技术,可以在请求的上下文应用的上下文做自定义操作。
    • Scrapy框架中,可以自定义MiddlerWare,在请求解析的时候做自定操作。
    • K8S编排框架中,我们也可以在执行某些函数的上下文中插入Hook函数,这也是和Web框架同理
    • Hook 是 PyTorch 中一个十分有用的特性。利用它,我们可以不必改变网络输入输出的结构,方便地获取、改变网络中间层变量的值和梯度。这个功能被广泛用于可视化神经网络中间层的 feature、gradient,从而诊断神经网络中可能出现的问题,分析网络有效性。

Hook大概原理

创建一个代理对象,然后把原始对象替换为我们的代理对象,这样就可以在这个代理对象为所欲为,修改参数或替换返回值。

正常调用:

HOOK调用:

 

有时我们可能会理解不清什么是handle,什么是hook。总的来说,handle是对计算机资源(文件,设备,网络,窗口等等)的抽象表示。程序员可以通过handle来操作系统中的各类资源。而hook指通过拦截系统或者应用中的事件,信号和调用,来更改系统或者应用的默认行为

 摘录一个别人写的例子,便于理解:

import time

class LazyPerson(object):
    def __init__(self, name):
        self.name = name
        self.watch_tv_func = None
        self.have_dinner_func = None

    def get_up(self):
        print("%s get up at:%s" % (self.name, time.time()))

    def go_to_sleep(self):
        print("%s go to sleep at:%s" % (self.name, time.time()))

    def register_tv_hook(self, watch_tv_func):
        self.watch_tv_func = watch_tv_func

    def register_dinner_hook(self, have_dinner_func):
        self.have_dinner_func = have_dinner_func

    def enjoy_a_lazy_day(self):

        # get up
        self.get_up()
        time.sleep(3)
        # watch tv
        # check the watch_tv_func(hooked or unhooked)
        # hooked
        if self.watch_tv_func is not None:
            self.watch_tv_func(self.name)
        # unhooked
        else:
            print("no tv to watch")
        time.sleep(3)
        # have dinner
        # check the have_dinner_func(hooked or unhooked)
        # hooked
        if self.have_dinner_func is not None:
            self.have_dinner_func(self.name)
        # unhooked
        else:
            print("nothing to eat at dinner")
        time.sleep(3)
        self.go_to_sleep()

def watch_daydayup(name):
    print("%s : The program ---day day up--- is funny!!!" % name)

def watch_happyfamily(name):
    print("%s : The program ---happy family--- is boring!!!" % name)

def eat_meat(name):
    print("%s : The meat is nice!!!" % name)


def eat_hamburger(name):
    print("%s : The hamburger is not so bad!!!" % name)


if __name__ == "__main__":
    lazy_tom = LazyPerson("Tom")
    lazy_jerry = LazyPerson("Jerry")
    # register hook
    lazy_tom.register_tv_hook(watch_daydayup)
    lazy_tom.register_dinner_hook(eat_meat)
    lazy_jerry.register_tv_hook(watch_happyfamily)
    lazy_jerry.register_dinner_hook(eat_hamburger)
    # enjoy a day
    lazy_tom.enjoy_a_lazy_day()
    lazy_jerry.enjoy_a_lazy_day()

#代码原作者链接:https://blog.csdn.net/Mybigkid/java/article/details/78383898

运行结果:

Tom get up at:1509246940.32
Tom : The program ---day day up--- is funny!!!
Tom : The meat is nice!!!
Tom go to sleep at:1509246949.34
Jerry get up at:1509246949.34
Jerry : The program ---happy family--- is boring!!!
Jerry : The hamburger is not so bad!!!
Jerry go to sleep at:1509246958.37
————————————————
#原作者代码链接:https://blog.csdn.net/Mybigkid/java/article/details/78383898

 

 参考链接:

https://zhuanlan.zhihu.com/p/55276265

https://www.zhihu.com/question/57130969/answer/151896360

https://zhuanlan.zhihu.com/p/75054200

https://zhuanlan.zhihu.com/p/89566158

https://blog.csdn.net/Mybigkid/article/details/78383898?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

posted @ 2020-07-07 16:37  青山牧云人  阅读(12422)  评论(0编辑  收藏  举报