Linux 版 (精华区)
发信人: tcpip (偶的昵称改了), 信区: Linux
标 题: 内核空间SMP编程
发信站: 紫 丁 香 (Sun Jan 9 22:06:13 2000) WWW-POST
内核空间SMP编程
作者:Dave Jones 编译:杨继张
多处理机系统正在变得越来越普通。尽管大多数用户空间代码仍将完美地运行,
而且
有些情况下不需要增加额外的代码就能利用SMP特性的优势,但是内核空间代码必须
编写成
具备“SMP意识”且是“SMP安全的”。以下几段文字解释如何去做。
问题
当有多个CPU时,同样的代码可能同时在两个或多个CPU上执行。这在如下所示用
于初
始化某个图像设备的例程中可能会出问题。
void init_hardware(void)
{
outb(0x1, hardware_base + 0x30);
outb(0x2, hardware_base + 0x30);
outb(0x3, hardware_base + 0x30);
outb(0x4, hardware_base + 0x30);
}
假设该硬件依赖于寄存器0x30按顺序依次被设为0、1、2、3来初始化,那么要是
有另
一个CPU来参乎的话,事情就会搞糟。想象有两个CPU的情形,它们都在执行这个例程
,不
过2号CPU进入得稍慢点:
CPU 1 CPU 2
0x30 = 1
0x30 = 2 0x30 = 1
0x30 = 3 0x30 = 2
0x30 = 4 0x30 = 3
0x30 = 4
这会发生什么情况呢?从我们设想的硬件设备看来,它在寄存器0x30上收到的字
节按
顺序为:1、2、1、3、2、4、3、4。
啊!原本好好的事第二个CPU一来就搞得一团糟了也。所幸的是,我们有防止这
类事情
发生的办法。
自旋锁小历史
2.0.x版本的Linux内核通过给整个内核引入一个全局变量来防止多于一个CPU会
造成的
问题。这意味着任何时刻只有一个CPU能够执行来自内核空间的代码。这样尽管能工
作,但
是当系统开始以多于2个的CPU出现时,扩展性能就不怎么好。
2.1.x版本的内核系列加入了粒度更细的SMP支持。这意味着不再依赖于以前作为
全局
变量出现的“大锁”,而是每个没有SMP意识的例程现在都需要各自的自旋锁。文件
asm/
spinlock.h中定义了若干类型的自旋锁。
有了局部化的自旋锁后,不止一个CPU同时执行内核空间代码就变得可能了。
简单的自旋锁
理解自旋锁的最简单方法是把它作为一个变量看待,该变量把一个例程或者标记
为
“我当前在另一个CPU上运行,请稍等一会”,或者标记为“我当前不在运行”。如
果1号
CPU首先进入该例程,它就获取该自旋锁。当2号CPU试图进入同一个例程时,该自旋
锁告诉
它自己已为1号CPU所持有,需等到1号CPU释放自己后才能进入。
spinlock_t my_spinlock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock (&my_spinlock);
...
critical section
...
spin_unlock (&my_spinlock);
中断
设想我们的硬件的驱动程序还有一个中断处理程序。该处理程序需要修改某些由
我们
的驱动程序定义的全局变量。这会造成混乱。我们如何解决呢?
保护某个数据结构,使它免遭中断之修改的最初方法是全局地禁止中断。在已知
只有
自己的中断才会修改自己的驱动程序变量时,这么做效率很低。所幸的是,我们现在
有更
好的办法了。我们只是在使用共享变量期间禁止中断,此后重新使能。
实现这种办法的函数有三个:
disable_irq()
enable_irq()
disable_irq_nosync()
这三个函数都取一个中断号作为参数。注意,禁止一个中断的时间太长会导致难
以追
踪程序缺陷,丢失数据,甚至更坏。
disable_irq函数的非同步版本允许所指定的IRQ处理程序继续运行,前提是它已
经在
运行,普通的disable_irq则所指定的IRQ处理程序不在如何CPU上运行。
如果需要在中断处理程序中修改自旋锁,那就不能使用普通的spin_lock()和
spin_unlock(),而应该保存中断状态。这可通过给这两个函数添加_irqsave后缀很
容易地
做到:
spinlock_t my_spinlock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock_irqsave(&my_spinlock, flags);
...
critical section
...
spin_unlock_irqrestore (&my_spinlock, flags);
――Dave Jones,1999年11月30日
--
"这一千多年没写诗了?"
"写了, 不过只写了两句."
"千年得两句, 一定是万古丽句了. 念来听听."
"好吧, 我现丑了" 太白星清了清嗓子, 浑厚的男中音在天庭响起:
大海啊, 都是水;
骏马啊, 四条腿;
※ 来源:·紫 丁 香 bbs.hit.edu.cn·[FROM: tcpip.hit.edu.c]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.850毫秒