全文预备教程
【知乎专栏】Linux Kernel中断漫谈(上)https://zhuanlan.zhihu.com/p/26568566
【知乎专栏】Linux Kernel中断漫谈(下)https://zhuanlan.zhihu.com/p/26612985
Interrupt Descriptor Table
我们以 先来看一下Linux的中断系统。
IRQ触发调试
这个真做不了,每个cpu的vector table和Interrupt description table不知道怎么对应。尝试了看各种头文件依然无果。
网上看到一个实验思路,但是我这里并不可行,求大牛解释一下:
// 改/arch/x86/kernel/irq.c
unsigned int do_IRQ(...) ->加参数把vector_irq打出来
// 然后内联汇编
asm("int $0x51");
Tasklet
我们使用tasklet,来做驱动程序的下半场。
tasklet简单来说就是一个要执行的待办事项。kernel给了添加待办、删除待办、临时disable/enable该项目等等。每条待办事项存了callback function和传参。
系统规定了每条待办事项有状态:
- TASKLET_STATE_SCHED 准备做还没做
- TASKLET_STATE_RUN 该条项目正在运行中啊!
为保证服务质量,tasklet可以做到:
- 对于每条待办事项,只会执行一次。(即使有好多cpu也不担心冲突)
- 可以允许同时出现“SCHD状态”和“RUN状态”的两条内容一样的待办事项。
- 任何时候,对于内容一样的待办事项,多次调用tasklet_schedule(),“处于SCHD状态的相同条目”只能重复出现一次。
教程顺序:
https://www.ibm.com/developerworks/cn/linux/l-tasklets/
http://www.wowotech.net/irq_subsystem/tasklet.html
注意 不要多次调tasklet_enable(),kernel会挂。。
(CMWQ) Concurrency Managed Workqueue
Pay Attention Please 请不要过分关注旧版的workqueue,那个简直就是naked module on cpu。
我们先提前知道,靠CMWQ跑的程序,里面可以有sleep,可以有lock,可以运行很久,就是个正常的process。
这个很有趣,想象我们要去银行搞事情,但是这家银行很有趣,队伍是从银行大门外开始排的。某天上午,门口排了了若干列队伍,等着银行门卫安排这些人们进去办业务,这就是workqueue模型。
- 银行里面是Kernel Core Zone(改动不得),银行外面是Coding Space(就是我们写的代码)。
- 每个排队的人都是work
- 每列在门外的队伍都是一个workqueue (记住缩写wq)
- 银行的柜员是worker,躲在银行窗口后面。他们的状态:或idle,或running。
- 每个银行的窗口都分别是一个worker-pool,即每个窗口可能会有好多个worker小姐姐同时接单,可以给好几个人同时办业务。
- 谁进银行办业务要听银行门卫(kernel调度)的。
- 一进大厅就是Kernel Core Zone了,我们不需要关心里面是什么样子。可能每个窗口前面会有一些人,可能有一个小队伍,人们或是同时办业务,或是在窗口前面等。
我们以一个来办事的work的角度看:先要在门口找个workqueue排着,等排到了进大厅,听门卫说进去以后怎么走,按照规定路线最终到达银行窗口面前,见到worker小姐姐。
我们可以写程序自己建一个workqueue,建workqueue时可以选如下参数:
- 这个workqueue允许最多同时n个人进去办业务(实际上几个人同时还要听门卫的,莫疑惑假设它是对的)。
- 这个workqueue里面排的都是办事比较多的人(cpu intensive)。
- 这个workqueue里面必须一个一个进,前面那个人出来,后面才能进(相当于最多允许1个人同时办业务)。
- 这个workqueue里面的人,都要找同一个worker柜台姐姐。
- 这个workqueue里面的人,尽量快的往里进,可以找不同的worker小姐姐同时办。
- 等等。。。
我们只完成Coding Space,进了大厅怎么安排就不管了。我们只提需求,剩下的交给门卫解决。
刚才说完银行门口的workqueue,现在来看看我们自己“排队的人(work)”:
一个正常的work用work_struct定义。可是呢有的人就想等上几分钟,再去找个门口的队伍开始排,这是就要用delayed_work_struct定义。当然,正常work和delayed_work可以排在一个队伍里排着。
我们是上帝,我们新建work,我们新建workqueue,他们都出生并生活在Coding Space。
Coding Space是我自己造的词,就为方便区分。刚开始看时我看worker和work两个词都会混,本来想把work换成task或者item,但是各种英文文章里面都用work。有句话怎讲,如无需要,勿增实体。
看到了这里,对结构以及名字有所了解,那么可以接触真正的入门教程了:https://www.kernel.org/doc/html/v4.15/core-api/workqueue.html
此篇阅读起来很快,需要提前在网上搜一下NUMA。
题外话,workqueue还提供一组函数xxx_pending()/flush(),他们有的能看状态,有的可以等待一个work完成,也可以等待一组workqueue完成,通常在退出时候会调用一下吧。正如文档里面所说,使用flush要三思。