linux内核笔记-内核同步
linux内核就相当于不断对请求进行响应的服务器,这些请求可能来自CPU,可能来自发出中断的外部设备。我们将内核看作两种请求的侍者。
(1)老板提出请求,侍者如果空闲,为老板服务。(系统调用或异常)
(2)侍者正在无顾客服务时,老板提出请求,则转去为老板服务。(中断异常嵌套)
(3)侍者正为老板服务时,另一老板提出请求,此时转去为另一个老板服务,回头再给这个老板服务。(中断嵌套)
(4)老板可命令老板停止为当前客户服务,侍者完成老板请求之后,可能为新选中的顾客服务。(内核抢占)
内核抢占特点:一个内核态运行的进程,可以被执行内核函数期间被另一个进程取代。有关内核抢占参照本文:内核抢占
同步概念
临界区是一段代码,进入临界区的内核控制路径必须全部执行这段代码,其他控制路径才能进入临界区。单核cpu可以通过简单的关闭中断、禁止内核抢占来进行保证临界区的互斥访问,多cpu就不行 了。
下列条件不需要同步:
(1)执行中断的内核路径不可能被可延迟或系统调用服务例程内核路径所中断,所以不需要同步;
(2)软中断和tasklet不能再同一个CPU上交替执行,所以仅这两者存在时,不需要同步;
(3)仅被一种tasklet访问的数据结构不需要同步。
同步原语
1.每CPU变量
最重要的同步技术就是把内核变量声明为每CPU变量,每CPU变量主要是数据结构的数组,系统每个CPU对应数组的一个元素。一个CPU不应该访问与其他CPU对应的数组元素。每个CPU可以随意修改自己的元素不用担心出现竞争条件。每CPU变量对来自异步函数(中断和可延迟函数)的访问不提供保护,在这种情况下需要提供另外的同步原语。内核抢占可导致每CPU变量产生竞争条件。
2.原子操作
这样的操作是芯片原子级的,执行这样的指令,中间不能中断,且避免其他的CPU访问同样的内存单元。这种原子操作,通过“锁定”内存总线实现,直到这条指令执行结束为止,其他处理器不能访问该内存单元。原子操作:
atom_read(v),atom_set,atom_add,atom_sub.....
3.优化和内存屏障
当使用编译器的时候,编译器可能重新安排汇编语言指令以使寄存器以最优的方式执行。当处理同步时,必须避免指令重新排序。可通过设置内存屏障,确保原语之后的操作语句执行之前,原语操作之前的语句已经完成,这样保证汇编语句顺序执行。
4.自旋锁
自旋锁是用来多处理环境中的一种特殊锁。如果内核路径发现锁是开着的,则可获取锁进入临界区。相反如果内核路径发现锁由另一个CPU上的控制路径所持有,则在周围“旋转”(其实,占着cpu死等,等到为止)。
自旋锁的循环指令表示“忙等”(这种忙等,是nop操作,经过linux优化了,说是节省能源)。注意,在忙等期间,内核抢占有效,就是等待的进程可能被其他进程替代。一般来说,由自旋锁所保护的每个临界区都是禁止内核抢占的。
spinlock_t含有的两个字段:
slock;自旋锁的状态,1表示未加锁
break_lock:表示有无等待该锁的进程
提供的操作:
spin_lock_init();//初始化一把锁
spin_lock();//循环试图获得自旋锁
spin_unlock();//释放锁
spin_unlock_wait();//等待锁
spin_is_locked();//判断锁释是否被持有
5.读写自旋锁
读写锁是为了增加内核的并发能力。该锁的特点:读者进程可以同时多个进入临界区;写者只能一个进入临界区(有写者的时候,读者无法进入)。读者和写者具有相同的优先权。
读/写自旋锁是一个rwlock_t结构。有read_lock和write_lock。
6.顺序锁
读/写自旋锁中,读者和写者具有相同的优先权。事实上,可以这样,即使读者在读的时候,也可以让写者继续进行,这种策略,写者永远不会等待。但是,读者需要对所读到的东西检查,检查是否有被某个写者修改,一旦发现被修改,要重新读取。
7.读-拷贝-创新(RCU)
写者要写的时候,拷贝一份出来写,然后拷回去。
8.信号量
信号量其实也是为了实现互斥和同步(无外乎就是一种P/V操作封装)。但是,信号量中的进程一旦发现资源不可用时,就将自己挂起进入睡眠状态,这不是一种忙等。
然后,使用该资源的进程使用结束后,唤醒正在等待的进程,ok,同步完毕。
linux提供两种信号量:(1)内核信号量,由内核控制路径控制;(2)System V IPC信号量,用户态进程使用。
9.信号量
跟信号量是一样的,但是允许多个读者同时进入设计的,你懂的。
linux内核笔记-内核同步的更多相关文章
- 趣谈linux操作系统笔记-内核初始化
内核的启动从入口函数 start_kernel() 开始.在 init/main.c 文件中,start_kernel 相当于内核的main 函数.打开这个函数,你会发现,里面是各种各样初始化函数 X ...
- Linux内核笔记--内存管理之用户态进程内存分配
内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...
- 【转载】linux内核笔记之进程地址空间
原文:linux内核笔记之进程地址空间 进程的地址空间由允许进程使用的全部线性地址组成,在32位系统中为0~3GB,每个进程看到的线性地址集合是不同的. 内核通过线性区的资源(数据结构)来表示线性地址 ...
- 【转载】linux内核笔记之高端内存映射
原文:linux内核笔记之高端内存映射 在32位的系统上,内核使用第3GB~第4GB的线性地址空间,共1GB大小.内核将其中的前896MB与物理内存的0~896MB进行直接映射,即线性映射,将剩余的1 ...
- 深入理解Linux内核-内核同步
内核基本的同步机制: 抢占内核的主要特点:一个在内核态运行的进程,可能在执行内核函数期间被另外一个进程取代. 内核抢占:Linux 2.6允许用户在编译内核的时候配置十分启用 进程临界区:每个进程中访 ...
- Linux学习笔记:【004】Linux内核代码风格
Chinese translated version of Documentation/CodingStyle If you have any comment or update to the c ...
- Linux 2.6内核中新的锁机制--RCU
转自:http://www.ibm.com/developerworks/cn/linux/l-rcu/ 一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁 ...
- Linux网络编程&内核学习
c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...
- Linux下编译内核配置选项简介
Code maturity level options代码成熟度选项 Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完 ...
随机推荐
- Android 计时与倒计时
方法一 Timer与TimerTask(Java实现) [java] view plain copy print ? public class timerTask extends Activit ...
- call、apply以及bind
call与apply都可以改变js的this指向,两者最主要的区别就是使用时传参的不同,apply的参数可以以数组的形式传进来,但是call方法的参数必须要一个一个的传进来,就像这样. func.ca ...
- 如何安装(装载)axure组件(部件)
我们在网络上经常可以下载到很多网友精心设计的axure组件,这些组件给我们节省了很多的时间,方便了我们进行原型设计,可是对于很多刚刚接触axure的朋友就遇到了2个问题: 第一:到哪里去下载这些组件 ...
- windows 2003 DNS服务的重建
DNS的重建 网络上转载之文章,据说来自微软官方,留下一份自己用,曾经帮助我解决了DNS方面的困扰,希望能给大家带来帮助 1.打开dns管理器,删除domain.com区域,如果存在_msdcs.do ...
- Linux账号管理(一)
整理自<鸟哥的Linux私房菜>,整理者:华科小涛http://www.cnblogs.com/hust-ghtao/ 管理员的工作中,相当重要的一环就是“管理账号”.因为整个系统都是你在 ...
- C# - 重写虚方法
项目目录: 创建教师类(Teacher),虚方法有Teach(); 创建学生类(Student),重写的方法是Teach(); 教师类: · 加上关键字 Virtual 就是声明可以重写此方法. us ...
- 《转》OpenStack Live Migration
This post is based assumption that KVM as hypervisor, and Openstack is running in Grizzly on top of ...
- Linux通配符摘要
参考<鸟哥linux私房菜> * - 通配符,代表随机字符(0对于许多) ? - 通配符,它代表一个字符 # - 凝视 / - 跳转符号,将特殊字符或通配符还原成一般符号 | - 分隔两个 ...
- Oracle SQL语句执行过程
前言 QQ群讨论的时候有人遇到这样的问题:where子句中无法访问Oracle自定义的字段别名.这篇 博客就是就这一问题做一个探讨,并发散下思维,谈谈SQL语句的执行顺序问题. 问题呈现 直接给出SQ ...
- Ajax - 异步处理(点击变成文本框并修改)
效果: 对应的文档结构: Test.aspx 前台代码: 引入JQuery(jquery-1.8.3.min.js). 引入自己所写的JS代码(UserJS.js). <html xmlns=& ...