基于内核线程的创建、使用和退出以及延时宏的补充说明介绍
基于内核线程的创建、使用和退出以及延时宏的补充说明介绍
发布时间:2016-12-28 来源:查字典编辑
摘要:相关函数:kthread_create():创建内核线程复制代码代码如下:structtask_struct*kthread_create(...

相关函数:

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_process(),然后通过此函数运行线程。

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_process()组成。

复制代码 代码如下:

#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 –p 线程号

可以使用下面命令来查找线程号:

ps aux|grep 线程名

示例程序:使用模块加载内核线程,实现每1s在内核中打印字符。

(makefile略去,和以前一篇博文一样的写法。)

复制代码 代码如下:

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/sched.h> //wake_up_process()

#include <linux/kthread.h> //kthread_create(),kthread_run()

#include <linux/err.h> //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,'',strlen(data)+1);

strncpy(mydata,data,strlen(data));

while(!kthread_should_stop())

{

SLEEP_MILLI_SEC(1000);

printk("%sn",mydata);

}

kfree(mydata);

return 0;

}

static int __init kernel_thread_init(void)

{

int err;

printk(KERN_ALERT "Kernel thread initalizing...n");

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 <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/sched.h> //wake_up_process()

#include <linux/kthread.h> //kthread_create(),kthread_run()

#include <linux/err.h> //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,'',strlen(data)+1);

strncpy(mydata,data,strlen(data));

while(!kthread_should_stop())

{

SLEEP_MILLI_SEC(1000);

printk("%sn",mydata);

}

kfree(mydata);

return 0;

}

static int __init kernel_thread_init(void)

{

int err;

printk(KERN_ALERT "Kernel thread initalizing...n");

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.n");

kthread_stop(my_task);

printk(KERN_ALERT "Canceled.n");

}

}

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_INTERRUPTIBLE)即可。

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新C语言学习
热门C语言学习
编程开发子分类