2012年(366)
分类: 系统运维
2012-03-13 18:42:21
1.自旋锁:自旋锁最多只能被一个可执行线程持有,如果一个线程试图获得一个已经被占用的自旋锁,那么该线程
就会移植进行忙循环等待锁重新可用(特别浪费处理器时间).所以自旋锁不应该被长期持有。这个也正式自旋锁设计的要点:在短期内进行轻量级枷锁。
2.信号量:信号量是一种睡眠锁,如果有一个任务试图获得一个已经被占用的信号量时,信号量会将其推进一个等待队列,然后让其睡眠,如果是长期状态,可以选择让请求线程睡眠,知道锁重新可以用时再唤醒它。这样就不会太浪费处理器周期。但这样的另外一个缺点是会带来一定的开销,有两次明显的上下文切换,被阻塞的线程要换出和换入,与实现自选锁少数的几行代码相比,上下文切换当然有较多的代码,因此持有自旋锁的时间最好小于完成两次上下文切换的时间,当然我们大多数人都不会无聊的去测量上下文切换的时间,所以我们让持有自选锁的时间尽可能短就可以了。
3.因为自选锁在同一时刻之多被一个执行线程持有,这就为多处理器提供了防止并发方位所需要的保护机制,但在
单处理器上,编译的时候并不乎,它仅仅被当作一个设置内核抢占机制是否被启用的开关,如果禁止内核抢占,那么编译时候自选锁会被
完全的剔除,有的地方会退化成本地中断禁止操作。
4.自选锁不可递归
5.自选锁可以使用在中断处理程序中(此处不能使用信号量,因为它们会导致睡眠),在中断处理程序中使用自选锁时,一定要在获取锁
之前,首先禁止本地中断,否则,中断处理程序就会打断正持有锁的代码,有可能会再次获取这个锁,造成死锁,只需禁止本地中断就可以了。
其实从理论上讲,中断上下文完全可以使能睡眠,这样也不会有什么问题,但这样违背了中断的意义,中断的意义在于有一个
优先级更高,更紧急的事件发生,内核要放弃当前稍低优先级的进程,进行更紧急情况的处理,而这时中断又自己去睡眠很不合情理,
况且在中断上下文中,中断是随机发生挂接在某个进程中的,连当前进程都不知道到底是一个什么进程就随性的加入睡眠,
调度另外一个进程,这显然也不是很合理的。
6.完成量
如果在内核中一个任务需要发出信号通知另一个任务发生了某个特定事件,利用完成量使两个任务同步,一个任务要执行一些工作,
另一个任务就会在完成量上等待,当这个任务完成工作后,会使用完成变量去唤醒等待的任务。和信号量思想是一样的。
7.自旋锁与信号量:
--中断上下文中只能使用自旋锁
--睡眠任务只能使用信号量
8.内核抢占,内核中的进程在任何时刻都可以停下来以便另一个具有更优先权的进程运行,这意味着一个任务预备抢占的任务可能会在同一个临界去内运行,为了避免这个情况发生,内核抢占代码使用自选锁作为非抢占区域的标记,如果一个自选锁被持有,内核便不能进行抢占。
preempt_disable();禁止抢占
preempt_enable();使能抢占
抢占计数存放这被持有锁的数量和preempt_disable调用次数,如果是0,那么内核可以进行抢占,如果为1活更大,那么不能抢占.
参考