カーネル・スレッドの作成、使用、終了、および遅延マクロに基づく補足説明

5911 ワード

関連関数:
kthread_create():カーネルスレッドの作成
 
  
struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...);  kernel thread kernel_thread , daemonize init , completion 。 , kthread_create。

スレッドが作成されると、すぐに実行されるのではなく、kthread_をcreate()が返すtask_structポインタwake_up_プロセス()を実行し、この関数を使用してスレッドを実行します.
 
kthread_run():スレッドの関数を作成して起動します.
 
  
struct task_struct *kthread_run(int (*threadfn)(void *data),void *data,const char *namefmt, ...); , kthread_create() wake_up_process() 。

実際にはマクロですkthread_create()とwake_up_プロセス組成.
 
  
#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_stop():スレッドに信号を送信することで、終了させる.
 
  
int kthread_stop(struct task_struct *thread);

スレッドが起動すると、スレッドがdo_をアクティブに呼び出さない限り、スレッドは常に実行されます.exit関数、または他のプロセス呼び出しkthread_stop関数は、スレッドの実行を終了します.
しかし、スレッド関数が非常に重要なタスクを処理している場合は、中断されません.もちろん、スレッド関数が戻ってこない場合、信号をチェックしない場合は、停止しません.
同時にkthread_を呼び出すstop関数の場合、スレッド関数は既に実行済みではありません.そうでなければkthread_stop関数はずっと待機します.
 
カーネルスレッドの一般的なフレームワーク
int threadfunc(void *data){
        …
        while(1){
               set_current_state(TASK_UNINTERRUPTIBLE);
               if(kthread_should_stop()) break;
if(){//条件が真である
//業務処理を行う
               }
Else//条件は偽
//CPUに他のスレッドを実行させ、指定された時間内に再スケジュールさせる
                      schedule_timeout(HZ);
               }
        }
        …
        return 0;
}
 
スレッド関連テストコマンド
topコマンドを使用して、カーネルスレッドを含むスレッドのCPU使用率を表示できます.コマンドは次のとおりです.
top�Cpスレッド番号
スレッド番号を検索するには、次のコマンドを使用します.
ps aux|grepスレッド名
 
例示的なプログラム:モジュールを使用してカーネルスレッドをロードし、1 sごとにカーネルに文字を印刷します.
△makefileは省略して、前のブログと同じ書き方をしています.
 
  
#include
#include
#include
#include    //wake_up_process()
#include //kthread_create(),kthread_run()
#include //IS_ERR(),PTR_ERR()
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)\
do { \
long timeout = (nMilliSec) * HZ / 1000; \
while(timeout > 0) \
{ \
timeout = schedule_timeout(timeout); \
} \
}while(0);
#endif

static struct task_struct *my_task = NULL;

static int my_kthread(void *data) 

    char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
    memset(mydata,'\0',strlen(data)+1);
    strncpy(mydata,data,strlen(data));
    while(!kthread_should_stop())
    {
        SLEEP_MILLI_SEC(1000);
        printk("%s
",mydata);
    }
    kfree(mydata);
    return 0;

static int __init kernel_thread_init(void)
{
    int err;
    printk(KERN_ALERT "Kernel thread initalizing...
");
    my_task = kthread_create(my_kthread,"hello world","mythread");
    if(IS_ERR(my_task)){
        printk("Unable to start kernel thread./n");
        err = PTR_ERR(my_task);
        my_task = NULL;
        return err;
    }
    wake_up_process(my_task);
    return 0;#include
#include
#include
#include    //wake_up_process()
#include //kthread_create(),kthread_run()
#include //IS_ERR(),PTR_ERR()
#ifndef SLEEP_MILLI_SEC
#define SLEEP_MILLI_SEC(nMilliSec)\
do { \
long timeout = (nMilliSec) * HZ / 1000; \
while(timeout > 0) \
{ \
timeout = schedule_timeout(timeout); \
} \
}while(0);
#endif

static struct task_struct *my_task = NULL;

static int my_kthread(void *data) 

    char *mydata = kmalloc(strlen(data)+1,GFP_KERNEL);
    memset(mydata,'\0',strlen(data)+1);
    strncpy(mydata,data,strlen(data));
    while(!kthread_should_stop())
    {
        SLEEP_MILLI_SEC(1000);
        printk("%s
",mydata);
    }
    kfree(mydata);
    return 0;

static int __init kernel_thread_init(void)
{
    int err;
    printk(KERN_ALERT "Kernel thread initalizing...
");
    my_task = kthread_create(my_kthread,"hello world","mythread");
    if(IS_ERR(my_task)){
        printk("Unable to start kernel thread./n");
        err = PTR_ERR(my_task);
        my_task = NULL;
        return err;
}

static void __exit kernel_thread_exit(void)
{
    if(my_task){
        printk(KERN_ALERT "Cancel this kernel thread.
");
        kthread_stop(my_task);
        printk(KERN_ALERT "Canceled.
");
        }
}


module_init(kernel_thread_init);
module_exit(kernel_thread_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("anonymous");


補足:
この遅延マクロは、場合によってはカーネルスレッドCPUの占有率が高すぎる場合がある.対schedule_によるとtimeout()ソースコードの分析は、スレッドをTASK_にする周期にすぎない.RUNNING状態、このスレッドは本格的な睡眠はありません.解決策:whileサイクルの先頭にset_を追加current_state(TASK_INTERUPTIBLE)でOKです.