linux 内核线程

来源:互联网 发布:统计数据库 编辑:程序博客网 时间:2024/05/16 15:43

linux内核可以看做是一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求)。内核需要多个执行流并行,为了防止可能的阻塞,多线程化是必要的。内核线程就是内核的分身,一个分身可以处理一件特定的事情。Linux内核使用内核线程来将内核分成几个功能模块,像kswapd、kflushd等等,这在处理异步事件如异步IO时特别有用,像我们在内核中可以通过创建一个线程来查询按键状态。内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间。支持多线程的内核叫多线程内核(Multi-Threads kernel)。内核线程的调度由内核负责,一个内核线程处于阻塞状态时不影响其他的内核线程,因为其实调度的基本单位。

查看linux内核线程文件kthread.h可以发现内核线程有以下几个函数

1、创建内核线程

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

注意:通过kthread_create创建的内核线程不会立即运行,还需要调用wake_up_process唤醒线程,即是kthread_run函数

2、创建内核线程并运行

/** * kthread_run - create and wake a thread. * @threadfn: the function to run until signal_pending(current). * @data: data ptr for @threadfn. * @namefmt: printf-style name for the thread. * * Description: Convenient wrapper for kthread_create() followed by * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM). */#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_run)是在kthread_create的基础上加了wake_up_process实现的

3、将内核线程绑定到某个CPU

/** * kthread_bind - bind a just-created kthread to a cpu. * @k: thread created by kthread_create(). * @cpu: cpu (might not be online, must be possible) for @k to run on. * * Description: This function is equivalent to set_cpus_allowed(), * except that @cpu doesn't need to be online, and the thread must be * stopped (i.e., just returned from kthread_create()). */void kthread_bind(struct task_struct *k, unsigned int cpu){BUG_ON(k->state != TASK_INTERRUPTIBLE);/* Must have done schedule() in kthread() before we set_task_cpu */wait_task_inactive(k);set_task_cpu(k, cpu);k->cpus_allowed = cpumask_of_cpu(cpu);}

4、停止内核线程

/** * kthread_stop - stop a thread created by kthread_create(). * @k: thread created by kthread_create(). * * Sets kthread_should_stop() for @k to return true, wakes it, and * waits for it to exit.  Your threadfn() must not call do_exit() * itself if you use this function!  This can also be called after * kthread_create() instead of calling wake_up_process(): the thread * will exit without calling threadfn(). * * Returns the result of threadfn(), or %-EINTR if wake_up_process() * was never called. */int kthread_stop(struct task_struct *k){int ret;mutex_lock(&kthread_stop_lock);/* It could exit after stop_info.k set, but before wake_up_process. */get_task_struct(k);/* Must init completion *before* thread sees kthread_stop_info.k */init_completion(&kthread_stop_info.done);smp_wmb();/* Now set kthread_should_stop() to true, and wake it up. */kthread_stop_info.k = k;wake_up_process(k);put_task_struct(k);/* Once it dies, reset stop ptr, gather result and we're done. */wait_for_completion(&kthread_stop_info.done);kthread_stop_info.k = NULL;ret = kthread_stop_info.err;mutex_unlock(&kthread_stop_lock);return ret;
}

5、内核线程是否停止

/** * kthread_should_stop - should this kthread return now? * * When someone calls kthread_stop() on your kthread, it will be woken * and this will return true.  You should then return, and your return * value will be passed through to kthread_stop(). */int kthread_should_stop(void){return (kthread_stop_info.k == current);}

6、内核线程测试例子

#include <linux/kthread.h>#include <linux/module.h>static struct task_struct *MyThread = NULL;static int MyPrintk(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()) {printk("%s\n", mydata);msleep(1000);}kfree(mydata);return 0;}static int __init init_thread(void){MyThread = kthread_run(MyPrintk, "hello world", "mythread");return 0; }static void __exit exit_thread1(void){if (MyThread) {printk("stop MyThread\n");kthread_stop(MyThread);}}module_init(init_thread);module_exit(exit_thread1);


原创粉丝点击