http://blog.csdn.net/wzhCAlex/article/details/52549383
5.1 内核同步与死锁问题
并发:两个进程可以真正的在临界区中同时执行。
原因:
(1)中断
(2)软中断和tasklet
(3)内核抢占
(4)睡眠及与用户空间的同步
(5)对称多处理
数据加锁:
(1)如果有其他执行线程可以访问这些数据;
(2)如果任何其他什么东西都能看见它;
(3)几乎访问所有的内核全局变量和共享数据都需要某种形式的同步方
法。
死锁产生原因:
(1)使用不可剥夺设备;
(2)进程在已经占有一个设备的基础上又提出新的设备,而该新设备又
被其他进程占有了,导致进程运行暂停;
(3)进程之间连环等待资源,如A等B,B等C,C等A。
避免死锁的方法:
(1)按顺序加锁,如果有两个或多个锁曾在同一时间里被请求,那么以
后其他函数请求它们时也必须按照前次加锁的顺序加锁。
(2)防止发生饥饿,也就是代码要保证能结束。
(3)不要重复请求同一个锁。
(4)所以进程在开始运行前,申请需要占用的全部设备,防止中途因申
请不到而暂停。
(5)在进程申请不到继续运行锁需要的设备时,必须释放已经占用的资
源。
5.2 解决并发同步的方法
1.原子操作
内核提供两组原子操作接口:一个针对整数,一个针对位进行操作。
2.自旋锁
自旋锁的作用是在短期内进行轻量级加锁,持有自旋锁的事件最好小于
两次上下文切换的耗时,且加锁时间不长,,代码不会睡眠。
3.自旋锁与下半部的问题
由于下半部(或中断)可以抢占进程上下文中的代码,所以当下半部(或
中断)和进程上下文共享数据时,必须对进程上下文中的共享数据进行
保护,需要加锁的同时还要禁止下半部(或中断)的执行。
4.信号量
信号量适用于锁被长时间持有的情况,持有信号量的代码可以被抢占,
也可以在持有信号量时去睡眠,但是当占用信号量时不能同时占有自旋
锁,因为在等待信号量时可能会睡眠,而在持有自旋锁时是不允许睡眠
的。
5.互斥体
互斥体是更简单的睡眠锁,只适用于:
(1)任何时候只有一个任务可以持有mutex;
(2)给mutex上锁者必须负责给其解锁,也就是不能在一个上下文中锁
定一个mutex,而在另一个上下文中给它解锁。
(3)当持有mutex时,进程不可以退出;
(4)mutex不能在中断或者下半部中使用。
信号量与互斥体比较:
(2)除非mutex的某个约束妨碍你使用,否则相比信号量要优先使用mutex。
(2)当写新代码时,只有碰到特殊场合(一般是很底层的代码)才会需
要使用信号量。
自旋锁和互斥体比较:
(1)在中断上下文只能使用自旋锁
(2)在任务睡眠时只有使用互斥体
(3)长期加锁,优先使用互斥体
(4)短期加锁,优先使用自旋锁
6.完成量
如果在内核中一个任务需要发出信号通知另一个任务发生了某个特定事
件,利用完成量是使两任务得以同步的简单方法。
7.禁止抢占
内核抢占代码使用自旋锁作为非抢占区域的标记,如果一个自旋锁被
持有,内核便不能进行抢占。