首先明确一点:hook是一个编程机制,与语言无关。
贴一段维基百科中对钩子的定义:
钩子编程(hooking),也称作“挂钩”,是计算机程序设计术语,指通过拦截软件模块间的函数调用、消息传递、事件传递来修改或扩展操作系统、应用程序或其他软件组件的行为的各种技术。处理被拦截的函数调用、事件、消息的代码,被称为钩子(hook)。
Hook
原意是指钩子
,它表示的就是在某个函数的上下文做自定义的处理来实现我们想要的黑科技
。
生搬硬套的理解HOOK,其实容易一知半解。要想要比较好的理解HOOK,最好是结合相应的语言/技术栈。
在很多技术领域都存在的这种Hook
技术,比如下面这些:
- 在
Python
的Web框架
中,如Django
,Flask
都存在这种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