嵌入式linux学习记录十三
这是 Linux 驱动开发中利用原子变量(Atomic Variable)实现“互斥锁(设备只能被一个进程打开)”的经典逻辑。
/* 通过判断原子变量的值来检查LED 有没有被别的应用使用 */if (!atomic_dec_and_test(&gpioled.lock)) {
atomic_inc(&gpioled.lock);/* 小于0 的话就加1,使其原子变量等于0 */
return -EBUSY; /* LED 被使用,返回忙 */
}
/* 执行需要保护的资源 */
/* 完成对资源操作后,把锁加1,恢复成资源可以使用的状态 */
atomic_inc(&gpioled.lock);这展示了在 Linux 驱动开发中,利用自旋锁(Spinlock)+ 普通变量(
dev_stats)实现设备互斥访问(只允许一个进程打开)的另一种标准写法。
spin_lock_irqsave(&gpioled.lock, flags); /* 上锁 */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_lock_irqsave(&gpioled.lock, flags); /* 上锁 */
if (gpioled.dev_stats) {
gpioled.dev_stats--;
}
spin_unlock_irqrestore(&gpioled.lock, flags);/* 解锁 */
解释:自旋锁的角色(保镖):它的任务非常短命。它的存在仅仅是为了保护
if (gpioled.dev_stats)和dev_stats++这两行代码在多核并行时不被打扰。它就像一个保镖,护送进程安全地完成“检查并登记”这个动作。dev_stats的角色(登记簿):它的任务非常长命。一旦被写成1,它就会一直保持为1,直到用户层主动调用close()关闭设备。它负责长达几小时、甚至几天的硬件资源占有标记。
