版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34770510/article/details/78343817
第5章 并发和竞争情况
1 通过举例内存分配
if (!dptr->data[s_pos]) {
dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);
if (!dptr->data[s_pos])
goto out;
}
假设2个进程同时走到dptr->data[s_pos]这一行,会造成竞争,来引出并发和管理的必要性
2 避免和处理并发的方法
2.1 旗标和互斥体
原理:
一个进程进入临界区,调用函数获取旗标,如果旗标大于0(进程继续执行,这个值是递减1的),反之,我们去释放掉旗标。
作用:阻止多个进程在同一个临界区内运行,
方法:函数选择其中1个
声明 <asm/semaphore.h>
初始化 void sema_init(struct semaphore *sem, int val);
互斥锁初始化 DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem);
获取旗标 void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
释放旗标 void up(struct semaphore *sem);
2.2 自旋锁
原理:
分为“上锁”,“解锁”,一个进程先到执行的部分,就上锁,另外的进程想执行必须反复检查这个锁 直到其中的进程被解锁
作用: 另一个互斥的方法
方法:函数选择其中1个
声明 <linux/spinlock.h>
初始化 spinlock_t my_lock = SPIN_LOCK_UNLOCKED;
运行时使用 void spin_lock_init(spinlock_t *lock);
上锁 void spin_lock(spinlock_t *lock);
解锁 void spin_unlock(spinlock_t *lock);
3 锁陷阱
当你编写你的代码, 你会毫无疑问遇到几个函数需要存取通过一个特定锁保护的结构. 在
此, 你必须小心: 如果一个函数需要一个锁并且接着调用另一个函数也试图请求这个锁,
你的代码死锁. 不论旗标还是自旋锁都不允许一个持锁者第 2 次请求锁; 如果你试图这
样做, 事情就简单地完了.
4 加锁的各种选择
4.1 不加锁算法
write放数据到一个数组的尾端, 而read从另一端移走数据. 当到达数组末端, write绕回到开始. 因此一个环形缓存需要一个数组和 2 个索引值来跟踪下一个新值放到哪里,
以及哪个值在下一次应当从缓存中移走.
我是真没看懂这个翻译写的什么