为了实现对临界资源的有效管理,应用层的程序有原子变量,条件变量,信号量来控制并发,同样的问题也存在与驱动开发中,比如一个驱动同时被多个应用层程序调用,此时驱动中的全局变量会同时属于多个应用层进程的进程空间,这种情况下也要使用一些技术来实现对并发的控制。本文将讨论内核中下述并发控制技术的技术特点和应用场景。

  1. 中断屏蔽

  2. 原子操作

    1. 原子变量操作

    2. 原子位操作

  3. 自旋锁

    1. 传统自旋锁

    2. 读写自旋锁

    3. 顺序锁

    4. RCU

  4. 信号量

    1. 传统信号量

    2. 读写信号量

    3. 完成量

  5. 互斥量

中断屏蔽

顾名思义,就是屏蔽所有的中断。在嵌入式系统,中断屏蔽可以有三级,1. 硬件接口的屏蔽,2. 硬件GIC的屏蔽,3. CPU(内核)的屏蔽。如果在接口处屏蔽了,那么中断来了就丢了,根本找不到。如果在GIC处屏蔽了,那么在屏蔽期间如果来了irq_1,irq_2,irq_3个中断,因为只有一个pending标志位,所以最后irq_3来的时候会将pending置位,之后解除屏蔽了,CPU发现pending有置位,还是会处理,但是1,2就肯定丢了。在ARM处的屏蔽,即内核中的屏蔽,看怎么设置了,如果就是local_irq_disable,那么丢了就是丢了,和在接口处屏蔽一样,如果是local_irq_save就和第二种一样,追到最后一个中断,内核也有相应的机制进行中断计数,知道这期间来了多少个中断,但是实际操作中,大部分情况我们都不会追着执行错过的中断,除非这个中断非常重要。

我们这里讨论的,就是在内核中进行中断屏蔽。由于内核中很多重要的操作都要依赖于中断,所以屏蔽所有的中断是十分危险的,里面执行的代码要尽可能的快,而且,由于内核的进程调度也是由中断驱动的,所以中断屏蔽中不能有可能引发休眠的代码,否则无法被唤醒。注意,中断屏蔽只是屏蔽了本CPU的中断,所以并不能解决SMP引发的竞泰问题,通常,中断屏蔽要和自旋锁联合使用,用于防止访问自旋锁保护的临界区时被中断打断

普通的中断屏蔽

local_irq_disable();    //屏蔽中断//或local_irq_save(flags);  //屏蔽中断并保存目前CPU中的中断位信息/* 临界区 */local_irq_enable();     //解除屏蔽//或local_irq_restore(flags);   //解除屏蔽并恢复中断位信息

底半部的中断屏蔽

local_bh_disable();     //屏蔽中断,bh版本的本质是屏蔽了这个CPU上的软中断

/* 临界区 */local_bh_enable();

延伸阅读

学习是年轻人改变自己的最好方式-Java培训,做最负责任的教育,学习改变命运,软件学习,再就业,大学生如何就业,帮大学生找到好工作,lphotoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训学习是年轻人改变自己的最好方式