如何解决并发导致的竞态问题

1. 中断屏蔽

相关函数

local_irq_disable()

local_irq_enable()

local_irq_save(flags)

local_irq_restore(flags)

local_bh_disable()

local_bh_enable()

模板

local_irq_disable();

//critical  section  临界区

local_irq_enable()

例程

void s3c2410_gpio_setpin(unsigned int pin, unsigend int to)

{

void __iomem *base=s3c24xx_GPIO_BASE(pin);

unsigned long offs=s3c2410_GPIO_OFFSET(pin);

unsigned long flags;

unsigned long dat;

local_irq_save(flags);

dat=__raw_read(base+0x04)

...

__raw_write(dat,base+0x04)

local_irq_restore(flags);

}

2. 信号量(semaphore)

信号量本身是一个整数值,可以大于1,

一对操作函数通常称为P和V

进入临界区(P)

      相关信号量上调P

      如果信号量>0,该值减一,进程继续

      如果信号量=0,进程等待,直到其它释放信号量

 退出临界区(V)

      信号量的解锁通过调用V完成

      该函数增加信号量的值

      必要的时候唤醒等待的进程

信号量与互斥体区别

信号量的值可以大于1, 而互斥体值只能为0或者1


初始化信号量

void sema_init(struct semaphore *sem,int val)

初始化静态互斥量

DECLARE_MUTEX(name)   //初始化为1

DECLARE_MUTEX_LOCKED(name)  //初始化为0

初始化动态互斥量

void init_MUTEX(name)   //初始化为1

void init_MUTEX_LOCKED(name)  //初始化为0

获取信号量

void down(struct semaphore *sem)//减小信号量的值,如果不能获得就一直等待

int down_interruptible(struct semaphore *sem)//完成和down一样的工作,但是操作是可以中断的

int down_trylock(struct semaphore *sem)  //永远不会休眠,如果信号量在调用时不可获得,就会立即返回一个非零值

释放信号量

void up(struct semaphore *sem)


使用信号量模板

DECLARE_MUTEX(sem)  //初始化为1

if(down_interruptible(&sem))

{

}

//critical section

up(&sem);

3. 完成量completion

静态初始化             DECLARE_COMPLETION(xxx_completion)    //   

动态创建                struct completion  xxx_completion;//创建一个完成量

                             init_completion(&xxx_completion)

等待完成量,没有完成之前,当前进程阻塞

void  wait_for_completion(struct  completion  *)

触发完成,唤醒一个等待进程

void   complete(struct  completion  *c)//唤醒一个等待线程

void  complete_all(struct  completion  *c)//唤醒所有等待线程

使用示例

DECLARE_COMPLETION(xxx_comp)

ssize_t  complete_read( struct file *file , char __user *buf, size_t count, lofft_t *pos)

{

         wait_for_completion(&xxx_comp);

         return 0;

}

ssize_t  complete_write( struct file *file , char __user *buf, size_t count, lofft_t *pos)

{

           completion(&xxx_comp);

           return 0;

}

4. 自旋锁

自旋锁是一个互斥设备

如果锁被其它设备获得,则代码进入忙循环,则代码进入忙循环并重复检查这个锁。

自旋锁和信号量的区别:

自旋锁是进入忙循环,即进程不阻塞,不退出,一直在while循环。而信号量是进程阻塞。

初始化自旋锁

spinlock_t  xxx_lock=SPIN_LOCK_UNCLKED;

void  spin_lock_init(spinlock_t  *lock);

锁定函数

void  spin_lock(spinlock_t  *lock)

获得自旋锁之前禁止中断(包括软件中断和硬件中断)

void  spin_lock_irq(spinlock_t  *lock)

获得自旋锁之前禁止中断(包括软件中断和硬件中断),中断状态保存在状态字flags中

void  spin_lock_irqsave(spinlock_t  *lock,  unsigned long flags)

获得自旋锁之前禁止软件中断,硬件中断保持打卡

void  spin_lock_bh(spinlock_t  *lock)

释放自旋锁

void  spin_unlock(spinlock_t  *lock)

void  spin_unlock_irqsave(spinlock_t  *lock,  unsigned long flags)

void  spin_unlock_irqsave(spinlock_t  *lock,  unsigned long flags)

void  spin_unlock_bh(spinlock_t  *lock)

自旋锁模板

spinlock_t  lock;

void  spin_lock_init(spinlock_t  &lock);

spin_lock(&lock)

//critical  section

spin_unlock(&lock)

5. 原子操作

http://www.jianshu.com/writer#/notebooks/917048/notes/1679174

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 临界区 1.1简介 在早期计算机系统中,只有一个任务进程在执行,并不存在资源的共享与竞争。随着技术和需求的飞速...
    Fly晴天里Fly阅读 9,103评论 2 13
  • 内核里处理的竞态主要通过以下方法处理: 信号量(互斥量)、自旋锁、读写信号量、读写自旋锁、等待队列、完成量。 信号...
    Lmmmmbbb阅读 674评论 0 0
  • 线程安全是怎么产生的 常见比如线程内操作了一个线程外的非线程安全变量,这个时候一定要考虑线程安全和同步。 - (v...
    幽城88阅读 696评论 0 0
  • POSIX threads(简称Pthreads)是在多核平台上进行并行编程的一套常用的API。线程同步(Thre...
    北辰青阅读 1,016评论 0 1
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,855评论 0 9