转了个圈,又回来了
分类: LINUX
2010-06-03 20:19:10
自旋锁和信号量
看到书上介绍了自旋锁,有一句话:如果没有获得锁,申请该锁的进程会一直自旋直到争取到锁为止。当时就想如果它一直自旋不让出处理器,那拥有该锁的进程又什么会有机会释放该锁呢。这样理解是因为么有搞清楚自旋的具体情况,上面的理解局限在了单处理器上面。
当在SMP,即多处理器的时候,上面的理解正确。但是在单处理器上面,申请锁的进程永远会在第一时间拥有该锁,并且会一直执行到释放该锁为止,除非有中断产生。
在单处理器可抢占式内核里面,自旋锁只是用来禁止内核抢占的。在单处理器的运行环境下,申请一个自旋锁后,首先要做的就是禁止内核抢占,这样就不会切换到别的进程中去,也就不会有别的进程因为申请不到该锁而一直自旋等待。唯一的可能去同时申请一个已经被拥有的自旋锁的是中断处理程序。
所以在内核编程中,自旋锁对共享数据访问的保护就是让对共享数据的访问原子的进行。分为几种情况:
(1) 几个进程会可能会通过系统调用而访问到内核中的同一个数据,这时用spin_lock, spin_unlock这一对函数就可以了,这样就会保证一个进程会原子的完成对共享数据的访问,不用担心别的进程。
(2) 进程上下文和中断上下文对共享数据的互斥访问,这个时候只需要在进程中调用spin_lock_irqsave,spin_unlock_irqrestore就可以,因为进程在获得该锁的时候回禁止本地中断。在中断处理程序中就可以不用采取措施。
(3) 几个不同的中断上下文也要完成对内核共享数据的互斥访问,在中断上下文中调用spin_lock_irqsave,spin_unlock_irqrestore就可以了。
在中断处理程序中是可以使用自旋锁的,但是在中断中使用自旋锁的时候一定要特别注意。但是在中断处理程序中不能使用信号量,因为信号量可能引起阻塞。中断处理程序时不能被阻塞的,因为中断处理程序不依附于任何进程上下文,当它被阻塞,就不能再被调度,这根普通的内核代码不同,普通的内核代码可以被阻塞,因为它是依附于陷入该内核代码空间的进程上下文的。所以在中断处理程序中也不能调用可能会引发阻塞的内核函数。如copy_from_user,copy_to_user等函数。