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内核笔记-内核同步的更多相关文章

  1. 趣谈linux操作系统笔记-内核初始化

    内核的启动从入口函数 start_kernel() 开始.在 init/main.c 文件中,start_kernel 相当于内核的main 函数.打开这个函数,你会发现,里面是各种各样初始化函数 X ...

  2. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  3. 【转载】linux内核笔记之进程地址空间

    原文:linux内核笔记之进程地址空间 进程的地址空间由允许进程使用的全部线性地址组成,在32位系统中为0~3GB,每个进程看到的线性地址集合是不同的. 内核通过线性区的资源(数据结构)来表示线性地址 ...

  4. 【转载】linux内核笔记之高端内存映射

    原文:linux内核笔记之高端内存映射 在32位的系统上,内核使用第3GB~第4GB的线性地址空间,共1GB大小.内核将其中的前896MB与物理内存的0~896MB进行直接映射,即线性映射,将剩余的1 ...

  5. 深入理解Linux内核-内核同步

    内核基本的同步机制: 抢占内核的主要特点:一个在内核态运行的进程,可能在执行内核函数期间被另外一个进程取代. 内核抢占:Linux 2.6允许用户在编译内核的时候配置十分启用 进程临界区:每个进程中访 ...

  6. Linux学习笔记:【004】Linux内核代码风格

    Chinese translated version of Documentation/CodingStyle   If you have any comment or update to the c ...

  7. Linux 2.6内核中新的锁机制--RCU

    转自:http://www.ibm.com/developerworks/cn/linux/l-rcu/ 一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁 ...

  8. Linux网络编程&内核学习

    c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...

  9. Linux下编译内核配置选项简介

    Code maturity level options代码成熟度选项 Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完 ...

随机推荐

  1. HDU 2045 不easy系列之(3)—— LELE的RPG难题

    思路: 1.若前n-1位涂的颜色是符合条件的,则因为首尾不同,再加入一位时,仅仅有1种方法:即s[n] = s[n-1] 2.若前n-1位组成的串不符合,再加入一位后合法.即由于首尾同样而引起的不合法 ...

  2. Eclipse更改默认工作目录的方法

    参考: Eclipse更改默认工作目录的方法:http://blog.163.com/take_make/blog/static/208212210201272611406227/ 用记事本打开&qu ...

  3. 利用VS2005进行dump文件调试(17篇博客)

    前言:利用drwtsn32或NTSD进行程序崩溃处理,都可以生成可用于调试的dmp格式文件.使用VS2005打开生成的DMP文件,能很方便的找出BUG所在位置.本文将讨论以下内容: 1.  程序编译选 ...

  4. Spring3表达式语言(SpEL)学习笔记

    最新地址请访问:http://leeyee.github.io/blog/2011/06/19/spring-expression-language Spring Excpression Langua ...

  5. poj 3778

    这就是个超级水题……!!!!写一写来纪念一下自己的错误…… 如果某个学生的的成绩是其他俩个或三个学生成绩的和则给予奖励 直接暴力,所以一开始直接用数组标记两个人或三个人的和,但是忽略了这种情况 20( ...

  6. Poj 3771 hdu 3405

    poj 3771 http://poj.org/problem?id=3771 wiki Prim http://zh.wikipedia.org/wiki/%E6%99%AE%E6%9E%97%E5 ...

  7. Net Core-Razor

    几行代码解决Razor中的嵌套if语句 MVC开发中,经常会遇到在razor中插入简单的逻辑判断. @if (clientManager.IsAdmin) { if (!Model.Topic.Top ...

  8. hdc和hwnd的区别

    句柄概念在WINDOWS编程中是一个很重要的概念,在许多地方都扮演着重要的角色.但由此而产生的句柄概念也大同小异,比如:<<Microsoft   Windows   3   Develo ...

  9. Spring拦截器中通过request获取到该请求对应Controller中的method对象

    背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...

  10. [置顶] android之Notification版本兼容性问题

    首先先来创建一个notification提示 //概要 String tickerText = context.getResources().getText(R.string.app_name).to ...