关中断与自旋锁
2023年11月 · 预计阅读时间: 2 分钟
问题来自于学习DS18B20温度传感器Linux驱动,因为设备脉冲信号时间很短,很可能错失中断,且需要关中断
在read函数中完成硬件操作:启动温度转换,休眠等待1s,再读取温度。关中断使用spin_lock_irqsave(&ds18b20_spinlock, flags);
,恢复中断使用spin_unlock_irqrestore(&ds18b20_spinlock, flags);
关中断与自旋锁等知识见《Linux设备驱动开发详解 - 宋宝华》7.5自旋锁 7.5.1 自旋锁的使用。 自旋锁可以保证临界区不受别的CPU和本CPU内的抢占进程打扰,但是得到锁的代码路径在执行临界区的时候,还可能受到中断和底半部(BH,稍后的章节会介绍)的影响。
这两对函数的区别在于 IRQ(中断请求)的状态的保存和恢复方式。
spin_lock_irq()
和spin_unlock_irq()
:
spin_lock_irq()
函数会先禁用 IRQ,然后获取自旋锁。spin_unlock_irq()
函数会先释放自旋锁,然后启用 IRQ。这对函数中,IRQ 的状态不会保存和恢复。如果在获取锁期间发生中断,中断处理程序将不会执行,因为 IRQ 被禁用,这可能会导致一些问题。
spin_lock_irqsave()
和spin_unlock_irqrestore()
:
spin_lock_irqsave()
函数会先保存当前 CPU 的 IRQ 状态,并禁用 IRQ,然后获取自旋锁。spin_unlock_irqrestore()
函数会先释放自旋锁,然后恢复保存的 IRQ 状态。这对函数会在获取锁之前保存当前 CPU 的 IRQ 状态,并在释放锁后恢复保存的 IRQ 状态。这样,在获取锁期间发生的中断不会被忽略,而是在释放锁后恢复执行中断处理程序。
注意:在使用
spin_lock_irqsave()
和spin_unlock_irqrestore()
时,必须将unsigned long
类型的变量用作第二个参数,用于保存和恢复 IRQ 状态。