首先明確一點: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