kernel_thread() kthread_create()/kthread_run()カーネルスレッドの作成の違いと使用

3535 ワード

1. kernel_thread()関数カーネルスレッドの作成
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
        return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
                (unsigned long)arg, NULL, NULL);
}

コード解析でkernel_thread()はdo_を通りますfork()で作成されたスレッドです.2.6のバージョンでは、カーネルスレッドを作成する方法を駆動するために使用することもできます.
モジュールでは4.xのカーネルバージョンではドライバモジュールでは使用できません.つまりkernel_を使用したいということです.thread内でドライバをカーネルにコンパイル
スレッドを作成できます.insmod方式でカーネルスレッドを作成しようとすると、kernel_threadにはEXPORT_がありませんSYSMBOL
出る.
注意:kernel_threadが作成したスレッドの親プロセスはinitです
2. kthread_create()/kthread_run()関数作成スレッド
2つの方法でスレッドを作成する方法は、kthrad_run()はマクロ定義であり、最終的にkthread_に呼び出されます.create()
#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()もマクロ定義です
#define kthread_create(threadfn, data, namefmt, arg...) \
        kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)

struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
                                           void *data,
                                           int node,
                                           const char namefmt[], ...);

最終的にはkthread_に呼び出されますcreate_on_Node()関数、kthread_create_on_Node()は既にEXPORT_SYSMBOLが出てくるので、
カーネルで使用するか、ドライバモジュールで使用するかで、新しいスレッドを作成できます.
注意:kthreat_create()が作成した新しいスレッドの親プロセスはkthreaddで、kthread_createが作成したスレッドもコンテキスト環境をクリーンアップしました
だからkthread_create()は、比較的正統なスレッドを作成する方法です.kthread_の使用を推奨create()の方法でスレッドを作成します.
3.例
    kernel_threadの方式:4.xのバージョンカーネルのドライバモジュールで使用
#include 
#include 
#include 
#include 
#include 
MODULE_LICENSE("GPL");

#define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)

int my_kernel_thread(void *arg)
{
        int n = 0;

        while(1)
        {
                printk("%s: %d
",__func__,n++); ssleep(3); } return 0; } static int __init practiceCall(void) { printk("%s:
",__func__); kernel_thread(my_kernel_thread,NULL,CLONE_KERNEL); return 0; } static void __exit practiceCallExit(void) { printk("%s:
",__func__); } module_init(practiceCall); module_exit(practiceCallExit);


kthread_run方式でスレッドを作成するには:
#include 
#include 
#include 
#include 
#include 

static int   dmatest_work (void *data)
{
    allow_signal(SIGTERM);
    current->state = TASK_INTERRUPTIBLE;

	printk("New kernel thread run
"); return 0; } static int __init dmatest_init(void) { /* Schedule the test thread */ kthread_run (dmatest_work, NULL, "dmatest"); return 0; } static void __exit dmatest_exit(void) { return; } MODULE_LICENSE("Dual BSD/GPL"); module_init(dmatest_init); module_exit(dmatest_exit);