一:中断屏蔽(不推荐使用)
可以使进程与进程间的并发不在发生
二:自旋锁:1自旋锁,2读写自旋锁,3顺序锁,4rcu
1:自旋锁实际是忙等待,当锁不可用时,cpu一直循环执行,测试并设置锁直到可用而取得锁,在忙等是不可以做任何事,仅仅是等待,所以只有在占用锁的时间极短的情况下使用才合理。
2:自旋锁可能导致系统锁死:原因:1,递归使用一个自旋锁,即如果一个已经拥有该锁的cpu想第二次获得这个自旋锁,cpu将死锁。2:如果进程获得自旋锁之后再阻塞,也有可能导致死锁的发生。如copy_from_user和copy_to_user,kmalloc等函数都有可能引起阻塞,所以在自旋锁占用期间不可调用可能发生阻塞的函数。
三:信号量
3.1当获取不到信号量时,进程不会原地打转,而是处于休眠状态
1:DECLARE_MUTEX(name) 定义一个名为name的信号量并初始化为1
DECLARE_MUTEX_LOCKED(name) 定义一个名为name的信号量并初始化为0,可用于同步
2:获取信号量:
void down(struct semaphore * sem) :会导致休眠,不可用于中断上下文
down_interruptible(struct semaphore * sem ) 因为此函数而进入休眠的进程可以被信号打断
int down_trylock(struct semaphore * sem) 不会休眠,立即返回,如果获得信号量,返回0,否则返回非0
3:释放信号量
void up(struct semaphore * sem)
3.2:完成量用于同步机制
1定义
struct completion my_completion;
2初始化
init_completion(&my_completion)
定义并初始化
DECLARE_COMPLETION( my_completion)
3:等待完成:
void wait_for_completion(struct completion * c)
4唤醒完成
void complete(struct completion * c)
void complete_all(struct completion * c)
3.3:互斥体
struct mutex my_mutex
mutex_init(&my_mutex)
mutex_locked(&mu_mutex)
临界资源
mutex_unlocked(&my_mutex)
四:原子操作:在执行过程中不会被别的代码路径所打断的操作
五:如何选择
1:当所不被获取是,使用信号量的开销是进程上下文的切换时间,自旋锁的时间是等待获取锁时自旋的时间,那个时间段用那个
2:信号量中可以发送阻塞,但自旋锁绝对不可以,因为阻塞意味着要进行进程切换,如果进程被切换出去了,另一个进程企图获取此锁,将引起死锁
3:信号量存在于进程上下文,如果被保护的资源在中断或软中断情况下使用,则只能选择自旋锁,若一定要用信号量,可以使用down_trylock()方式,不能获取立即返回,不会引起阻塞。