一个网站能放多少关键词,国企招聘网最新招聘2023,网站建设运营公司企业特色,广东建设安全质量协会网站接前一篇文章#xff1a;Linux内核与驱动面试经典“小”问题集锦#xff08;1#xff09; 问题2
问#xff1a;spin_lock和spin_lock_irq以及spin_lock_irqsave的区别是什么#xff1f;也可以说它们之间有什么区别和联系#xff1f;
备注#xff1a;此题是自旋锁问题的…接前一篇文章Linux内核与驱动面试经典“小”问题集锦1 问题2
问spin_lock和spin_lock_irq以及spin_lock_irqsave的区别是什么也可以说它们之间有什么区别和联系
备注此题是自旋锁问题的进一步问题一般都是在前边你回答出Linux内核的锁机制之后上一回的问题1参见Linux内核与驱动面试经典“小”问题集锦1的进一步提问、追问。这个问题在蔚来、比特大陆以及其它一些公司面试时问到过。
答
spin_lock()/spin_unlock()是自旋锁机制的基础其与关中断local_irq_disable()/开中断local_irq_enable()、关中断并保存状态字local_irq_save()/开中断并恢复状态字local_irq_restore()、关底半部local_bh_disable()/开底半部local_bh_enable()形成了整套自旋锁机制。其相互之间的关系如下
spin_lock与spin_lock_irq的关系 spin_lock_irq() spin_lock() local_irq_disable() 即spin_lock_irq()是spin_lock()的同时关中断。与之相对应 spin_unlock_irq() spin_unlock() local_irq_enable() 即spin_unlock_irq()是spin_unlock()的同时开中断。
spin_lock与spin_lock_irqsave的关系 spin_lock_irqsave() spin_lock() local_irq_save() 即spin_lock_irqsave()是spin_lock()的同时关中断并保存状态字。与之相对应 spin_unlock_irqrestore() spin_unlock() local_irq_restore() 即spin_unlock_irqrestore()是spin_unlock()的同时开中断并恢复状态字。
spin_lock与spin_lock_bh的关系 spin_lock_bh() spin_lock() local_bh_disable() 即spin_lock_bh()是spin_lock()的同时关底半部。与之相对应 spin_unlock_bh() spin_unlock() local_bh_enable() 即spin_unlock_bh()是spin_unlock()的同时开底半部。
spin_lock_irq()、spin_lock_irqsave()、spin_lock_bh()类似函数会为自旋锁的使用“系好安全带”以避免突如其来的中断驶入对系统造成的伤害。 问题3
问中断中应该使用自旋锁还是信号量或互斥锁
备注这个问题在百度、蔚来以及其它一些公司面试时问到过。
答
自旋锁是专为防止多处理器并发而引入的一种锁它在内核中大量应用于中断处理等部分。自旋锁最多只能被一个内核任务持有。在单处理器上自旋锁仅仅当作一个设置内核抢占的开关内核不能被抢占。
信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时信号量会将其推入等待队列然后让其睡眠当持有信号量的进程将信号量释放后在等待队列中的一个任务将被唤醒从而便可以获得这个信号量。信号量不同于自旋锁它不会关闭内核抢占所以持有信号量的代码可以被抢占。信号量只能在进程上下文中使用因为中断上下文中是不能被调度的即在中断上下文中释放时不能进行进程切换。
综上由于在中断中不能被调度并且中断处理函数是不可重入的因此中断中应该选择自旋锁而非信号量或互斥锁等。
额外
这里要多说一点。如果做出上述回答后面试官继续追问为什么中断中不能休眠或进行调度则原因如下
1中断处理的时候不应该发生进程切换因为在中断上下文中唯一能打断当前中断handler的只有更高优先级的中断它不会被进程打断。如果在中断上下文中休眠则没有办法唤醒它因为所有的wake_up_xxx都是针对某个进程而言的而在中断上下文中没有进程task_struct的概念因此如果真的休眠则内核几乎肯定会死。
2schedule()在切换进程时保存当前的进程上下文CPU寄存器的值、进程的状态以及堆栈中的内容以便以后恢复此进程运行。中断发生后内核会先保存当前被中断的进程上下文在调用中断处理程序后恢复。但在中断处理程序里CPU寄存器的定已经变化了吧最重要的程序计数器PC、堆栈SP等如果此时因为睡眠或阻塞操作调用了schedule()则保存的进程上下文就不是当前的进程上下文了。所以不可以在中断处理程序中调用schedule()以及引发schedule()的操作。 参考资料
《Linux设备驱动开发详解 —— 基于最新的Linux 4.0内核》 宋宝华 编著机械工业出版社
信号量和自旋锁的选择
为什么中断不能睡眠