arm-linux 自旋锁

自旋锁的使用注意事项:
①、 自旋锁保护的临界区要尽可能的短 ,因此在 open 函数中申请自旋锁,然后在 release
数中释放自旋锁的方法就不可取。我们可以使用一个变量来表示设备的使用情况,如果设备被
使用了那么变量就加一,设备被释放以后变量就减 1 ,我们只需要使用 自旋锁保护这个变量
可。
②、考虑驱动的兼容性,合理的选择 API 函数。
综上所述,在本节例程中,我们通过定义一个变量 dev_stats 表示设备的使用情况, dev_stats
0 的时候表示设备没有被使用, dev_stats 大于 0 的时候表示设备被使用。驱动 open 函数中先
判断 dev_stats 是否为 0 ,也就是判断设备是否可用,如果为 0 的话就使用设备,并且将 dev_stats
1 ,表示设备被使用了。使用完以后在 release 函数中将 dev_stats 1 ,表示设备没有被使用
了。因此真正实现设备互斥访问的是变量 dev_stats ,但是我们要使用自旋锁对 dev_stats 来做保
护。
设备结构体:
/* gpioled 设备结构体 */
34 struct gpioled_dev {
35 dev_t devid ; /* 设备号 */
36 struct cdev cdev ; /* cdev */
37 struct class * class ; /* */
38 struct device * device ; /* 设备 */
39 int major ; /* 主设备号 */
40 int minor ; /* 次设备号 */
41 struct device_node * nd ; /* 设备节点 */
42 int led_gpio ; /* led 所使用的 GPIO 编号 */
43 int dev_stats ; /* 设备状态, 0 ,设备未使用 ;>0, 设备已经被使用 */
44 spinlock_t lock ; /* 自旋锁 */
45 };
open函数:
spin_lock_irqsave (& gpioled . lock , flags ); /* 上锁 *
/*调用 spin_lock_irqsave 函数获
取锁,为了考虑到驱动兼容性,这里并没有使用 spin_lock 函数来获取锁。*/
if ( gpioled . dev_stats ) { /* 如果设备被使用了
spin_unlock_irqrestore (& gpioled . lock , flags ); /* 解锁 */
return - EBUSY ;
}
gpioled . dev_stats ++; /* 如果设备没有打开,那么就标记已经打开了 */ spin_unlock_irqrestore (& gpioled . lock , flags ); /* 解锁 */ *
判断 dev_stats 是否大于 0 ,如果是的话表示设备已经被使用了,那么就调用 spin_unlock_irqrestore 函数释放锁,并且返回-EBUSY 。如果设备没有被使用的话就在第 66 行将 dev_stats 1 ,表 示设备要被使用了,然后调用 spin_unlock_irqrestore 函数释放锁。自旋锁的工作就是保护 dev_stats 变量,真正实现对设备互斥访问的是 dev_stats

release 函数:
/* 关闭驱动文件的时候将 dev_stats 1 */
spin_lock_irqsave (& dev -> lock , flags ); /* 上锁 */
if ( dev -> dev_stats )
{ dev -> dev_stats --; }
spin_unlock_irqrestore (& dev -> lock , flags ); /* 解锁 */
dev_stats 1 ,表示设备被释放了,可以被其他的应用 程序使用。将 dev_stats 1 的时候需要自旋锁对其进行保护。
init 函数:
/* 初始化自旋锁 */ spin_lock_init (& gpioled . lock );

猜你喜欢

转载自blog.csdn.net/L1153413073/article/details/125548087