Tramp data In Kernel
表象
內核中經常見到某些函數有很多的參數,而且這些參數會一級一級往下面傳遞,部分參數可能只有最深一級函數才會用到,但卻被傳遞了很多級,其中不乏一些bool型的參數,比如如下的代碼流程,6個參數傳遞了很多級。
kvm_mips_map_page() -> gfn_to_pfn_prot() -> __gfn_to_pfn_memslot() ->hva_to_pfn() -> hva_to_pfn_slow()
對于這樣的代碼,大家覺得如何?這樣的代碼是否有毛病?
這叫什么?
對于逐級傳遞的參數,業界有專門的術語對應,叫Tramp data,其標準定義為:
(programming) Data which is passed via one function to another, and not otherwise used by the first.有問題么?
Tramp data是一種典型的代碼壞味道,其表示:
一些代碼需要了解相隔遙遠的另一些代碼提供的信息,需要通過中間媒介來傳遞這些信息。其帶來典型的問題如:
另外,內核中經常使用bool類型的tramp data作為參數。bool類型的參數本身也是一種壞味道,會使代碼的可讀性變差。 再者,參數過多也是一種壞味道,問題很多,比如使函數變得復雜、職責不單一、難以測試等。不專門討論~
為什么出現?
Tramp data出現的一個典型場景是用于代替全局變量,我們知道不合適的全局變量也是一種壞味道,對于全局變量的重構,最簡單的方法就是使用tramp data了,這個很容易理解。
另一些場景,比如內核中,一些功能實現復雜,有很長的調用鏈,在底層的函數中需要了解的信息,通常都使用這樣的tramp data來傳遞。
如果解決?
最基本的處理方式是:
至少需要保證每一級函數傳遞的參數名稱是相同的,保證可讀性。還有一些建議,比如使用單例來重構,但單例本質上還是全局數據,又走回去了,但是一些情況下,全局變量可能比tramp data更好一些~
進一步的處理,可能就涉及代碼自身設計的問題了,出現tramp data可能說明代碼在設計上出了問題,理論上,整潔代碼要求
- 函數職責單一。單一職責的函數,應該不會有太多的參數,tramp data出現的幾率也小。
- 低耦合。距離遙遠的代碼間的依賴,說明其耦合不低。
- 數據聲明和數據使用的距離盡量短。
- 抽象層次一致。個人理解,可能隱含的意思包括函數依賴的數據應當最好在同一抽象層次中。
重構理論中,建議用:去除中間人和提取類的方法來重構,具體操作需要針對具體的情況處理了,實際操作比理論可能復雜得多。
內核中的困惑
內核中類似這樣的比比皆是,好像已經形成了一種習慣和風格,編寫新代碼時往往會參考已有代碼方式,導致新代碼中仍然有很多這樣的情況。
將那前面的代碼流程看,6個參數中,幾乎所有的數據都可以從vcpu中獲取,按整潔代碼和重構理論中的建議,對于過多參數的重構,典型的處理方式就是抽象,如將相關的參數抽象成對象傳遞,對應內核中的這種情況,理論上,看似僅傳遞一個vcpu參數應該是更佳的選擇,但代碼中偏偏提取了vcpu中的各種數據,然后將其逐級傳遞。
這是內核中的普遍現象,可能原因是:為了更好性能。 這可能也是內核代碼跟用戶態程序相比,能不做clean code的最好的借口了~
內核社區中曾經也發起過關于內核代碼clean code的爭論,但最終沒有結果,至今,內核中包含上千萬行代碼,早已形成了自己的code style了,不能說其代碼不clean,可能需要你換個角度來看~
原文地址:?https://happyseeker.github.io/kernel/2017/01/20/tramp-data-in-kernel.html
總結
以上是生活随笔為你收集整理的Tramp data In Kernel的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 彻底弄懂dalvik字节码【三】
- 下一篇: Mips KVM TrapEmulate