[关闭]
@myecho 2019-04-01T15:55:37.000000Z 字数 1777 阅读 797

内核同步工具底层实现

linux内核笔记


同步工具

原子变量/自旋锁的实现
https://www.cnblogs.com/fanzhidongyzby/p/3654855.html
http://blog.chinaunix.net/uid-23046336-id-3262445.html

当然,并不是所有的指令前面都可以加lock前缀的,只有ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG,DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, 和 XCHG指令前面可以加lock指令,实现原子操作。

互斥锁和信号量的实现本质上是相同的
x86: https://www.jianshu.com/p/a7ddb2998b3b
arm架构: https://www.veryarm.com/14767.html

读写锁的实现

futex:
https://blog.csdn.net/jianchaolv/article/details/7544316
借助futex,glic或者pthread库中可以组合futex以及原有的内核的同步工具来一起使用

技术 说明 适用范围
per-CPU变量 在CPU之间复制数据结构 所有CPU
原子操作 对一个指令原子地读写和修改的指令 所有CPU
内存屏障 避免指令重新排序 本地或所有CPU
自旋锁 加锁时忙等 所有CPU
信号量 枷锁时阻塞等待 所有CPU
顺序锁 基于访问计数器的锁 所有CPU
禁止本地中断 禁止单个CPU上的中断处理 本地CPU
禁止本地软中断 禁止单个CPU上的可延迟函数处理 本地CPU
读写拷贝的更新(RCU) 用指针而不是锁来访问共享数据结构 所有CPU

抢占

preempt_enable()/disable()分别会增加和减少抢占计数
抢占分成两种:用户抢占和内核抢占
用户抢占发生在从系统调用返回用户空间和从中断处理程序返回用户空间时
内核抢占(2.6)是说从执行内核代码的时候进行抢占-只要没有持有锁,该内核区域就可以执行抢占

每个进程的thread_info中引入了preempt_count计数器,当有内核同步工具上锁的时候就会进行+1,释放锁的时候减1,当这个数值为0且need_resched标志被设置的时候,就会调用调度程序,内核抢占发生的时机如下

内核抢占与关中断之间的关系

首先要明确的,关中断之后,就没有调度了(没有系统调用 没有中断返回)
https://stackoverflow.com/questions/20769768/why-disabling-interrupts-disables-kernel-preemption-and-how-spin-lock-disables-p

关于中断和抢占之间的关系,在《Linux Kernel Development (Third Edition)》的P127页 中断控制的第二段中,作者提到了这样一句话:

Moreover, disabling interrupts also disbles kernel preemption.

也就是说其实中断和抢占有着比较密切的联系,我并不能完全理解这句话的意义。其中最后 一个词语 kernel preemption 指的是否仅仅是内核抢占还是包括用户抢占不得而知(从字 面上说应该是单独指的内核抢占)。

在 stack overflow 中有很多人提这个问题,各种解释众说纷纭不过有一点可以肯定的是, 中断处理器结束运行之后无论是返回用户空间(用户抢占)还是返回内核空间(内核抢占) 都有可能会发生调度从而出现抢占,这点在前面关于抢占的讨论中有提到过。从这个角度理 解,阻止了中断至少不会出现从中断处理器中返回而导致的抢占。

另外中断处理是在一个特殊的上下文(context)中断上下文中完成的,在这个上下文中中 断处理器无法阻塞也不能睡眠,因为它本身没有一个进程在背后支撑,所以它是不可调度的 。也就是说中断处理器是无法抢占的。但是中断处理器还是有可能被其他的中断处理器中断 的,因为中断可能发生在任何的时候,如果出现了更高优先级的中断,那么很可能当前中断 处理器的处理再次被中断。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注