一步一步走进字符驱动--自旋锁

本文深入介绍了自旋锁的概念及其在操作系统中的应用。自旋锁作为一种常见的临界区资源互斥访问手段,在多处理器环境中尤为关键。文章详细阐述了自旋锁的定义、初始化、获取与释放过程,并通过示例代码展示了如何利用自旋锁实现设备打开的唯一性。

一步一步走进字符驱动--自旋锁

前面说到原子操作和今天的自旋锁,以及信号量等.都是为了防止抢占式操作系统和SMP所带来的竞态的发生.那么什么叫竞态呢?相信很多学过linux系统编程和window 开发的都知道.当一个进程在访问一个公共资源时,由于时间片时间到或者被抢占等,会导致其他进程运行,有可能也访问该资源.那么就会修改这份资源,导致本来的进程再此操作这份资源时,资源内的数据已被修改..由于这种情况,所以操作系统才引出各种锁来锁定公共资源来达到资源的保护.

今天我们大致看一下自旋锁.

简介:

自旋锁是一种典型的对临界区资源进行互斥访问的手段,其名称是根据它的工作方式得来的.为了获得自旋锁,在某CPU上运行的代码需先执行一个原子操作,该操作测试并设置某一内存变量,由于它是原子操作,所以在该操作完成之前其他执行单元不能访问这个内存变量.如果测试结果表明锁已经空闲,则程序获得这个自旋锁并继续执行,如果测试表明锁仍被占用,程序将在一个小的循环内重复这个"测试并设置"操作,即进行所谓的"自旋",就是原子打转.

自旋锁定义:	linux/Spinlock.h
typedef struct spinlock {
union {
struct raw_spinlock rlock;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
struct {
u8 __padding[LOCK_PADSIZE];
struct lockdep_map dep_map;
};
#endif
};
} spinlock_t;

1:定义自旋锁

spinlock_t lock;

2:初始化自旋锁

spin_lock_init(lock); //该宏用于动态初始化自旋锁

3:获得自旋锁

static inline void spin_lock(spinlock_t *lock); //获取自旋锁,若能获取,则立即返回,否则自选在这等待获取

static inline int spin_trylock(spinlock_t *lock); //尝试获取自旋锁,若能获取则返回TRUE,否则返回FALSE,不原地自选

4:释放自旋锁

static inline void spin_unlock(spinlock_t *lock); //释放获得的自旋锁

示例:

/*定义一个自旋锁*/

spinlock_t lock;

spin_lock_init(lock);

spin_lock(&lock); //获取自旋锁

/*临界区资源*/

spin_unlock(&lock); //释放自旋锁

由于自旋锁在自旋时不能被中断打断,否则将锁死,所以延伸出带中断的自旋锁

static inline void spin_lock_irq(spinlock_t *lock);
static inline void spin_unlock_irq(spinlock_t *lock);
#define spin_lock_irqsave(spinlock_t *lock, flags);
static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
static inline void spin_lock_bh(spinlock_t *lock);
static inline void spin_unlock_bh(spinlock_t *lock);

自旋锁主要针对单SMP和单CPU但支持抢占式的情况,对于单CPU和内核不支持抢占式的话,自旋锁会退化成空操作.

自旋锁实现设备打开唯一性,示例代码:

spinlock_t 	lock;
int	 global_count = 0;	//定义文件被打开的次数
int 	global_mem_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋给文件私有数据指针*/
struct globalmem_dev *devp;
devp = container_of(inode->i_cdev,struct globalmem_dev,cdev);
filp->private_data = devp;
spin_lock(&lock);
if (global_count) { //文件被打开
return -EBUSY;
}
global_count++;//增加使用计数器
spin_unlock(&lock);
/*判断文件打开的标志*/
return 0;
}
int 	global_mem_release(struct inode *inode, struct file *filp)
{
spin_lock(&lock);
global_count--;//减少使用计数器
spin_unlock(&lock);
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值