2012-04-16 32 views
10

私は散在した情報のビットを見てきましたが、私は1つの最終的な答えには達していないようです。カーネルでゾンビスレッドをどのようにクリーンアップしますか?カーネル内のスレッドを適切に処理する方法は?

カーネル内のスレッドを正しく処理して正しい方法で処理するために、私はこの質問をもっと広くしたいと思います。 Linuxカーネルでスレッドを作成、終了、クリーンアップするにはどうすればよいですか?

は、私がこれまで持っていることはこれです:

thread_func: 
    exited = 0; 
    while (!must_exit) 
     do stuff 
    exited = 1; 
    do_exit(0) 

init_module: 
    must_exit = 0; 
    exited = 1; 
    kthread_run(thread_func, ...) /* creates and runs the thread */ 

cleanup_module: 
    must_exit = 1; 
    while (!exited) 
     set_current_state(TASK_INTERRUPTIBLE); 
     msleep(1); 
    /* How do I cleanup? */ 

私はクリーンアップ溶液に発見した最も近いものがrelease_taskですが、私はそれについて話をどこにも見つけることができませんでした。私はスレッドの機能がkthread_createkthread_runなどであると想像しましたが、kthread_joinまたはkthread_waitでなければなりませんでした。 do_waitもそうですが、struct task_struct *は受け付けていません。

さらに、do_exitが良いアイデアか、必要な場合はどちらかというとわかりません。誰かが、kthreadをどのように作成し、終了し、クリーンアップするべきかの最小限のスケッチを思い付くことができますか?

+2

私は、kthread_stop、またはkthread_should_stopがあることを覚えているようです。 –

+0

@MartinJames、誰か( 'cleanup_module')が' kthread_stop'を呼び出すまで、自分が(do_exit'を使って)終了したり、 'kthread_should_stop'をポーリングしたりすることができます。私は 'kthread_stop'もスレッドをクリーンアップするかどうかについてはどこにも見当たりませんでした。私が不思議に思うのは、(インターネット上の)人々が 'do_exit'を使うことを提案していれば、' do_exit'の後にスレッドをクリーンアップするべきではないはずです。 – Shahbaz

+0

ちなみに、[this](http://lwn.net/Articles/65178/)は私が決定的な答えに達することができないと言ったときの話です。そこには相容れないものがたくさんあります。 – Shahbaz

答えて

11

これを行う「正しい」方法の1つは、スレッド機能がkthread_should_stopであるかどうかをチェックし、停止する必要があるかどうかを単に戻すことです。

do_exitに電話する必要はなく、kthread_stopをモジュール出口機能から使用する予定がある場合は、そうしない方がいいでしょう。

あなたはkernel/kthread.c(Linuxカーネル3.3.1からの抽出物)にkthread_create_on_nodeのドキュメントを見て、これを見ることができます:

/**
* kthread_create_on_node - kthreadを作成します。
* @threadfn:signal_pending(現在)まで実行する関数です。
* @data:@threadfnのデータptr。
* @ node:メモリノード番号。
* @namefmt:スレッドのprintf形式の名前。
*
*説明:このヘルパー機能は、カーネル
* threadを作成し、名前を付けます。スレッドは停止します.wake_up_process()を使用して
*を起動します。 kthread_run()も参照してください。
*
*スレッドが特定のCPUに拘束されようとしている場合は、@nodeで*そのノード
を与え、kthreadスタック用のNUMAの親和性を得るか、あるいは与えるために-1。
*起床すると、スレッドは@dataを@dataとした@threadfn()を
*引数として実行します。 @threadfn( ')kthread_should_stop(')のいずれかすることができ、それは誰もがkthread_stop(呼び出しませんそのため
* スタンドアロンのスレッドである場合は、直接)(do_exitを呼び出す)、または
* リターンは(真ですつまり、
* kthread_stop()が呼び出されました。戻り値はゼロである必要があります
*または負のエラー番号。それはkthread_stop()に渡されます。
*
* task_structまたはERR_PTR(-ENOMEM)を返します。
*/

コメントはkthread_stopための存在である "マッチング" A:

(threadfnの場合)は、発信者がtask_structが離れてを行くことができないことを確認しなければならない、)(do_exit自体を呼び出すことができます。

(そして、私はあなたがそれを行うかどうかはわかりません - おそらくget_task_structstruct_taskにつかまっ。)

あなたが好きなものを買ってあげるスレッドの作成の道を歩く場合:

kthread_create           // macro in kthread.h 
    -> kthread_create_on_node        // in kthead.c 
    -> adds your thread request to kthread_create_list 
    -> wakes up the kthreadd_task 

kthreadd_taskreset_initinit/main.cに設定されています。これは、(kthread.cから)kthreadd機能を実行します

kthreadd             // all in kthread.c 
    -> create_kthread 
    -> kernel_thread(kthread, your_kthread_create_info, ...) 

そしてkthread機能自体がありません:

kthread 
    -> initialization stuff 
    -> schedule() // allows you to cancel the thread before it's actually started 
    -> if (!should_stop) 
    -> ret = your_thread_function() 
    -> do_exit(ret) 

を...だからyour_thread_functionは単に返す場合、do_exitはその戻り値で呼び出されます。あなた自身でそれをする必要はありません。

+0

タスク構造体はグローバル変数なので、どこにも置くことはできません。しかし、これは、スタンドアロンスレッドが 'do_exit()'を呼び出す場合(つまり 'kthread_stop'を呼び出さないでください)、クリーンアップを必要としないのでしょうか? – Shahbaz

+0

場所に行くことができます。タスク構造体が参照するタスクが完全に完了し、出口構造体によってタスク構造体が解放された場合、モジュールデータ内のコピーはダングリングポインタのようになります。使用できません。 – Mat

+0

そして、あなたのスレッドを 'kthread_stop'するつもりがなければ' do_exit'を呼び出すことができ、通常のクリーンアップが起こります。 _しかし、あなたのスレッドが何とかあなたのモジュールを使い果たしてしまったら、困ったことになります。 – Mat

関連する問題