Linux操作系统--内核同步方法

临界区:临界区的代码不能被打断,原子的执行。进入临界区不能发生进程切换,不能发生中断。

造成并发的原因:

1、中断——中断可能随时打断当前正在执行的代码

2、软中断和tasklet——内核可以在任何时刻唤醒软中断,打断正在执行的代码

3、内核抢占——内核中的任务可能被另一个任务抢占

4、睡眠和用户空间的同步——内核代替进程执行,可能会被阻塞,导致进程切换,不同的进程访问共享资源导致竞争

5、对称多处理器——多个处理器可以同时访问一个共享资源,导致竞争

 

哪些资源需要加锁保护:大部分内核数据结构需要加锁,给数据加锁,而不是代码。

死锁的原因:资源的竞争、进程推进顺序的不合理。

死锁产生的必要条件:互斥(一个资源只能被一个线程占用)、请求与保持(一个进程已经占有一种资源还想获取另一种资源)、不可剥夺、循环等待。

 

同步方法:

0、每CPU变量:只有本地CPU可以访问相应的变量,但是访问的时候也需要进行保护,内核抢占可能带来竞争。

1、原子操作

2、自旋锁短时间内轻量级加锁。(多处理器环境的特殊锁)

自旋锁的特点:1、自旋锁保护的临界区不能进入休眠;2、自旋锁保护的临界区能被中断中断;3、自旋锁保护的临界区代码执行时不内核不能被抢占;4、可以在中断上下文中使用(需要禁止本地中断)。【不能因为任何原因让出处理器】

自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作。自旋锁适用于锁使用者保持锁时间比较短的情况下。

 自旋锁三种状态
自旋锁保持期间是抢占失效的(内核不允许被抢占)。
1、单CPU且内核不可抢占:
      自旋锁的所有操作都是空。不会引起死锁,内核进程间不存在并发操作进程,进程与中断仍然可能共享数据,存在并发操作,此时内核自旋锁已经失去效果。
 2 、单CPU且内核可抢占:
      当获得自旋锁的时候,禁止内核抢占直到释放锁为止。此时可能存在死锁的情况是参考自旋锁可能死锁的一般情况。
      禁止内核抢占并不代表不会进行内核调度,如果在获得自旋锁后阻塞或者主动调度,内核会调度其他进程运行,被调度的内核进程返回用户空间时,会进行用户抢占,此时调用的进程再次申请上次未释放的自旋锁时,会一直自旋。但是内核被禁止抢占,从而造成死锁。
      内核被禁止抢占,但此时
中断并没被禁止,内核进程可能因为中断申请自旋锁而死锁。
3 、多CPU且内核可抢占:
      这才是是真正的SMP的情况。当获得自旋锁的时候,禁止内核抢占直到释放锁为止

3、互斥锁:一个比信号量更加简单方便的睡眠锁

特点:必须在同一个上下文中上锁和解锁,不能在一个上下文中上锁,另一个上下文中解锁;不能递归的上锁和解锁;不能在中断或者下半部使用;不能在中断上下文使用。原子性:互斥锁的操作是原子操作;唯一性:只有一个线程持有锁;非繁忙等待。

对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。

4、信号量:一种通用复杂的睡眠锁

只能在进程上下文获取信号量锁,不能在中断上下文获取信号量锁,因为可能导致睡眠。可以在持有信号量的时候睡眠,因为其他信号量可以睡眠等待。

二值信号量 / 互斥信号量:任意时刻只允许有一个持有者

计数信号量:任意时刻可以有多个持有者。

关于选择:

除非mutex的某个约束导致不能使用互斥锁,才选择信号量,否则一般情况下选择互斥锁。中断上下文只能使用自旋锁。

死锁:

在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁,调用有些其他函数也可能造成死锁,如 copy_to_user()、copy_from_user()、kmalloc()等。 

因此我们要慎重使用自旋锁,自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作。自旋锁适用于锁使用者保持锁时间比较短的情况下。

1、试图递归地获得自旋锁必然会引起死锁:递归程序的持有实例在第二个实例循环,以试图获得相同自旋锁时,不会释放此自旋锁。
2、进程得到自旋锁后阻塞,睡眠:
     在获得自旋锁之后调用copy_from_user()、copy_to_ser()、和kmalloc()等有可能引起阻塞的函数。
3、中断中没有关中断,或着因为申请未释放的自旋锁
     在中断中使用自旋锁是可以的,应该在进入中断的时候关闭中断,不然中断再次进入的时候,中断处理函数会自旋等待自旋锁可以再次使用。或者在进程中申请了自旋锁,释放前进入中断处理函数,中断处理函数又申请同样的自旋锁,这将导致死锁。

5、读写自旋锁 和 读写信号量

6、completion变量

7、大内核锁  (已经不使用)

8、顺序锁即seq锁

9、优化屏障和内存屏障:事实上,所有的同步原语都起到了优化和内存屏障的作用。

优化屏障:保证编译程序不会混淆放在原语操作之前的程序和原语之后的程序,避免指令重新排序。

内存屏障:确保原语之前的操作都已经完成。

10、禁止内核抢占:一般对每CPU变量访问需要关闭内核抢占。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值