我在内核模块中有一个受spin_lock()
保护的关键部分。我使用spin_lock()
在不禁用 irq 或 softirqs 的情况下获取锁。众所周知,IOCTL 是通过软件中断 128 (0x80( 进入内核的系统调用。因此,如果我们在获取spin_lock()
的关键部分中间从用户空间发出 IOCTL,是否会发生上下文切换?如果在 IOCTL 的后端也使用相同的spin_lock()
,该怎么办?它会导致僵局吗?
我使用 spin_lock(( 在不禁用 irq 或 软IRQS
IRQ/SoftIRQ 与系统调用无关。当可以从中断上下文中使用受保护的数据结构时,需要禁用 IRQ 或软 IRQ。顺便说一句,有一个特殊的spin_lock
- API,如spin_lock_bh()/spin_unlock_bh()
,spin_lock_irq()
/spin_unlock_irq()
等。您应该阅读本指南。
是否会发生上下文切换?
我没有看到任何可以阻止它的东西(如果您的意思是系统调用上下文切换(。当系统调用发生时,它会在用户上下文(进程上下文 - 例如引发系统调用的进程上下文(中进入内核模式(上下文切换(,而不是中断或软中断上下文。因此,如果您的数据结构只能从用户上下文中访问 - 则应为用户上下文使用常规锁定 API。
至于在内核模式下按住自旋锁时的上下文切换 - 它不会发生,因为自旋锁本身会禁用抢占:
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
preempt_disable();
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
然后只有更高优先级的代码可以抢占(IRQ,softIRQ(,但如果"更高优先级的代码"不会尝试获取您持有的锁,则无需担心(从死锁的角度来看(。
如果在 IOCTL 的后端也使用相同的 spin_lock(( 怎么办?
它肯定会"旋转",直到您松开锁。
它会导致僵局吗?
取决于你将如何使用它。
附言互斥体有什么问题?
另请阅读:
- 旋转锁
- 互斥锁
- IRQ
- 上下文切换内部
- 在 Linux 上的 32 位代码中,"int 0x80"或"syscall"哪个更好?