【自旋锁】
线程A获取自旋锁后,B假如想获取自旋锁则只能原地等待,仍占用CPU,不会休眠,直到获取自旋锁为止。
【函数】
DEFINE SÃINLOCK(spinlock t lock) 定义并初始化一个变量
int spin lock init(spinlock t*lock) 初始化自旋锁
void spin lock(spinlock t *lock) 获取自旋锁。也叫做加锁
void spin_unlock(spinlock t *lock) 释放自旋锁,也叫做解锁
int spin trylock(spinlock t *lock) 尝试获取自旋锁,如果没有获取到就返回0
int spin is locked(spinlock t *lock) 检查自旋锁是否被获取,如果没有被获取就返回非0,否则返回0
【如何使用】
- 访问临界资源时首先申请自旋锁
- 获取自旋锁后进入临界区,获取不到就等待
- 退出临界区释放自旋锁
【临界区】
【注意事项】
- 原地等待消耗CPU。临界区代码一定不能多。
- 临界区中不可以调用会导致进程休眠的函数,否则可能死锁
- 一般用于多核CPU
【实验】
/* 定义一个自旋锁 */
static spinlock_t my_spinlock;
static flag = 1; //标志位模拟驱动有没有被用到
static int cdev_open(struct inode *inode, struct file *filp)
{
spin_lock(my_spinlock); //加锁
if(flag != 1){
spin_unlock(my_spinlock);
return -EBUSY;
}
flag = 0;
spin_unlock(my_spinlock); //解锁
file->private_data = &dev1; //指向设备结构体
return 0;
}
static int cdev_release(struct inode *inode, struct file *filp)
{
spin_lock(my_spinlock); //加锁
flag = 1;
spin_unlock(my_spinlock); //解锁
}
【验证】
int main(int argc, char *argv[])
{
int fd1;
char buf1[32] = "ni hao test1!";
fd1 = open("/dev/test1", HELLO); /* 打开设备节点1 */
sleep(5); /* 延时5秒,为了实验效果*/
close(fd1);
return 0;
}
【实验结果】
A打开驱动程序,假设执行到FLAG = 0,此时又有B要使用驱动,那么Flag = 0意味着A正在使用驱动,同时Flag =0 使得flag !=1所以B进不去驱动,只能报错。
当等A使用驱动完毕,触发release函数,flag被置为1,才意味着其他程序可以使用驱动了。