有碰過kernel code的人大概多少都瞭解我標題的意思,kernel code很迷人,但很危險,稍不小心,就會被kernel panic拖進地獄
拿我最近review的code當例子,截取某一段code如下,這是一段相當簡單的kernel threading code,當kernel module被insert時,會開啟kernel thread執行thread_main這個function,當remove module時,會呼叫delete_thread把kernel thread砍掉,可以仔細看看thread_kill這段function,有沒有什麼問題
- void thread_kill( struct thread_t *th )
- {
-
- wait_queue_head_t queue;
- int try;
-
- try = 0;
-
- init_waitqueue_head( &queue );
-
- while ( ( atomic_read( &th -> dead ) == 0 ) && ( try < 5 ) )
- {
-
- atomic_set( &th -> kill, 1 );
- wake_up_interruptible( &th -> wait );
- interruptible_sleep_on_timeout( &queue, 100 );
-
- try++;
- }
- }
- void delete_thread( struct thread_t *del_thread )
- {
-
- thread_kill( del_thread );
- kfree( del_thread );
- }
- void thread_main( void *parameter )
- {
- //th=route_table_thread;th->usr_func=route_activate;
-
- struct thread_t *th;
-
- th = ( struct thread_t* )parameter;
- init_waitqueue_head( &th -> wait );
-
- atomic_set( &th -> kill, 0 );
- atomic_set( &th -> dead, 0 );
-
- do
- {
- interruptible_sleep_on( &th -> wait ); //push thread_main into sleep;
-
- th -> user_func();
-
- }
- while ( !atomic_read( &th -> kill ) );
-
- atomic_set( &th -> dead, 1 );
- }
thread_kill這個function寫的很怪,依照這段code的寫法,它會嘗試判斷th->dead是否被設1,和try是否小於5,如果條件不合,會繼續把th->kill設為1並再沉睡一段時間
問題點一:有沒有可能kernel thread已經結束但thread_kill還是繼續執行(Yes)
問題點二:有沒有可能kernel thread根本沒砍掉但程式已經執行到kfree( del_thread ) (Yes)
上面的問題二情況比較嚴重,如果沒有在rmmod時當機,那一定在將來的某個時間點當掉,為什麼?當kernel thread從沉睡中醒來(有可能被kernel signal interrupt),發現它的th->xxx…等變數都不見了,那執行th->user_func()的結果就是當機
針對kernel thread的終結方法,我這邊建議用waiting completion的方式,所以我建議這段程式更改如下
- static struct completion comp;
-
- void thread_kick( struct thread_t *th )
- {
- wake_up_interruptible( &th -> wait );
- }
-
- void thread_kill( struct thread_t *th )
- {
- atomic_set(&th->kill,1);
- thread_kick(some_thread_object);
- }
-
- void thread_main( void *parameter )
- {
- //th=route_table_thread;th->usr_func=route_activate;
-
- struct thread_t *th;
-
- th = ( struct thread_t* )parameter;
- init_waitqueue_head( &th -> wait );
- init_completion(&comp);
- //以下恕刪
- }
-
- void delete_thread( struct thread_t *del_thread )
- {
- thread_kill( del_thread );
- wait_for_completion(&comp);
- kfree( del_thread );
- }
Regular expression-跟brainfuck差不多的東西 (2009-11-13 15:37)
Reading file in kernel-簡單但實用 (2009-10-13 15:18)
Linux file system for dummies-只花你45分鐘 (2009-08-19 15:40)
OPENSSL-TCP SSL初心者之路 (2009-07-16 15:16)
NAPI與pure interrupt driver的效能比較 (2009-04-29 19:06)
usermode helper-來自kernel的呼喚 (2009-04-21 16:19)
kernel module memory detector-抓出有害的kernel module (2009-03-31 13:50)
readahead與posix_advise-預讀取是萬能靈丹? (2009-03-06 15:54)
Who call me – kernel版 (2009-02-19 10:53)