同步:识别出异常处理、中断处理、可延迟函数、内核线程中的临界区,采用适当的保护措施,以确保在任意时刻只有一个内核控制路径处于临界区。
如果是但CPU系统,可以采取访问共享数据结构时关闭中断的方式实现临界区,因为只有在开中断的情况下,才能发生内核控制路径的嵌套。
但是在多处理器系统中,许多CPU可能同时执行内核路径,不能假设只要禁止内核抢占功能,而且中断、异常和软中断处理程序都没有访问过该数据结构,就能保证这个数据结构能够安全地访问。
一、内核抢占
内核抢占:如果进程执行内核函数时(内核态运行),允许发生内核切换。
使用内核抢占的目的:减少用户态进程的分派延迟(dispatch latency),即从进程变为可执行状态到它实际开始运行之间的时间间隔。
二、同步原语
Linux内核有多种内核同步技术:每CPU变量(Per-CPU),原子操作、内存屏障、自旋锁、信号量、顺序锁、本地中断禁止、本地软中断(可延迟函数)禁止、读-拷贝-更新(RCU)
1)Per-CPU(每CPU)变量
总的原则:内核控制路径应该在禁用抢占的情况下访问Per-CPU变量。
2)原子操作
“读 - 修改 - 写”类型:若干汇编语言指令都是这种类型,访问存储器单元两次,第一次读原值,第二次写新值。
存储器仲裁器:对访问RAM芯片的操作进行串行化的硬件电路。
避免由于“读 - 修改 - 写”类型引起竞争的方法:确保这样的操作在芯片级是原子的。避免其他CPU访问同一存储单元。
3)优化和内存屏障
(1)编译器优化,用barrier()优化屏障 防止
(2)CPU取指优化,用 wmb/rmb等防止
优化屏障(optimization barrier):barrier()宏, 原语保证编译程序不会混淆 原语之前 的汇编语言指令 和 原语之后 的汇编语言指令。
内存屏障(memory barrier):保证原语之后 的操作 一定要在 原语之前的操作已经完成后 才执行。Pentium4引入lfence、sfence、mfence等汇编指令,有效的实现 读内存屏障、写内存屏障 和读-写内存屏障。
asm volatile(“lfence”) 等同于
asm volatile("lock; addl $0, 0(%%esp)”::”memory”)
lock使得这条指令成为CPU的一个内存屏障。
4)自旋锁
自旋锁:如果内核控制路径发现锁由运行在另一个CPU的内核控制路径”锁着“,就在当前CPU”旋转“,反复执行一条紧凑的循环指令,直到锁被释放。
一般来说:自旋锁所保护的每个临界区都是禁止内核抢占的。但是分为:具有内核抢占的spin_lock宏;非抢占式内核中的spin_lock宏。
spin_unlock宏: movb $1,slp->slock
5)读/写自旋锁
读/写自旋锁:允许多个内核控制路径 同时 读 同一个数据结构;如果一个内核控制路径想对这个结构进行写操作,那么它必须首先获得 读/写锁的 写锁,写锁 独占访问这个资源。
6)顺序锁(seqlock)
顺序锁(seqlock):读者正在读的时候也允许写者继续运行,读者需要反复多次(读之前一次 读完之后一次 读取一个标志位,每个读者都必须在读数据前后两次读顺序计数器[seqlock_t中sequence字段],写者通过write_seqlock(){是sequence加1}和write_sequnlock()获取和释放锁)相同的数据直到它获得有效的副本。类似 读/写自旋锁, 为 写者 赋予了较高的优先级。
7)RCU(读-拷贝-更新)
RCU(读-拷贝-更新):保护被多个CPU 读 的数据结构而设计的同步技术。写者更新数据结构时,它间接引用指针并生成整个数据结构的副本;写者修改这个副本;一旦修改完,写者改变指向数据结构的指针(需要使用内存屏障 来保证,只有数据结构被修改后,已更新的指针对其他CPU才是可见的。其中内存屏障一种方法:自旋锁和RCU结合 禁止写者的并发执行),写者必须在读者执行完rcu_read_unlock()之后,才可以释放旧副本。
a)RCU只保护被动态分配并通过指针引用的数据结构;b)在被RCU保护的临界区中,任何内核控制路径都不能睡眠。
静止状态(quiescent state),CPU经历以下一种状态即为静止状态:
a)CPU执行进程切换
b)CPU开始在用户态执行
c)CPU执行空循环
写者调用call_rcu()释放旧副本.当所有CPU都通过quiescent state之后,call_rcu()接受rcu_head描述符的地址和将要调用的回调函数的地址作为参数。回调函数执行,写者释放数据结构的旧副本。
内核没经过一个时钟滴答,就周期性检查本地CPU是否进经过了一个quiescent state。
8)信号量
9)读/写信号量
10)补充原语
11)禁止本地中断
12)禁止和激活可延迟函数
三、避免竞争条件
1)引用计数器
2)大内核锁
每个进程描述符都含有lock_depth字段,允许同一个进程几次获取大内核锁。
分享到:
相关推荐
深入理解Linux内核-内存篇,阅读笔记
这只是该图书的一部分,其余请参看后缀中的数字,总共7部分(如深入理解Linux内核-第3版-中文版.part01.rar)。解压时,只要将7部分压缩文件放在同一个目录下,任意选一部分右键-》解压到“深入理解Linux内核-第3版-...
深入理3.10 P101, 第三段 勘误: 第三段和第一段重复, 而且还漏掉了很多东西, 原书第三段翻译如下: 处于TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE 状态的进程被分成很多类, 每一类代表一...解Linux内核正版书籍所有勘误
深入理解Linux内核-第3版-中文版,高清版 由于太大,分卷压缩后上传!请下载全部6个压缩包.
深入理解linux内核,中文第三版,第5章,内合同步
深入理解Linux内核 + Linux内核设计与实现,绝对完整,我最近也在学,建议先学Linux内核设计与实现,对Linux内核有一个大体的认识,在看深入理解Linux内核,要舍得花时间。
深入理解LINUX内核,简要笔记,欢迎下载哦。
深入理解linux内核 第三版 中文版 前十章 pdf
《深入理解linux内核中文第三版》,高清晰扫描,真正中文第三版,对Linux 2.6内核进行了详细而细致的讲解。由于之前的压缩包分卷太多,现提供每一章的单独下载文件。100%高清晰第三版!
深入理解linux内核,中文第三版,第7章,进程调度
深入理解linux内核,中文第三版,第6章,定时测量
深入理解linux内核,中文第三版,第8章,内存管理
深入理解linux内核,中文第三版,第三章,进程
深入理解linux内核,中文第三版,第一章,绪论
深入理解linux内核,中文第三版,第二章,内存寻址
致读者:深入理解LINUX内核第三版pdf版本扫描出来的,内容比较大,所以必须分章节才能上传。我上传比你下载要更长时间,请大家谅解和支持,但是本文可以确保是第三版内容,希望大家下载后好好学习,我家里有2个版本...
深入理解linux内核,中文第三版,第4章,终端和异常
深入理解linux内核第三版中文版,详细讲解linux内部运作机制,学习linux的经典教材。 目录: 前言 第一章绪论 第二章内存寻址 第三章进程 第四章中断和异常 第五章内核同步 第六章定时测量 第七章进程调度 第八章...
深入理解linux内核(第三版中文).pdf