Linux内核同步方法

2020-10-27  本文已影响0人  睡不醒的大橘

临界区和竞争条件

  1. 访问和操作共享数据的代码段称为临界区。如果两个执行线程在同一个临界区中同时执行,称为竞争条件。避免并发和防止竞态出现的机制被称为同步

  2. 内核中造成并发的原因包括:

  1. 在编写代码的开始阶段就要设计恰当的锁,要给数据而不是代码加锁。

内核同步方法

自旋锁(spin lock)
  1. 自旋锁最多只能被一个可执行线程持有。如果一个执行线程试图获得一个被争用(已经被持有)的自旋锁,那么该线程就会一直进行忙循环—旋转—等待锁重新可用,要是锁未被争用,请求锁的执行线程便能立刻得到它,继续执行,在任意时间,自旋锁都可以防止多于一个的执行线程同时进入临界区,注意同一个锁可以用在多个位置—例如,对于给定数据的所有访问都可以得到保护和同步。

  2. 自旋锁是不可递归的。

  3. 自旋锁可以使用在中断处理程序中。在中断处理程序中使用自旋锁时,一定要在获取锁之前,首先禁止本地中断,否则中断处理程序会打断正持有锁的内核代码,有可能会试图去争用这个已经被持有的自旋锁。但锁的持有者在中断处理程序执行完毕前不可能运行,导致双重请求死锁。

读写自旋锁
  1. 这种自旋锁为读和写分别提供了不同的锁。一个或多个读任务可以并发地持有读锁;写锁只能被一个写任务持有,而此时不能有并发的读操作。
信号量 (semaphone)
  1. Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行 其它代码。当持有信号量的进程将信号量释放后,处于等待队列中的一个任务将被唤醒,并获得这个信号量。

  2. 由于信号量的睡眠特性,所以:

  1. 信号量根据同一时刻允许持有者的数量分为 互斥信号量二值信号量
互斥体(mutex)
  1. 互斥体行为和使用互斥信号量类似,但接口更简单,实现也更高效。

  2. 使用注意事项:

顺序锁(seq)
  1. 实现这种锁主要依靠一个序列计数器。当有疑义的数据被写入时,会得到一个锁,并且序列值会增加。在读取序列值之前或之后,序列号都被读取。如果读取的序列号值相同,说明在读操作进行的过程中没有被写操作打断过。此外,如果读取的值是偶数,那么就表明写操作没有发生(要明白因为锁的初值是0,所以写锁会使值成为奇数,释放的时候就变成偶数)。

  2. 顺序锁适合以下情况

上一篇 下一篇

猜你喜欢

热点阅读