カーネル・スレッドの作成、使用、終了、および遅延マクロに基づく補足説明
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です.