1、原子操作(atomic)
2、自旋锁(spin_lock)
3、信号量(semaphore)
4、互斥体(mutex)
5、中断屏蔽
并发控制:
并发:
指的是多个执行单元同时、并行被执行
竞态:
而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态
竞态发生的情况:1, 多cpu, 2, 单cpu , 支持多任务的调度, 抢占
- 单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。
驱动中使用原子变量:
- atomic_t tatomic = ATOMIC_INIT(1); 定义原子变量并初始化为 1
- 在open设备时, 判断下原子变量
if(!atomic_dec_and_test(&tatomic)) 对原子变量减1 并测试, 减1 之后如果为0, 返回true,
{
atomic_inc(&tatomic); // 在return前, 维持原子变量的原值,
return -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 时候, 有写操作, 需要再读一次,
信号量:
- 定义信号量 struct semaphore sem;
- 初始化信号量 void sema_init(struct semaphore *sem, int val); // 信号量的初始值, 根据资源情况设定 的
- 获取信号量 :
void down(struct semaphore * sem); 获取信号量, 一直在等信号量, 中断无法激活该进程
int down_interruptible(struct semaphore * sem); 获取信号量, 等信号量, 中断可以激活该进程
int down_trylock(struct semaphore * sem); 尝试获取信号量, 获取到了, 正常向下执行, 没有获取到信号量, 返回一个结果,
- 释放信号量:
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); 释放一个互斥体