企业级网站内容管理解决方案百度网站快速优化
企业级网站内容管理解决方案,百度网站快速优化,电商网站开发案例,公司国外网站建设最近在内核频繁使用了自旋锁#xff0c;自旋锁如果使用不当#xff0c;极易引起死锁#xff0c;在此总结一下。
自旋锁是一个互斥设备#xff0c;它只有两个值#xff1a;“锁定”和“解锁”。它通常实现为某个整数值中的某个位。希望获得某个特定锁得代码测试相关的位。…最近在内核频繁使用了自旋锁自旋锁如果使用不当极易引起死锁在此总结一下。
自旋锁是一个互斥设备它只有两个值“锁定”和“解锁”。它通常实现为某个整数值中的某个位。希望获得某个特定锁得代码测试相关的位。如果锁可用则“锁定”被设置而代码继续进入临界区相反如果锁被其他人获得则代码进入忙循环而不是休眠这也是自旋锁和一般锁的区别并重复检查这个锁直到该锁可用为止这就是自旋的过程。“测试并设置位”的操作必须是原子的这样即使多个线程在给定时间自旋也只有一个线程可获得该锁。
自旋锁最初是为了在多处理器系统SMP使用而设计的但是只要考虑到并发问题单处理器在运行可抢占内核时其行为就类似于SMP。因此自旋锁对于SMP和单处理器可抢占内核都适用。可以想象当一个处理器处于自旋状态时它做不了任何有用的工作因此自旋锁对于单处理器不可抢占内核没有意义实际上非抢占式的单处理器系统上自旋锁被实现为空操作不做任何事情。
自旋锁有几个重要的特性1、被自旋锁保护的临界区代码执行时不能进入休眠。2、被自旋锁保护的临界区代码执行时是不能被被其他中断中断。3、被自旋锁保护的临界区代码执行时内核不能被抢占。从这几个特性可以归纳出一个共性被自旋锁保护的临界区代码执行时它不能因为任何原因放弃处理器。
考虑上面第一种情况想象你的内核代码请求到一个自旋锁并且在它的临界区里做它的事情在中间某处你的代码失去了处理器。或许它已调用了一个函数copy_from_user假设使进程进入睡眠。也或许内核抢占发威一个更高优先级的进程将你的代码推到了一边。此时正好某个别的线程想获取同一个锁如果这个线程运行在和你的内核代码不同的处理器上幸运的情况那么它可能要自旋等待一段时间可能很长当你的代码从休眠中唤醒或者重新得到处理器并释放锁它就能得到锁。而最坏的情况是那个想获取锁得线程刚好和你的代码运行在同一个处理器上这时它将一直持有CPU进行自旋操作而你的代码是永远不可能有任何机会来获得CPU释放这个锁了这就是悲催的死锁。
考虑上面第二种情况和上面第一种情况类似。假设我们的驱动程序正在运行并且已经获取了一个自旋锁这个锁控制着对设备的访问。在拥有这个锁得时候设备产生了一个中断它导致中断处理例程被调用而中断处理例程在访问设备之前也要获得这个锁。当中断处理例程和我们的驱动程序代码在同一个处理器上运行时由于中断处理例程持有CPU不断自旋我们的代码将得不到机会释放锁这也将导致死锁。
因此如果我们有一个自旋锁它可以被运行在硬件或软件中断上下文中的代码获得则必须使用某个禁用中断的spin_lock形式的锁来禁用本地中断注意只是禁用本地CPU的中断不能禁用别的处理器的中断使用其他的锁定函数迟早会导致系统死锁导致死锁的时间可能不定但是发生上述死锁情况的概率肯定是有的看处理器怎么调度了。如果我们不会在硬中断处理例程中访问自旋锁但可能在软中断例如以tasklet的形式运行的代码中访问则应该使用spin_lock_bh以便在安全避免死锁的同时还能服务硬件中断。
补充
锁定一个自旋锁的函数有四个
void spin_lock(spinlock_t *lock);
最基本得自旋锁函数它不失效本地中断。
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
在获得自旋锁之前禁用硬中断只在本地处理器上而先前的中断状态保存在flags中
void spin_lockirq(spinlock_t *lock);
在获得自旋锁之前禁用硬中断只在本地处理器上不保存中断状态
void spin_lock_bh(spinlock_t *lock);
在获得锁前禁用软中断保持硬中断打开状态
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/87983.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!