news 2026/2/25 21:00:51

Linux驱动学习笔记:SPI子系统中的内核线程初始化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux驱动学习笔记:SPI子系统中的内核线程初始化
进入(KWorker_Thread)
  • 来源:SPI 子系统的标准机制。在__spi_sync->__spi_queued_transfer内部,代码会将消息挂入队列,并无条件地唤醒后台工作线程(kthread_queue_work)。
  • 时机:虽然用户线程已经开始干活了,但后台线程(kworker)被唤醒需要调度时间(几十微秒到几毫秒)。当它终于醒来时,就发生了第二次进入。
  • 结果:它进入函数后,发现master->cur_msg不为空(因为用户线程正在处理),或者master->busy为真。于是它什么也没做,直接退出

kthread_queue_work明明只是把一个“任务”扔进队列,为什么它最终执行的代码偏偏会是__spi_pump_messages这个函数?它是怎么绑定上去的?

答案是:在 SPI 控制器初始化(注册)阶段,这个“任务”就已经和这个“函数”通过函数指针绑定在一起了。

我们需要把目光从__spi_sync(运行时)移回到spi_register_controller(初始化时)。

1. 核心机制:kthread_init_work

在 Linux 内核源码drivers/spi/spi.c中,当一个 SPI 控制器(Master/Controller)被注册时,会执行初始化队列的逻辑。

请看源码中的这一关键段落(通常在spi_controller_initialize_queue函数中):

/* drivers/spi/spi.c */staticintspi_controller_initialize_queue(structspi_controller*ctlr){/* ... *//* 1. 初始化内核工作线程 (Worker) */kthread_init_worker(&ctlr->kworker);/* 2. 创建并启动线程 */ctlr->kworker_task=kthread_run(kthread_worker_fn,&ctlr->kworker,"%s",dev_name(&ctlr->dev));/* * 3. 【真相在这里】绑定任务与函数! * 这行代码的意思是: * 初始化 ctlr->pump_messages 这个任务结构体, * 并指定:将来谁运行这个任务,谁就去执行 __spi_pump_messages 函数。 */kthread_init_work(&ctlr->pump_messages,__spi_pump_messages);/* ... */}

2. 运行时流程还原

明白了初始化绑定后,我们再回看运行时的流程,一切就豁然开朗了:

第一步:触发 (In__spi_queued_transfer)

当你调用__spi_sync时,它内部调用了:

/* 把 master->pump_messages 这个"任务单"扔给 kworker */kthread_queue_work(&master->kworker,&master->pump_messages);

这就好比你在餐厅的订单栏上挂了一张具体的**“炒菜单”**(pump_messages),而不是一张白纸。这张单子上写着一行小字:“执行动作:__spi_pump_messages”

第二步:调度 (In Kernel Scheduler)

后台的kworker线程(它平时在死循环里睡觉)被唤醒。它醒来后检查自己的任务列表,发现了这张“炒菜单”。

第三步:执行 (Inkthread_worker_fn)

内核线程的通用执行逻辑大概长这样(简化版):

/* kernel/kthread.c - kthread_worker_fn */intkthread_worker_fn(void*worker_ptr){while(1){/* ... 睡眠等待 ... *//* 醒来,取出任务 */work=list_first_entry(...);/* ... *//* 4. 【执行回调】 * work->func 就是初始化时绑定的 __spi_pump_messages */work->func(work);}}

3. 为什么会出现两次进入__spi_pump_messages

  1. **Caller 线程:
    • ioctl里,你把消息放入队列。
    • 你调用kthread_queue_work,把“炒菜单”挂到了 KWorker 的待办栏上。(此时 KWorker 还在睡觉,或者刚听到闹钟还没起床)。
    • Caller 优化:你自己这会儿也没事干,你想“干脆我自己先炒了吧”。于是你直接调用函数__spi_pump_messages(false)
    • 你成功了,硬件归你了,你开始炒菜(传输数据)。
  2. KWorker 线程
    • 过了几十微秒,它终于穿好衣服起床了(被调度到了 CPU 上)。
    • 它走到待办栏,拿下了那张“炒菜单”(master->pump_messages)。
    • 它根据单子上的指令,执行work->func(),也就是第二次调用__spi_pump_messages(true)
    • 撞车:它一进函数,看到master->cur_msg不为空(你正在炒菜),或者master->busy是真的。
    • 结果:它耸耸肩,把单子扔了(return),回去继续睡觉。

总结

kthread_queue_work之所以会进入__spi_pump_messages,是因为在驱动初始化阶段,使用kthread_init_work将两者死死地绑定在一起了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/20 22:10:41

计算机Java毕设实战-基于springboot的无人机销售系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/19 14:17:32

Java毕设项目推荐-基于 SpringBoot 的社区智慧养老监护管理平台系统设计与实现基于springboot的社区独居老人健康管理系统【附源码+文档,调试定制服务】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/18 18:53:10

Java毕设选题推荐:基于springboot+vue的无人机农田监测巡查系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/2/25 14:52:21

计算机毕业设计springboot房屋租赁管理系统 基于SpringBoot的在线房屋出租与求租撮合平台 SpringBoot+Vue智慧住房租赁综合服务平台

计算机毕业设计springboot房屋租赁管理系统(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 租房市场长期存在信息碎片化、真假难辨、流程繁琐三大痛点:租客东奔西跑看…

作者头像 李华
网站建设 2026/2/19 23:38:06

计算机毕业设计springboot房屋租赁管理系统 基于SpringBoot的在线房源租售一体化运营平台 SpringBoot+Thymeleaf智慧住房租赁合约管理系统

计算机毕业设计springboot房屋租赁管理系统(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 毕业季换房高峰,"找房半小时、看房跑断腿、签合同像考古"的场景…

作者头像 李华
网站建设 2026/2/21 14:29:23

计算机毕业设计springboot房屋租赁系统 基于SpringBoot的在线房屋出租与求租撮合平台 SpringBoot+Vue智慧住房租赁综合服务平台

计算机毕业设计springboot房屋租赁系统(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。租房市场长期存在信息碎片化、真假难辨、流程繁琐三大痛点:租客东奔西跑看房&a…

作者头像 李华