《TCP/IP详解 卷2:实现》 —1.12 中断级别与并发
1.12 中断级别与并发
我们在1.10节看到联网代码处理输入分组用的是异步和中断驱动的方式。首先,一个设备中断引发接口层代码执行,然后它产生一个软中断引发协议层代码执行。当内核完成这些级别的中断后,执行插口代码。
在这里给每个硬件和软件中断分配一个优先级。图1-13所示的是8个优先级别的顺序,从最低级别(不阻塞中断)到最高级别(阻塞所有中断)。
图1-13 阻塞所选中断的内核函数
[Leffler et al. 1989]的表4-5显示了用于VAX实现的优先级别。386的Net/3的实现使用图1-13所示的8个函数,但splsoftclock与splnet在同一级别,splclock与splhigh也在同一级别。
用于网络接口级别的名称imp来自缩写IMP(接口报文处理器),它是在ARPANET中使用的路由器的最初类型。
不同优先级的顺序意味着高优先级中断可以抢占低优先级中断。看图1-14所示的事件顺序。
1) 当插口层以级别spl0执行时,一个以太网设备驱动程序中断发生,使接口层以级别splimp执行。这个中断抢占了插口层代码的执行。这就是异步执行接口输入例程。
2) 当以太网设备驱动程序在运行时,它把一个接收的分组放置到IP输出队列中并调度一个splnet级别的软中断。软中断不会立即有效,因为内核正在一个更高的优先级(splimp)上运行。
3) 当以太网设备驱动程序完成后,协议层以级别splnet执行。这就是异步执行IP输入例程。
4) 一个终端设备中断发生(完成一个SLIP分组)时,它立即被处理,抢占协议层,因为终端输入/输出(spltty)优先级比图1-13中的协议层(splnet)更高。
5) SLIP驱动程序把接收的分组放到IP输入队列中并为协议层调度另一个软中断。
6) 当SLIP驱动程序结束时,被抢占的协议层继续以级别splnet执行,处理完从以太网设备驱动程序收到的分组后,处理从SLIP驱动程序接收的分组。仅当没有其他输入分组要处理时,它才会把控制权交还给被它抢占的进程(在本例中是插口层)。
7) 插口层从它被中断的地方继续执行。
对于这些不同优先级,一个要关心的问题就是如何处理那些在不同级别的进程间共享的数据结构。在图1-12中显示了三种在不同优先级进程间共享的数据结构—插口队列、接口队列和协议队列。例如,当IP输入例程正在从它的输入队列中取出一个收到的分组时,一个设备中断发生,抢占了协议层,并且那个设备驱动程序可能添加另一个分组到IP输入队列。这些共享的数据结构(本例中的IP输入队列,它共享于协议层和接口层),如果不加协调地访问它们,可能会破坏数据的完整性。
Net/3的代码经常调用函数splimp和splnet。这两个调用总是与splx成对出现,splx使处理器返回到原来的优先级。例如下面这段代码,被协议层IP输入函数执行,检查是否有其他分组在它的输入队列中等待处理:
struct mbuf *m;
int s;
s = splimp ();
IF_DEQUEUE (&ipintrq, m);
splx(s);
if (m == 0)
return;
调用splimp把CPU的优先级升高到网络设备驱动程序级,防止任何网络设备驱动程序中断发生。原来的优先级作为函数的返回值存储到变量s中。然后执行宏IF_DEQUEUE把IP输入队列(ipintrq)头部的第二个分组删去,并把指向此mbuf链表的指针放到变量m中。最后,通过调用带有参数s(其保存着前面调用splimp的返回值)的splx,CPU的优先级恢复到调用splimp前的级别。
由于在调用splimp和splx之间所有的网络设备驱动程序的中断被禁止,在这两个调用间的代码应尽可能地少。如果中断被禁止的时间过长,其他设备会被忽略,数据会被丢失。因此,对变量m的测试(看是否有其他分组要处理)被放在调用splx之后而不是之前。
当以太网输出例程把一个要输出的分组放到一个接口队列,并测试接口当前是否忙时—若接口不忙则启动接口,需要这些spl调用。
在这个例子中,设备中断被禁止的原因是,防止在协议层正往队列添加分组时设备驱动程序从它的发送队列中取走下一个分组。设备发送队列是一个在协议层和接口层共享的数据结构。
在整个源代码中到处都会看到spl函数。
- 点赞
- 收藏
- 关注作者
评论(0)