核心線程的退出要從建立開始,下面是kernel_thread的建立過程
中regs.ip = kernel_thread_helper,也就是說建立的核心線程從kernel_thread_helper開始運行,
kernel_thread_helper函數定義如下:
其中的關鍵是,call *%rsi,調用的是kernel_thread中的fn參數(函數指標),調用結束後的語句是
call do_exit,調用的是系統的do_exit函數退出進程(線程)。
我們知道do_exit()函數會釋放部分不需要的系統資源,然後將task_state設為ZOMBIE狀態,然後通知父進程,
通過前一篇博文我們知道所有核心線程的父進程都是2號核心線程,而2好核心線程並沒有處理訊號。
所以核心線程結束後會一直處於ZOMBIE狀態。直到一種情況的發生。
kthread_stop的調用----徹底殺死核心線程
kthread_stop的定義如下:
核心在於,kthread_stop會設定kthread結構提的should_stop標誌為1,然後喚醒核心線程,
等待其結束,最後調用put_task_struct來釋放核心線程的task_struct,此時徹底釋放了核心線程
所佔的系統資源。
有一點值得注意,那就是要想kthread_stop能夠殺死正在執行的核心線程,則核心線程必須檢測
kthread->should_stop標誌位,如果被標記了就返回才可以。
所有的核心線程如果想徹底釋放,必須外部調用kthread_stop才行,由於2號核心線程(核心線程的父親)
的存在並且不處理訊號,導致如果沒有外界調用kthread_stop函數,則結束的核心線程將一直處於ZOMBIE狀態。
驅動編寫時這一點要小心在意!!一般說來,核心線程一旦啟動就會跟隨系統始終,除非模組被移除。所以這個特點
決定害處不大。
以上討論的是通過系統調用kthread_create來建立的核心線程的建立和退出機制,
還有另外一種建立方式,就是kernel_thread調用來建立,二者的區別如下:
(1)最重要的不同:kthread_create建立的核心線程有乾淨的上下文環境,適合於驅動模組或使用者空間的程式建立核心線程使用,不會把某些核心資訊暴露給使用者程式
(2)二者建立的進程的父進程不同: kthread_create建立的進程的父進程被指定為kthreadd, 而kernel_thread建立的進程可以是init或其他核心線程。