第5章:并发与竞态条件-9:The Spinlock Functions

In continuation of the previous text 第5章:并发与竞态条件-8:Introduction to the Spinlock API, let's GO ahead.

The Spinlock Functions

Wehave already seen two functions, spin_lock and spin_unlock, that manipulate spin locks. There are several other functions, however, with similar names and purposes. Wewill now present the full set. This discussion will take us into ground we will not be able to cover properly for a few chapters yet; a complete understanding of the spin lock API requires an understanding of interrupt handling and related concepts.

There are actually four functions that can lock a spinlock:

我们已经介绍了 spin_lock 和 spin_unlock 两个操作自旋锁的核心函数,此外还有多个名称相似、用途相关的函数。下面将完整介绍自旋锁的函数集 —— 部分内容涉及后续章节的知识点(如中断处理),对自旋锁 API 的全面理解需要结合这些概念。

共有 4 个函数可用于获取自旋锁,核心差异在于是否禁用中断及禁用范围:

void spin_lock(spinlock_t *lock);
 void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
 void spin_lock_irq(spinlock_t *lock);
 void spin_lock_bh(spinlock_t *lock);

Wehave already seen how spin_lock works. spin_lock_irqsave disables interrupts (on the local processor only) before taking the spinlock; the previous interrupt state is stored in flags. If you are absolutely sure nothing else might have already disabled interrupts on your processor (or, in other words, you are sure that you should enable interrupts when you release your spinlock), you can use spin_lock_irq instead and not have to keep track of the flags. Finally, spin_lock_bh disables software interrupts before taking the lock, but leaves hardware interrupts enabled.

  • spin_lock:核心获取函数,仅获取锁,不影响中断状态。持有锁期间会禁用本地 CPU 抢占,但硬件中断和软件中断仍可响应。

  • spin_lock_irqsave:获取锁前先禁用本地 CPU 的硬件中断,并将中断的原始状态保存到 flags 中(flags 需为全局或栈上变量,不能是临时指针)。这是最安全的变体,适用于 “锁可能被中断处理程序访问” 的场景。

  • spin_lock_irq:获取锁前禁用本地 CPU 的硬件中断,但不保存中断状态。仅当你能确定当前中断处于启用状态,且释放锁时需要重新启用中断时才能使用,否则可能导致中断状态混乱。

  • spin_lock_bh:获取锁前禁用软件中断(bottom half,如下半部、tasklet),但保留硬件中断启用。适用于锁仅被进程上下文和软件中断访问,无需屏蔽硬件中断的场景。

If you have a spinlock that can be taken by code that runs in (hardware or software) interrupt context, you must use one of the forms of spin_lock that disables inter rupts. Doing otherwise can deadlock the system, sooner or later. If you do not access your lock in a hardware interrupt handler, but you do via software interrupts (in code that runs out of a tasklet, for example, a topic covered in Chapter 7), you can use spin_lock_bh to safely avoid deadlocks while still allowing hardware interrupts to be serviced.

若自旋锁可能被中断上下文(硬件 / 软件中断) 访问,必须使用上述带 “中断禁用” 的锁定函数(spin_lock_irqsave/spin_lock_irq/spin_lock_bh),否则迟早会导致系统死锁;若仅在进程上下文和软中断上下文共享锁,用 spin_lock_bh 即可(无需禁用硬件中断,提升响应性)。

There are also four ways to release a spinlock; the one you use must correspond to the function you used to take the lock:

释放函数需与获取函数严格对应,撤销获取时的中断操作:

 void spin_unlock(spinlock_t *lock);
 void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
 void spin_unlock_irq(spinlock_t *lock);
 void spin_unlock_bh(spinlock_t *lock);

Each spin_unlock variant undoes the workperformed by the corresponding spin_lock function. The flags argument passed to spin_unlock_irq restore must be the same variable passed to spin_lock_irqsave. You must also call spin_lock_irqsave and spin_ unlock_irqrestore in the same function; otherwise, your code may breakon some architectures.

每个释放函数的作用是 “撤销对应锁定函数的操作”:

  1. spin_unlock:释放锁,恢复本地 CPU 的抢占;

  2. spin_unlock_irqrestore:释放锁,并通过 flags 恢复中断的原始状态;

  3. spin_unlock_irq:释放锁,并重新启用本地 CPU 的中断;

  4. spin_unlock_bh:释放锁,并重新启用软中断。

There is also a set of nonblocking spinlock operations:

这类函数尝试获取锁时不会自旋等待,立即返回结果:

 int spin_trylock(spinlock_t *lock);
 int spin_trylock_bh(spinlock_t *lock);

These functions return nonzero on success (the lockwas obtained), 0 otherwise. There is no “try” version that disables interrupts.

获取成功返回非零值,失败返回 0。无 “禁用硬件中断” 的非阻塞变体(避免中断状态意外变更)。

补充说明:

  1. 函数配对强制规则:获取与释放函数必须一一对应,否则会导致中断状态混乱或死锁。

    锁定函数释放函数适用场景
    spin_lockspin_unlock仅进程上下文共享锁,无中断 / 软中断访问
    spin_lock_irqsavespin_unlock_irqrestore进程 + 硬件中断上下文共享锁(最常用安全变体)
    spin_lock_irqspin_unlock_irq确定当前中断开启,且需禁用中断的场景
    spin_lock_bhspin_unlock_bh进程 + 软中断上下文共享锁(保留硬件中断)
    spin_trylockspin_unlock非阻塞获取锁,仅进程上下文
    spin_trylock_bhspin_unlock_bh非阻塞获取锁,进程 + 软中断上下文
  2. flags 参数的正确使用flags 是 unsigned long 类型,用于保存中断状态,必须在栈上分配(避免多线程竞争),示例:

    unsigned long flags;
    spin_lock_irqsave(&my_lock, flags); // 保存状态并禁用中断
    // 临界区操作...
    spin_unlock_irqrestore(&my_lock, flags); // 恢复状态并释放锁
  3. 非阻塞函数的使用场景:适合 “尝试一次即可” 的场景,例如:

    if (spin_trylock(&my_lock)) {
        // 成功获取锁,执行临界区
        spin_unlock(&my_lock);
    } else {
        // 获取失败,执行备选逻辑
        return -EBUSY;
    }
  4. 中断禁用的粒度限制

    所有自旋锁的中断禁用仅作用于本地 CPU,不影响其他 CPU 的中断响应,兼顾同步安全性和系统并发性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值