总结
比如06中的spi驱动,因为是异步处理数据避免堵塞
这时候把线程当作一个工人,分派任务,分配处理任务的方法
数据结构
图中一个kthread_worker代表一个工人 kthread_worker->task是对应的线程, 也就是把这个线程抽象为一个工人
kthread_work链表代表对应的工作任务 kthread_work->func 处理工作的函数
struct kthread_worker {
unsigned int flags;
spinlock_t lock; //保护work_list链表的自旋锁
struct list_head work_list; //kthread_work 链表,相当于流水线
struct list_head delayed_work_list; // 延时工作 list
struct task_struct *task; //为该kthread_worker执行任务的线程对应的task_struct结构,把这个线程抽象为工人
struct kthread_work *current_work; //当前正在处理的kthread_work
};
struct kthread_work {
struct list_head node; //kthread_work链表的链表元素
kthread_work_func_t func; //执行函数,该kthread_work所要做的事情
struct kthread_worker *worker; //处理该kthread_work的kthread_worker
/* Number of canceling calls that are running at the moment. */
int canceling;
};
简单使用
初始化流水线工人kthread_worker
struct kthread_worker hi_worker; // 声明一个kthread_worker
kthread_init_worker(&hi_worker); // 初始化kthread_worker
工人里面的内核线程 需要单独初始化 kthread_worker->task
//kthread_run()这个函数来创建一个内核线程
//线程里面的执行函数 kthread_worker_fn()是固定的 这个函数会去调用具体工作里面的kthread_work->func
struct task_struct *kworker_task = kthread_run(kthread_worker_fn, &hi_worker, "nvme%d", dev->instance);
准备 kthread_work
定义一个 kthread_work 并初始化他,为他指定工作函数 xxx_work_fn:
struct kthread_work hi_work;//声明一个kthread_work
kthread_init_work(&hi_work, xxx_work_fn); //初始化kthread_work,设置work执行函数.
启动 work
上面两步准备好了 worker 和 work,如果有需要处理的 work 的话,那么需要把这个 work 挂到 worker 上:
kthread_queue_work(&hi_worker, &hi_work);
flush 指定 worker 上所有 work
将指定的 worker 上的所有 work 全部执行
kthread_flush_worker(&hi_worker);
停止当前的线程
kthread_stop(kworker_task);
详细过程
创建了线程后 给这个线程增加的指定函数kthread_worker_fn()
差不多是循环看这个工人的工作链表,有的话就调用函数对这个工作处理,把这个工作从链表上删除
kthread_run(kthread_worker_fn, &hi_worker, "nvme%d", dev->instance);
kthread_worker_fn(void *worker_ptr)
struct kthread_worker *worker = worker_ptr;//拿到worker指针
worker->task = current; //同时对worker指针的task(线程)进行初始化,为当前运行的线程或进程
repeat: //死循环,一直处理工人的work链表的工作
set_current_state(TASK_INTERRUPTIBLE); //设置当前线程可中断
work = NULL;
if (!list_empty(&worker->work_list)) //遍历工作链表是否为空
work = list_first_entry(&worker->work_list,struct kthread_work, node);//找到工作
list_del_init(&work->node);//进行删除
worker->current_work = work//把流水线工人的当前工作指向work
if (work) { //工作不为空
__set_current_state(TASK_RUNNING);//设置当前线程正在运行
work->func(work); //使用work上面的处理工作函数
goto repeat;
啊啊