18

私はあちこちに散らばった情報を見てきましたが、最終的な答えを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_createスレッド関数は、などなので、またはkthread_runがあるはずだと想像しましたが、ありませんでした。また、可能性が高いように見えましたが、それはかかりません。kthread_joinkthread_waitdo_waitstruct task_struct *

さらに、それがdo_exit良いアイデアなのか、それとも必要なのかはわかりません。誰かが、kthreadを作成、終了、およびクリーンアップする方法の最小限のスケッチを思い付くことができますか?

4

1 に答える 1

19

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

を呼び出す必要はありません。モジュールの終了関数から呼び出すdo_exit場合は、おそらく呼び出さないでください。kthread_stop

kthread_create_on_nodeこれは、kernel/kthread.c(Linuxカーネル3.3.1からの抜粋)のドキュメントを見るとわかります。

/
***kthread_create_on_node-kthreadを作成します。
* @threadfn:signal_pending(current)まで実行する関数。
* @data:@threadfnのデータptr。
* @node:メモリノード番号。
* @namefmt:スレッドのprintfスタイルの名前。
*
*説明:このヘルパー関数は、カーネル
スレッドを作成して名前を付けます。スレッドは停止します。wake_up_process()を使用してスレッドを開始
します*。kthread_run()も参照してください。
*
*スレッドが特定のCPUにバインドされる場合は、そのノードを
* @nodeに指定して、kthreadスタックのNUMAアフィニティを取得するか、-1を指定します。
*ウェイクアップされると、スレッドは@dataを引数として@threadfn()を実行し
ます。@threadfn()は、誰もkthread_stop()を呼び出さないスタンドアロンスレッドの場合はdo_exit()を直接呼び出すか、
* 'kthread_should_stop()'がtrueの場合(つまり * kthread_stop()が呼び出された場合)に戻ることができます。 。戻り値はゼロ *または負のエラー数である必要があります。kthread_stop()に渡されます。 * * task_structまたはERR_PTR(-ENOMEM)を返します。 * /





「一致する」コメントが存在しkthread_stopます:

threadfn()がdo_exit()自体を呼び出す可能性がある場合、呼び出し元はtask_structが消えないようにする必要があります

(そして、私はあなたがそれをどのように行うのかわかりません-おそらくで保持しstruct_taskますget_task_struct。)

スレッド作成のパスをたどると、次のようになります。

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_taskに設定されinit/main.cていreset_initます。関数を実行しkthreaddます(からkthread.c

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その戻り値で呼び出されます。自分でやる必要はありません。

于 2012-04-16T16:59:36.900 に答える