Linux内核锁机制

1400阅读 0评论2020-09-14 stolennnxb
分类:LINUX

现在,内核使用了由锁组成的细粒度网络,来明确保护各个数据结构。
内核为此提供了各种锁选项,分别优化不同的内核数据使用模式:

1. 原子操作:它们保证简单的操作,诸如计数器+1之类,可以不中断的原子执行。

2. 自旋锁:最常用的锁选项。它们用于短期保护某段代码,以防止其他处理器的访问。在内核等待自旋锁释放时,会重复检查能否获得锁,而不会进入睡眠状态

3. 信号量:在等待信号量时,内核进入睡眠状态,直至被唤醒。唤醒后,内核才重新尝试获取信号量。互斥量是信号量的特例,互斥量保护的临界区,每次只能有一个用户进入。它本身会记录可以同时处于信号量保护的临界区的进程的数目和在该信号量上睡眠的进程task_struct(链表)。等待进入临界区的时候,进程的状态会置为TASK_UNINTERRUPTIBLE状态,在这个过程中也是无法接收信号的。推出临界区的时候,会执行up操作,这个操作会将链表中的进程唤醒。


4. 读写锁:这些锁会区分对数据结构的两种不同类型的访问。任意数目的处理器都可以对数据结构来进行并发读访问,但是只有一个处理器能够进行写访问。


5. RCU机制:全称read-copy-update,性能很好,会有一定的内存开销,但大多数情况可以忽略,对使用者也提出了一些约束:a). 对共享资源的访问在大部分时间是读取,写入应该相对较少;b). 在RCU保护的代码范围内,内核不能进入睡眠;c). 受保护资源必须通过指针访问。


RCU的原理很简单(很像网络上流行的“一看就会,一用就废”),该机制记录了指向共享数据结构的指针的所有使用者。在该结构将要改变时,首先创建一个副本,在副本中修改。在所有进行读访问的使用者结束对旧副本的读取之后,指针可以替换为指向新的、修改后副本的指针。被反引用(*ptr)的指针不能在rcu_read_lock()和rcu_read_unlock()保护的代码范围之外使用,也不能用于写访问。如果必须修改ptr指向的对象,则需要使用rcu_assign_pointer,后续的读操作将会看到新结构。另外,RCU能够能保护读访问不受写访问的干扰,但它不会对写访问之间的干扰提供防护。如果更新来自内核中的多个地方,这就必须要使用同步元语防止并发的写操作。


实时互斥量以及优先级反转:
当系统上有两个正在运行的进程,A优先级高,C优先级底。假定C已经获取了一个互斥量,若在此时A也向获取该互斥量,则A必须等待。如果此时有一个进程B,优先级位于A和C之间,假设它不需要锁,所以它就可以抢占C,此时A也在等待,外界开到的现象就是:明明B的优先级没有A的高,但是看起来它更高。解决这种现象的方案就是通过优先级继承来解决——如果高优先级进程阻塞在互斥量上,则当前获取到互斥量的进程的优先级暂时被调成高优先级,直至其运行完成。完成这一工作的就是实时互斥量了。

上一篇:linux当中用户空间虚拟内存管理
下一篇:Linux当中的文件映射