
这是 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()关闭设备。它负责长达几小时、甚至几天的硬件资源占有标记。