05

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

总结

比如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;

啊啊

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6