kthread_runマクロ


Rev.2を表示中。最新版はこちら

kthread_runマクロはカーネルスレッドを作成し、起動(アクティブキューに接続)に繋ぐ。カーネルスレッドはユーザプロセスのマルチスレッドと同じような感じ。異なるのは、ユーザプロセスの親もプロセスとして動作するが、カーネルスレッドの親は、カーネル本体で、このカーネルはプロセスとして動作しているわけでない。

lkmで/procのコールバック処理を実装した場合、この関数はカーネル上の1パスの関数にしか過ぎない。従ってその処理が終了しても(return)、実態はカーネル内に存在し続ける。しかしカーネルスレッドだと、カーネルパスの延長上で動作するのでなく、カーネルからスケジュールされるプロセスとして動作することになる。従って、その処理が終了したらプロセスとして存在しなくなる。(ただしメモリ上に存在する)

従って、lkmから作成したカーネルスレッド、lkmをrmmmodする時に、その前にそのカーネルスレッドを削除する必要がある。この処理を忘れると、実在しないカーネルスレッドに起動がかかるって事になる。(たぶん)

カーネルスレッド内の処理は、サービスの間retできない。上記のごとくretするとプロセスが削除されてしまう。カーネルの実装的には、カーネルスレッドとなる関数の復帰後に、do_exit関数がコールされるようになっている。

以下はlkm下のカーネルスレッドでjiffiesを表示させるサンプル。
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/jiffies.h>

MODULE_AUTHOR("y.kitamura");
MODULE_DESCRIPTION("kthread test");
MODULE_LICENSE("GPL");

static struct task_struct *kthread_tsk;
static void my_kthread_main(void)
{
       set_current_state(TASK_INTERRUPTIBLE);
       schedule_timeout(HZ);
       printk("kthread:%ld\n", jiffies);
}

static int my_kthread(void *arg)
{
       printk("HZ:%d\n", HZ);
       while (!kthread_should_stop()) {
               my_kthread_main();
       }
       return 0;
}

static int __init kthread_test_init(void)
{
       kthread_tsk = kthread_run(my_kthread, NULL, "param %s&%d", "test", 123);
       if (IS_ERR(kthread_tsk))
               return -1;
       printk("pid->%d:prio->%d:comm->%s\n",
               kthread_tsk->pid,
               kthread_tsk->static_prio,
               kthread_tsk->comm);
       return 0;
}

static void __exit kthread_test_exit(void)
{
       kthread_stop(kthread_tsk);
}

module_init(kthread_test_init);
module_exit(kthread_test_exit);
実行結果
[root@localhost lkm]# dmesg
[ 3991.325662] pid->7712:prio->120:comm->param test&123
[ 3991.326134] HZ:1000
[ 3992.326479] kthread:3692326
[ 3993.326179] kthread:3693326
[ 3994.326339] kthread:3694326
[ 3995.328651] kthread:3695328
rmmod時に、kthread_should_stopがコールされる様にする必要がある。kthread_should_stopはkthread->should_stop = 1として、カーネルスレッドを起床させ、wait_for_completionでスレッドが削除されるまでウエイトする。そして後、モジュールを削除する事が可能になる。
int kthread_should_stop(void)
{
       return to_kthread(current)->should_stop;
}

int kthread_stop(struct task_struct *k)
{
       struct kthread *kthread;
       int ret;

       trace_sched_kthread_stop(k);
       get_task_struct(k);

       kthread = to_kthread(k);
       barrier(); /* it might have exited */
       if (k->vfork_done != NULL) {
               kthread->should_stop = 1;
               wake_up_process(k);
               wait_for_completion(&kthread->exited);
       }
       ret = k->exit_code;

       put_task_struct(k);
       trace_sched_kthread_stop_ret(ret);

       return ret;
}

実装は後日に・・・

最終更新 2012/07/24 17:10:05 - north
(2012/07/24 17:03:22 作成)


検索

アクセス数
3575115
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。