Chinaunix首页 | 论坛 | 博客
  • 博客访问: 122114
  • 博文数量: 22
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 284
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-16 11:37
个人简介

不是一个称职的程序员……

文章分类

全部博文(22)

文章存档

2014年(15)

2013年(7)

我的朋友

分类: 嵌入式

2013-10-17 20:50:47

在应用层可以使用信号量PV操作和互斥锁来实现线程间对临界资源访问的同步与互斥。同样在内核态的驱动程序中,多个执行单元并发执行时也会造成对共享资源的竞争,形成竞态。

linux内核发生竞态的三种情况:
(1)对称多处理器(SMP)的多个CPU,多个CPU共用总线、外设和存储器,必然会造成资源的竞争。
(2)进程与进程之间也有可能对共享资源造成竞争,linux2.6内核以后是支持抢占调度的。
(3)中断和进程之间,中断程序有可能访问当前进程正在访问的资源。

解决办法:
屏蔽中断、原子操作、自旋锁、信号量

1、屏蔽中断
使用方法:
local_irq_disable() //屏蔽中断
....................
临界区
....................
local_irq_enable()//开中断

这种方法使得进程和中断之间竞态消失,同时进程和进程之间的竞态也消失,因为进程调度是依靠中断来实现的。但是,此方法对SMP多CPU引发的竞态则无能为力了。
要求:要尽可能快的执行完临界区代码,中断对CPU至关重要,不能一直关闭。
此方法不常用。


2、原子操作
原子操作指的是在执行过程中不会被别的进程所中断的操作,linux内核提供了两类函数实现原子操作,实现方法参见include/asm/atomic.h 也可参考linux设备驱动开发详解(宋宝华著)P142页。这里不再赘述。

3、自旋锁

所谓自旋,就是当进程不能获得资源时处于忙等待状态,注意不是阻塞态,通俗的说是原地打转。注意:所谓的自旋是对多处理器而言的,单处理器不可能出现自旋状况。
特点:
(1)无法获得锁时处于忙等待(运行态)。
(2)任务获得自旋锁后,内核关抢占。这一点对于单处理器很重要,这就是单处理器使用自旋锁的原因,防止了进程抢断。
(3)一个任务持有锁的时间要尽可能的短。

衍生锁:
读写自旋锁:读与读之间可以同时进行,读与写,写与写之间是互斥的。
顺序锁:读与读,读与写之间是可以同时的,但写与写之间是互斥的。

4、信号量
与自旋锁原理差不多,只是当获取不到信号量时进程不会原地打转,而进入阻塞态。
一般用法:
struct semaphore sem;
sema_init(&sem, 1);
down(&sem);
..................
临界区
..................
up(&sem);


自旋锁                         VS                 信号量
忙等待(运行态)                               等待态
禁止睡眠、调度                                 允许睡眠
时间尽可能短                                    时间不限
可用于中断                                     一般不用于中断
(执行中断时不能睡眠

解释:自旋锁当无法获取锁时或出于忙等待状态(运行态),不会阻塞,而且获得锁以后会禁止调度,这也就实现了进程间的互斥,由于CPU禁止调度也就导致了要求占用锁的时间要尽可能的短,进程禁止调度是件非常可怕的事情。由于自旋锁不会睡眠,因此可以用于中断。
而信号量,无法获取时会阻塞、睡眠,由于信号量对进程调度没有什么影响,所以他的时间要求也没有自旋锁那么严格。由于执行中断时不允许进程阻塞,中断后会禁止调度,进程再一阻塞,会导致系统死掉,所以信号量不能用于中断。

阅读(3139) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~