Linux内核同步机制

为什么要引入同步机制? 

在操作系统引入了进程概念,进程成为调度实体后,系统就具备了并发执行多个进程的能力,但也导致了系统中各个进程之间的资源竞争和共享。另外,由于中断、异常机制的引入,以及内核态抢占都导致了这些内核执行路径(进程)以交错的方式运行。对于这些交错路径执行的内核路径,如不采取必要的同步措施,将会对一些关键数据结构进行交错访问和修改,从而导致这些数据结构状态的不一致,进而导致系统崩溃。因此,为了确保系统高效稳定有序地运行,linux必须要采用同步机制。
 

各种内核同步机制

 原子操作

  • 用来保证执行过程不被打断,是很多其他同步方法的基石。  Linux操作系统实现了三种原子操作:32位整数原子操作、64位整数原子操作、位原子操作。

 

自旋锁

  • 自旋锁的最初设计目的是在多处理器系统中提供对共享数据的保护。
  •     Linux最常见的锁是自旋锁。自旋锁可以保证被加锁的目标最多只被一个线程持有,等待锁的线程就会进行忙等待,自旋等待锁可以重新启用。
  •     自旋锁会关闭内核抢占,持有自旋锁的进程,不会被其他进程抢占CPU。
     

信号量

  •     Linux的信号量是一种睡眠锁。如果任务想要获取一个不可用的信号量时,信号量会将任务推进一个队列,然后让这个任务睡眠。这时处理器可以去处理其他任务。当该信号量可用后,处于等待队列的任务将被唤醒,并获得该信号量。
  •     信号量的睡眠是可以被打断的,Linux内核同时提供了可以被打断和不允许被打断两种方式。
     

信号量和自旋锁对比

  1. 信号量适用于锁会被长时间持有的情况。如果锁持有时间较短,自旋锁会更合适;
  2. 信号量只能用于进程上下文,而不能用于中断上下文。由于信号量发生争用的时候,没获取到信号量的进程会睡眠,而中断上下文不允许睡眠,所以中断上下文中只能使用自旋锁;
  3. 任务占用自旋锁的时候不允许请求信号量,因为持有自旋锁的时候不允许睡眠,但是等待信号量的时候会睡眠;
  4. 信号量允许多个进程同时持有锁,而自旋锁最多只能有一个任务持锁。
     

互斥体 

  • 原本,互斥体是描述任何可以睡眠的互斥锁,但是在Linux内核3.18版本中,引入了一种新的锁机制:互斥体(mutex)。这种互斥体的行为和计数为1的信号量基本相同,区别在于互斥体的接口操作更简洁、实现更高效、使用限制更强。

 

互斥体、信号量和自旋锁的区别

  • 如果场景支持使用互斥体,则尽量使用互斥体;
  • 互斥体可能导致睡眠,则不支持睡眠的场景,例如中断、软中断等,只能使用自旋锁;
  • 如果任务获取不到互斥体会陷入睡眠,如果持锁任务持锁时间较长,应该使用互斥体,避免自旋锁的忙等待消耗处理器资源;否则应该使用自旋锁,避免线程睡眠和唤醒带来的开销
     

禁止内核抢占

  • 内核是具有抢占性的,内核中运行的任务随时有可能被优先级更高的任务抢占内核资源。有一些数据是不需要加锁但是不允许内核抢占的,例如不允许被并发访问每个处理器私有的资源。这里不需要加锁;但是这些数据不允许并发访问,所以需要通过禁止内核抢占来控制。实际上单核处理器上的自旋锁,就可以用禁止内核抢占来替代。

 全概念

结合代码

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值