我们可以使用kthread_run()去创建一个内核线程并启动它,当一个内核线程被启动之后就会不停的运行下去除非其他线程调用了kthread_stop来结束这个线程,但是我们在调用kthread_stop之前一定要检查需要被终止的线程是否还在运行,如果kthread_stop调用了一个未运行的线程造成的后果是完犊子的(我这里做的实验就是导致我的虚拟机完全卡死,原因是kthread_stop调用的参数是个NULL),为了避免这种现象的出现还有一个重要的函数:kthread_should_stop,他的返回值是should_stop标志,当返回1时表明这个线程时可以被终止的。下面我们用一小段代码来说明下kthread的具体使用方法:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
MODULE_LICENSE("Dual BSD/GPL");
static struct task_struct *tsk;
static int thread_function(void *data)
{
int time_count = 0;
do {
printk(KERN_INFO "thread_function: %d times", ++time_count);
msleep(1000);
}while(!kthread_should_stop());
return time_count;
}
static int kai_init(void)
{
printk(KERN_INFO "Hello, world!\n");
tsk = kthread_run(thread_function, NULL, "mythread%d", 1); //创建并启动线程
if (IS_ERR(tsk)) {
printk(KERN_INFO "create kthread failed!\n");
}
else {
printk(KERN_INFO "create ktrhead ok!\n");
}
return 0;
}
static void kai_exit(void)
{
printk(KERN_INFO "Hello, exit!\n");
if (!IS_ERR(tsk)){
int ret = kthread_stop(tsk); //将should_stop设为1并发送信号给进程
printk(KERN_INFO "thread function has run %ds\n", ret);
}
}
module_init(kai_init);
module_exit(kai_exit);
这里我们通过模块加载和卸载的方式去调用了kai_init,并在kai_init中使用kthread_run创建了线程thread_function。在thread_function中没有做别的事情只是一直打印一句话为了减少cpu的负荷,设置了每次打印的间隔时间时1s。最后通过卸载模块的方式调用了kthread_stop去结束这个线程。
编译运行后我们可以得到kthread.ko:
使用insmod 加载这个模块:
使用dmesg命令查看打印信息:
可以看到创建的线程已经在工作了输出了打印信息。
卸载模块并再次使用dmesg查看打印信息:
可以看到线程被终止。