Linux kernel 的 kretprobe 機(jī)制和 kprobe 完全不同,本質(zhì)原因在于,函數(shù)的入口地址是固定的,但函數(shù)的返回地址不固定,由于返回位置不固定,無法固定函數(shù)大小,無法事先插樁。一圖以示之:
想在函數(shù)返回時插入個 hook,只有在函數(shù)被調(diào)用時確定了函數(shù)返回地址(x86 為例,壓棧返回地址)后才可能。
因此,kprobe 在register 時即可將 hook 掛載,與 kprobe 不同,kretprobe 需在函數(shù)每次被調(diào)用時才能將 hook 掛載。這只是事情的輪廓,“在函數(shù)調(diào)用時掛載 hook” 才是大頭。
task 將函數(shù)返回地址替換成 kretprobe 的 hook 地址之前要保存舊返回地址,由于函數(shù)可被不同task 同時調(diào)用,因此不同 task 需擁有獨立的 kretprobe instance。
同一個 kretprobe hook,不同 kretprobe instance,Linux kernel 預(yù)分配了若干(與 CPU 數(shù)量相關(guān)) kretprobe instance,掛接在 kretprobe 的某 list 上,每當(dāng)有 task 需要 kretprobe 特定函數(shù)時,在函數(shù)的入口處先從 kretprobe 的 list 上摘出一 kretprobe instance 供自己私用,此時函數(shù)返回地址已經(jīng)壓棧,替換返地址為 hook 前將其 save 在獨享的 kretprobe instance 中。
很長一段時間跨越很多內(nèi)核版本,多個 kretprobe instance 以 hlist node 的方式掛接在以 task地址 hash 為 key 的 hlist 上,而對 hlist node 的 CURD 必然涉及 lock,對于高頻調(diào)用的熱點函數(shù),kretprobe 里的這個lock 相當(dāng)于自設(shè)的路障hash 到同一個 bucket 的 task 同時調(diào)用一個函數(shù)時會被串行化,嚴(yán)重影響性能,甚至使系統(tǒng) soft/hard lockup。這是一個知道的人很少的秘密。
為什么不用 percpu lock? 因為函數(shù)調(diào)用返回前可能發(fā)生 task 遷移
后來,那些煤炭奈兒(maintainer,妹忒訥兒估計也發(fā)現(xiàn)了問題,提交了一些派馳(patch),將hlist 改成了 CAS-based lock-free free list, 但人家自己也說了 Not the fastest thing in theworld under heavy contention, but simple and correct,詳見源文件
上面這些話,請自行比較不同內(nèi)核版本的 pre handler kretprobe 函數(shù)實現(xiàn)。該函數(shù)的注釋是:This kprobe pre handler is registered with every kretprobe. When probe hits it will set upthe return probe.
so?
別張口就來,掛 kretprobe 的前提是你理解它的副作用,而不是只知道個詞,特別是那些上了ebpf 毒癮的。
我討厭一些脫離一線很久卻又要彰顯自己懂得很多而對工人精確指點的經(jīng)理,這些經(jīng)理只給出一祈使句指導(dǎo),代碼腳本還是工人照著經(jīng)理意思去寫,經(jīng)理彰顯才華后,事了拂衣去。
經(jīng)理知道 kretprobe 可以修改函數(shù)返回值,但他大概不知道 kretprobe 隱藏的秘密。知道這些秘密的經(jīng)理不會指使工人用 kretprobe 修改返回值。經(jīng)理就好好當(dāng)經(jīng)理,做好資源和人力的分配調(diào)度,別天天混進(jìn)工人隊伍里瞎指揮,還美其名日技術(shù)導(dǎo)向,這就是扯淡。
kretprobe 的理論解法是將 return address 也固定,因此理論上可以截獲 ret 指令,進(jìn)入一個common stub hook 中判定該函數(shù)是不是需要被 hook,如果不需要這就返回,如果需要就先調(diào)用 hook 再返回,但依然會引入別的開銷,那么可以縮小替換范圍,只在 kretprobe function 附近搜索并替換 ret 指令。
工人提出用 kretprobe 修改 init cwnd,經(jīng)理會說這是非標(biāo)的方案,kprobe/kretprobe 更多只做 debug 和可觀測性,不能上線...但工人想修改 nit cwnd 卻沒方案時,經(jīng)理會讓工人用kretprobe 來改,絕口不提是否非標(biāo)。經(jīng)理知道 kprobe/kretprobe,但并不真懂,僅科普水平,或做過 demo,但也僅此。對技術(shù)細(xì)節(jié)非常感興趣又親自指揮細(xì)節(jié)的經(jīng)理不是合格經(jīng)理。但不知何時,不知為什么,工人們普遍覺得懂技術(shù)的經(jīng)理才合格,于是經(jīng)理們不得不去懂點技術(shù),顯得很 geek,這樣才是真經(jīng)理。很多經(jīng)理都會此地?zé)o銀三百兩式地強(qiáng)調(diào)自己寫過代碼,懂技術(shù),可也沒人問啊。
審核編輯:劉清
-
Linux系統(tǒng)
+關(guān)注
關(guān)注
4文章
594瀏覽量
27407 -
分配器
+關(guān)注
關(guān)注
0文章
194瀏覽量
25764 -
CAS
+關(guān)注
關(guān)注
0文章
34瀏覽量
15212 -
Hash算法
+關(guān)注
關(guān)注
0文章
43瀏覽量
7383
原文標(biāo)題:kprobe 和 kretprobe 隱藏的秘密
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論