LoginSignup
4
4

More than 5 years have passed since last update.

[Linux][kernel module] カーネルモジュール内でkthreadを作成する

Last updated at Posted at 2017-05-11

カーネルモジュールの中でkthreadを作成する方法メモ

ローダブルカーネルモジュールの作成とビルド方法に関しては以下などを参考にしてください。
[Linux][kernel module] 簡単なローダブルカーネルモジュールのビルドとロード - Qiita

ソース

testmod.c
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kthread.h>

MODULE_LICENSE("MIT");

struct task_struct *k;

static void kthread_main(void)
{
    schedule();
}

static int kthread_func(void* arg)
{
    printk(KERN_INFO "[%s] start kthread\n", k->comm);

    while (!kthread_should_stop()) {
        kthread_main();
    }

    printk(KERN_INFO "[%s] stop kthread\n", k->comm);

    return 0;
}

static int __init testmod_init(void)
{
    printk(KERN_INFO "driver loaded\n");

    k = kthread_run(kthread_func, NULL, "testmod kthread");

    return 0;
}

static void __exit testmod_exit(void)
{
    kthread_stop(k);
    printk(KERN_INFO "driver unloaded\n");
}

module_init(testmod_init);
module_exit(testmod_exit);

基本的な流れ

メイン

  • init関数で kthread_run(3, ...) マクロにてスレッドの作成を行う
  • exit関数で kthread を終了する

kthread_run(3, ...) マクロは以下のようになっているとのことです。

kthread_run
#define kthread_run(threadfn, data, namefmt, ...)                          \
({                                                                         \
       struct task_struct *__k                                            \
               = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
       if (!IS_ERR(__k))                                                  \
               wake_up_process(__k);                                      \
       __k;                                                               \
})

kthread_create(3, ...) を実行後、wake_up_process(1) が実行されています。
namefmt については、printfのようにフォーマット指定子が使用でき、変数を使用したスレッド名を設定することができます。

kthread側

  • 新しいスレッドから、kthread_funcが呼び出される
  • 終了まで繰り返し呼び出されるループを作成(スレッドの終了は kthread_should_stop() で検出する)
  • schedule() にて一定期間スリープ

TODO: schedule() の動作については要調査

実行例

実行例
$ sudo insmod testmod.ko
$ ps aux | head -1 && ps auwx | grep "\[testmod kthread\]"
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     28716 84.8  0.0      0     0 ?        R    23:14  16:07 [testmod kthread]
$ sudo rmmod testmod.ko
$ dmesg | tail
[187744.330108] driver loaded
[187744.330326] [testmod kthread] start kthread
[187812.178718] [testmod kthread] stop kthread
[187812.178743] driver unloaded

カーネルモジュール内でのスレッドの開始と終了がされていることが確認できました。
psコマンドで作成したスレッドの確認をすることもできました、

関連

[Linux][kernel module] 簡単なローダブルカーネルモジュールのビルドとロード - Qiita
[Linux][kernel module] ローダブルカーネルモジュールのロード時に引数でパラメータを渡す方法 - Qiita
[Linux][kernel module] kthreadの実行CPUを指定/制限する - Qiita

参考

カーネルスレッドのループと停止をカーネルモジュールで実装 - 人間とウェブの未来
kthread_runマクロ - Linuxの備忘録とか・・・(目次へ)
[PDF] kthreads

4
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4