標籤:completion
LDD3之並發和競態-completion(完成量)的學習和驗證
首先說下測試環境:
Linux2.6.32.2
Mini2440開發板
一開始難以理解書上的書面語言,這裡《linux中同步例子(完成量completion)》舉了一個公交車上司機和乘客的例子還不錯,轉過來:
這是一個公交司機和售票員之間的線程調度,用於理解完成量,完成量是對訊號量的一種補充,主要用於多處理器系統上發生的一種微妙競爭。在這裡兩個線程間同步,只有當售票員把門關了後,司機才能開動車,只有當司機停車後,售票員才能開門。
如果還是不能夠理解就只能反覆的偵錯工具了,現在就把書上的例子使用起來,編譯出來completion.ko後進行如下步驟驗證
# 1.插入核心模組
insmod completion.ko
# 2.查看申請的次裝置號${MINOR}
cat /proc/devices | grep complete
# 3.建立裝置節點
mknod /dev/complete c ${MINOR} 0
# 4.首先開啟一個終端查看核心資訊輸出
cat /proc/kmsg
# 5.一個終端讀,會睡眠
cat /dev/complete
# 6,另一個終端寫
echo /dev/complete
# 7.查看輸出
<7>[22050.937732] process 28852 (cat) going to sleep
<7>[22093.994805] process 28866 (bash) awakening the readers...
<7>[22093.994817] awoken 28852 (cat)
下面來驗證LDD3上所說的:
1.wait_for_completion
注意wait_for_completion執行會一個非中斷的等待,如果沒有人來完成該任務,則會產生一個不可殺的進程。
驗證:
在運行了cat /dev/complete的時候就已經運行了wait_for_completion,並不運行寫程式,看不殺的進程是會不會存在。
通過嘗試確實是終止不了。
結論:wait_for_completion等待後如果沒人處理任務,那麼真的會產生一個不可殺的使用者進程,所以這個要小心使用。
2.complete和complete_all1)complete
在執行第3步(最下)後,只有第2步的cat被喚醒,第1個還在睡眠。
結論:和書的一樣。
2)complete_all
分了兩種情況來測試:
a.init_completion + complete_all
測試失敗!和書上的不照!
b.DECLARE_COMPLETION + complete_all
測試成功!
結論:complete只會喚醒一個等待線程,complete_all會喚醒所有等待線程,前提是靜態建立。
3.INIT_COMPLETION
根據書上描述這個是和complet_all配合使用的,那麼就測試一下驅動。
結論:使用INIT_COMPLETION進行重新初始化後,完成量可以多次使用。
4.complete_and_exit1).當核心準備清除該模組時,exit函數會告訴該線程退出並等待completion
這段描述不理解,實驗證明一下:
不過看了原型,有點眉目了,這個函數是要添加到exit_xxx函數中的,也就是當沒有完成時,是卸載不了的,但是為了卸載可以調用這個函數進行強制完成並卸載。檢驗一下,直接卸載:
會像圖中所示,提示“資源不可用!”。但如果在complete_cleanup中添加complete_and_exit後,同樣是“資源不可用!”說明假設失敗。
2).決定應用程式的退出碼?
同樣假設失敗,這裡填寫的是-1,但是應用程式退出碼仍然是0.不過有一點是確實可以代替使用!
3).核心多進程中子進程的退出碼
驅動群中群主是這樣說的。
結論:由於多進程還沒有掌握,這個先遺留下來,以後再來補充。
5.wait_for_completion_timeout
結論:不可以被中斷,到定時時間無人處理則自行結束。
6.wait_for_completion_interruptible
這個並沒有在LDD3中出現,但是很可以就是LDD3中注2中提到的可中斷版本.
結論:證實可以被ctrl+c中斷,即使用者空間的進程可以被殺死!
7.wait_for_completion_interruptible_timeout
結論:10s後如果沒有completion則自行中斷。
8.wait_for_completion_killable
從源碼和實驗結果上看不出和wait_for_completion_interruptible有任何區別,代碼是前者使用的是TASK_INTERRUPTIBLE後者使用的是 TASK_KILLABLE。
理論上:TASK_NTERRUPTIBLE 睡眠,可以被訊號喚醒;TASK_KILLABLE睡眠 只能被致命訊號喚醒。
不過現在沒有辦法區別哪些是致命訊號,哪些不是!
9.wait_for_completion_killable_timeout
同樣,從源碼和實驗結果上看不出和wait_for_completion_interruptible_timeout有任何區別,代碼是前者使用的是TASK_INTERRUPTIBLE後者使用的是 TASK_KILLABLE。
10.try_wait_for_completion
其返回值始終為0,不知道如何操作才用使其返回值為1.
結論:完全不明白它存在的意義!
11. completion_done
結論:無論有無等待者,判斷出來的都是有!進程或者代碼中都有把等待資訊去掉都無濟於事。