linux驱动的并发控制

1、原子操作(atomic)

2、自旋锁(spin_lock)

3、信号量(semaphore)

4、互斥体(mutex)

5、中断屏蔽

 

并发控制:

并发:

指的是多个执行单元同时、并行被执行

竞态:

而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态

 

竞态发生的情况:1, 多cpu, 2, 单cpu , 支持多任务的调度, 抢占

  1.  单cpu, 不支持多任务,不支持任务调度,抢占,

 

互斥访问:

是指一个执行单元在访问共享资源的时候,其他的执行单元被禁止访问。

临界区:

访问共享资源的代码区域称为

互斥机制:

中断屏蔽 ,   原子操作,  自旋锁,  信号量,  互斥体

 

 

中断屏蔽:

不能解决多cpu 引发的竞态

 

原子操作:

定义原子变量

atomic_t v = ATOMIC_INIT(0); /

原子变量++

void atomic_inc(atomic_t *v);    /* 原子变量增加1 */

原子变量操作及测试:

int atomic_dec_and_test(atomic_t *v);

上述操作对原子变量执行自减操作后(注意没有加)测试其是否为0,为0返回true,否则返回false。

驱动中使用原子变量:

  1. atomic_t  tatomic = ATOMIC_INIT(1);  定义原子变量并初始化为 1
  2. 在open设备时, 判断下原子变量

                if(!atomic_dec_and_test(&tatomic))   对原子变量减1 并测试, 减1 之后如果为0, 返回true,

         {

                  atomic_inc(&tatomic);                    // 在return前, 维持原子变量的原值,

                  return -1;

         }      

  1. 在close设备的时候,

atomic_inc(&tatomic);             原子变量加1, 之后原子变量值为1, 表示设备又可以用了

 

原子操作的理解:

就是用原子变量 和 原子变量的相关操作, 用我们的逻辑实现了设备的互斥。

 

自旋锁:

定义自旋锁

spinlock_t  lock;

初始化自旋锁

spin_lock_init(&lock)

获得自旋锁

spin_lock(&lock)

如果能够立即获得锁,它就马上返回,否则,它将自旋在那里

spin_trylock(&lock)

该宏尝试获得自旋锁lock,如果能立即获得锁,它获得锁并返回真,否则立即返回假

释放自旋锁

spin_unlock(&lock)

 

 

自旋锁在驱动里的使用:

spinlock_t    tLock;      定义一个自旋锁变量

spin_lock_init(&tLock);      初始化自旋锁变量 tLock

 

获取自旋锁:

Spin_lock(&tLock)

释放自旋锁

Spin_unlock(&tLock);

 

 

自旋锁其他操作:

spin_lock_irq() = spin_lock() + local_irq_disable()     在获取锁的时候, 关掉中断

spin_unlock_irq() = spin_unlock() + local_irq_enable()           在释放锁的时候, 使能中断         

 

spin_lock_irqsave() = spin_lock() + local_irq_save()     在获取锁的时候, 保存中断的状态,  中断关掉

spin_unlock_irqrestore() = spin_unlock() + local_irq_restore() 在释放锁的时候, 恢复中断的状态

 读写自旋锁:

举例: 一段 buffer,  一个进程去写, 多个进程去读, 读写不同时, 

顺序锁:

一段buffer, 一个进程写, 多个进程可以去读, 读写同时进行, 读buffer 时候, 有写操作, 需要再读一次,

 

 

 

信号量:

  1. 定义信号量      struct semaphore                   sem;
  2. 初始化信号量    void  sema_init(struct semaphore *sem,    int val);       // 信号量的初始值, 根据资源情况设定 的
  3. 获取信号量  :

void  down(struct semaphore * sem);     获取信号量, 一直在等信号量, 中断无法激活该进程

int  down_interruptible(struct semaphore * sem);   获取信号量, 等信号量, 中断可以激活该进程

 

int  down_trylock(struct semaphore * sem);  尝试获取信号量, 获取到了, 正常向下执行, 没有获取到信号量, 返回一个结果,

  1. 释放信号量:

void up(struct semaphore * sem);

 

互斥体:

一个二值的信号量, 

可以解决信号量无法解决的问题:   优先级翻转 ,   天花板协议

相关函数:

struct mutex my_mutex;        定义一个互斥体

mutex_init(&my_mutex);                                 初始化一个互斥体

void inline _ _sched mutex_lock(struct mutex *lock);                           获取一个互斥体

void __sched mutex_unlock(struct mutex *lock);                          释放一个互斥体

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值