標籤:

抽離設計邏輯

今天有人來找我討論一個程序怎麼改。他這個程序包括三個Linux內核模塊,有點類似Linux的device-bus-driver的模型:包括一組engine,一個框架,和一組app:

大概的意思是,app和engine都可以註冊給框架,如果框架發現兩者需求匹配,就會引起兩者的關聯(attach),從而讓app可以使用engine的能力。

他們在測試的時候發現,這個程序在執行複雜的隨機插入,刪除的過程後,有一定的幾率發生指針索引異常,所以他們想和我討論一下怎麼修改的問題。

給我講這個背景的兄弟是大體是這樣描述這個問題的:你看,insmod app1.ko的時候,它註冊給框架,這裡加入到一個鏈表裡,然後這個鏈表馬上要查詢,查詢的時候如果遇到engine1.ko插入進來,框架會進入這個流程,這時如果卸載engine1.ko,就會XXXX,這樣app1就索引不到engine1的這個指針了,然後我把這個加入鏈表的操作改到這裡,那麼……

我聽了幾分鐘,就開始頭腦發麻了。我說,你不要一上來給我說這個鏈表,那個結構的,我們先來說說你說的這個東西的「情理」好不好?

我們有三個(種)對象。先看app和框架的關係:app註冊給框架,app一定提供了數據(指針)給框架,那麼app.init_module()註冊的時候,就必須把框架鎖死在內存中,所以,框架的註冊函數必須module_get(THIS)把自己鎖在內存中,如果這個過程不成功,註冊函數必須保證,app的數據沒有交給框架,框架也沒有被module_get()。這裡的邏輯無懈可擊吧?

engine和框架的關係也是一樣的。

好了,現在討論app和engine同時插入的情況:怎麼看這應該不正常,但不光我們不正常,Linux的其他內核模塊也不會正常對吧?所以簡單確認一下,就會發現,Linux已經有鎖保證module_init和module_exit()全部是串列的。兩者的先後行為在這個上面也是無懈可擊的對吧?

最後是app和engine的關聯:如果兩者互相看到對方的數據了,兩者肯定有對方的指針,誰都不能簡單被rmmod。如果把兩者都module_get了,兩個都卸不掉。那麼我們很容易就得這樣決定:一旦attach,必須讓其中一方把另一方module_get()了,然後沒有被get的一方就可以卸載,並在module_exit()中負責deatch對方的數據結構,讓兩者在數據上不再發生關聯,然後才module_put()對方。這樣,這個邏輯也無懈可擊吧?

好了,現在你可以跟我談你那些鏈表的事情了……

你看,很多人問,為什麼不直接寫代碼而要做設計。這就是原因——設計是可以分離代碼邏輯來單獨討論的。

推薦閱讀:

氣和深度學習1:綜述
自然,守弱和Plan B
Specification的寫法問題
找到道法自然的「度」
淺談高內聚低耦合

TAG:軟體架構 |