Linux 大内核锁原理
上一篇 / 下一篇 2012-07-11 09:37:39 / 个人分类:Linux
*s]m3_;J0 大内核锁(BKL)的设计是在kernel hacker们对多处理器的同步还没有十足把握时,引入的大粒度锁。他的设计思想是,一旦某个内核路径获取了这把锁,那么其他所有的内核路径都不能再获取到这把锁。
`VR Pb`(K#Gl*LJ0h)D_EdJ;~0 自旋锁加锁的对象一般是一个全局变量,大内核锁加锁的对象是一段代码,里面可能包含多个全局变量。那么他带来的问题是,虽然A只需要互斥访问全局变量a,但附带锁了全局变量b,从而导致B不能访问b了。51Testing软件测试网za3BCB%l
51Testing软件测试网 |L%t!Fn\kYT8x大内核锁最先的实现靠一个全局自旋锁,但大家觉得这个锁的开销太大了,影响了实时性,因此后来将自旋锁改成了mutex,但阻塞时间一般不是很长,所以加锁失败的挂起和唤醒也是非常costly 所以后来又改成了自旋锁实现。51Testing软件测试网;fE+I'Eb
+AQ [K8K*C^n/bH~0 大内核锁一般是在文件系统,驱动等中用的比较多。目前kernel hacker们仍然在努力将大内核锁从linux里铲除。
f7{%}Pq[%a0 51Testing软件测试网-LRNT$S ~2BI6vr下面来分析大内核锁的实现。51Testing软件测试网W J e8Gs? u` Mz7q
51Testing软件测试网IJ3xdHF我们之前说了大内核锁有两种实现,分别是自旋锁和mutex锁。51Testing软件测试网;P6W)]?7y Ok&M#b0cN
51Testing软件测试网 a5UNt q如果是mutex锁实现,自然不能在中断环境下使用大内核锁,因为中断下禁止调度是金科玉律。51Testing软件测试网t iXjGj8cn7k;S!_1a
%B%n+EBvw P-v1h0 那么在大内核锁内调度是否可以?我们知道,如果一个内核流程获取到资源后就应该尽快完成操作释放资源,以便下一个竞争者获取到资源。所以资源持 有者不得睡眠是一个普遍共识。可是大内核锁不这么认为,持有大内核锁的用户是允许睡眠的-虽然我们并不鼓励这样,但是内核的大内核锁的设计方案里,会在进 程切换时,检查当前进程是否持有大内核锁并释放,当重新获取到cpu后,再尝试抓这把大内核锁。也就是说,进程在持有大内核锁时是可以睡眠的,这就带来资 源starvation51Testing软件测试网b5p1M4{!M2NH6sH
51Testing软件测试网XQc tW0AH;W?b来看基于自旋锁的大内核锁实现
-?Z[&Gr0o%ML9K9LS0 51Testing软件测试网&~3}%Yn;?Y
51Testing软件测试网F*e1T Mt.GbWK,ik-Z static inline void __lock_kernel(void)51Testing软件测试网!VOiTR cI8} c7q 51Testing软件测试网.Ag"s'_qq8uLc;}| 6]~vMP5`lB051Testing软件测试网8g/b(J0^8z`/g |
这段代码的意思是:
Ino C1C0 51Testing软件测试网B ^$y5GA1)如果当前进程如果不是重复加锁的话,就尝试去抓这把锁,并把锁深度加1。这么做的目的是避免锁重入。
*U+?Hh$U}+yJ5P0d Vy0 51Testing软件测试网$TV$d C.pRT/j2)实际加锁的时候,先关抢占,如果尝试加锁失败,则会根据调用lock_kernel之前关抢占与否,来决定是闷头死转,还是大开门户的轮询。
3{ D,BT.B(u|O$Cvw0vce,q-e0 如果是mutex实现的大内核锁kernel_lock,则第2步直接mutex_lock--要么成功要么阻塞。
.QUs8C'yy\$f0 51Testing软件测试网J2c%c#VWaw3BT%Z之前我们提到,在进程发生切换时,会检查当前进程是否持有大内核锁,这是在schedule里做的。51Testing软件测试网X$i+Ri }
pS#ajb S h%l0 51Testing软件测试网6O5hY)LS"PD*Mr
asmlinkage void __sched schedule(void) 8H@$_8IF-m0{ {(H5y%j?0 release_kernel_lock(prev);51Testing软件测试网F&K+O R4a,w b3J context_switch(); |