十一月 | ||||||
---|---|---|---|---|---|---|
日 | 一 | 二 | 三 | 四 | 五 | 六 |
27 | 28 | 29 | 30 | 31 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
代码之美 - 081008
《Linux内核驱动模型:协作的好处》这章篇幅不大,可读得费劲。
上来就有两句话没看懂:在2.4版本的内核中,每一个设备的物理部分都由一段总线特定的代码来控制。总线代码负责各种不同类型的任务,而每一种具体总线的代码之间则没有交互。
后一句的原文是:This bus code was responsible for a wide range of different tasks, and each individual bus code had no interaction with any other bus code.
这里,总线特定代码(bus-specific code)是什么意思?
然后,Greg Kroah-Hartman提出两个问题,1是在解决电源管理问题时,内核需要知道不同设备的连接关系;2是不论哪一台USB打印机先启动,两台打印机的名字永不变。
其他系统的一般解决方法,1是内核中放一个处理设备名的小数据库,2是通过文件系统中可以直接访问设备的devfs类型来导出设备的所有信息。
对Linux来说,内核里放数据库是不能接受的,同时,Linux的devfs文件系统实现中“存在一些众所周知的且难以消除的竞争条件,导致几乎所有的Linux发布的版本中都不能依赖它。”这句话怎么理解?
再然后,作者用一个“简单”的例子展现了,展现了什么呢,我觉得是展现了C语言的复杂用法。如作者所说:是的,非常强大,只要你清楚地知道你正在做什么。
不信就看看这个宏吧:
-
#define container_of(ptr, type, member) ({ \
-
const typeof( ((type *)0) ->member ) * _mptr = (ptr); \
-
(type *)( (char *)_mptr - offsetof(type, member) );})
作者通过介绍Linux内核中解决前面提到的两个问题所需的数据结构和支持函数的演变,来说明协作给Linux带来的好处,还好文末有个总结,否则我又要忘了他要说什么。
Non-Preemptive Kernel
非抢占(Non-Preemptive)内核中如果任务不主动放弃,就不会被其他的高优先极任务抢掉对于CPU的控制。一个ISR可以使一个更高优先级的任务进入等待运行状态,但ISR总是返回被中断的任务。如图:
①低优先级任务(LPT)执行;
②低优先级任务被中断;
③执行中断服务例程,使高优先级任务(HPT)就绪;
④中断服务例程返回到被中断的低优先级任务;
⑤低优先级任务继续执行;
⑥低优先级任务放弃CPU;
⑦高优先级任务运行。
这个比较简单,而非抢占内核的其他优点也都好理解。可书上有这么一句话:非抢占内核的一个优点是中断等待时间通常比较低。什么是中断等待时间?
往后翻10页,书上又写:中断等待时间=中断被禁止的最长时间量+在ISR中开始执行第一个指令的时间。
这个式子我看了大约五分钟。又翻回前面那句话反复默念。然后我决定认为自己理解了。一个任务在执行,收到一个中断,而这时中断有可能是被禁止的,一直到中断重新被打开,CPU保存现场环境到堆栈,跳转到ISR。所谓“中断被禁止的最长时间”的意思是从收到中断到开中断这一段时间。而保存CPU现场后才开始执行ISR,那么保存现场的这个时间是不是包含在中断等待时间内?从上面的式子看是的。
但是又来个式子:中断响应时间=中断等待时间+保存CPU状态的时间(非抢占内核)。
糊涂了,什么是“在ISR中开始执行第一个指令的时间”?
问题出在哪?出在ISR。开中断后,ISR即接管,保存现场的动作是ISR做的,中断等待时间就是从收到中断到ISR接管的时间,然后保存现场,然后开始执行用户代码,到这时是中断响应时间。对于抢占内核,保存完现场后要调用一个内核函数,通知内核一个ISR在处理并允许内核记录中断嵌套的情况,所以前面说,非抢占内核的一个优点是中断等待时间通常比较低。
非抢占内核最大的问题是响应时间。一个就绪的高优先级任务可能要等待不可预期的一段时间才能运行,所以实时内核多是抢占内核。如图是抢占内核的情况:
①低优先级任务执行;
②异步事件使任务中断;
③响应异步事件,运行中断服务例程,使高优先级任务就绪;
④中断服务例程返回到高优先级任务;
⑤高优先级任务执行,直到它被中断转向执行优先级更高的任务;
⑥高优先级任务结束,内核切换到低优先级任务;
⑦低优先级任务继续执行。