首页 > 试题广场 >

Linux内核中,在自旋锁的基础上还衍生出了其他特定场合使用

[单选题]
Linux内核中,在自旋锁的基础上还衍生出了其他特定场合使用的锁,关于这些锁的描述,错误的是()
  • 读写自旋锁一次只能允许一个写操作。
  • 读写自旋锁当没有写操作的时候允许一个或多个线程持有读锁。
  • 使用顺序锁的可以允许在写的时候进行读操作。
  • 顺序锁可以保护任意数据类型,包括指针指向的复杂数据结构
顺序锁为什么不能保护指针类型数据

顺序锁(seqlock)不能安全地保护指针类型数据,主要是因为它的读者是无锁读取的,无法保证在读取过程中指针指向的内容不会被写者修改或释放,从而导致野指针、数据不一致或崩溃

🧠 顺序锁的工作机制回顾

顺序锁是一种乐观锁,适用于“读多写少”的场景:

  • 写者加锁并更新版本号(通常是一个整数)。

  • 读者不加锁,读取数据前后检查版本号是否一致。

  • 如果版本号在读前后不一致,说明有写入发生,读者需要重试。

⚠️ 为什么不能保护指针类型数据?

1. 读者无锁访问,无法阻止写者释放指针指向的内存

  • 写者可能在更新过程中释放或替换指针指向的结构体。

  • 读者在无锁状态下访问该指针,可能访问已释放或未初始化的内存。

2. 指针指向的数据可能是多字段结构体

  • 即使版本号一致,读者可能读取到部分更新前、部分更新后的字段,导致数据不一致。

3. 无法保证指针指向的数据的原子性

  • 顺序锁只能保证版本号一致性,不能保证指针指向的数据在读者读取过程中不被修改。

📉 示例:错误使用顺序锁保护指针

c
struct my_data {
    int a;
    int b;
};

struct my_data *shared_ptr;
seqlock_t my_seqlock;

reader() {
    unsigned seq;
    struct my_data *local;

    do {
        seq = read_seqbegin(&my_seqlock);
        local = shared_ptr;          // 读指针
        int a = local->a;            // 访问指针内容
        int b = local->b;
    } while (read_seqretry(&my_seqlock, seq));
}

如果shared_ptr在写者中被替换或释放,读者可能访问非法内存,导致崩溃。

✅ 正确做法

  • 顺序锁适合保护标量数据(如整数、时间戳、计数器等)。

  • 若要保护指针类型数据,应使用:

    • RCU(Read-Copy-Update):适合保护指针和复杂结构体,读者无锁访问,写者延迟释放。

    • 读写锁(rwlock):读者加共享锁,写者加独占锁,确保一致性。

🧩 总结

特性 顺序锁 RCU / 读写锁
是否适合保护指针 ❌ 不适合 ✅ 适合
读者是否加锁 ❌ 无锁读取 RCU:无锁;rwlock:加锁
是否能防止释放指针内存 ❌ 无法防止 ✅ RCU 延迟释放或加锁保护
推荐使用场景 标量数据,高读低写 指针数据、复杂结构体

如果你正在设计内核模块或驱动,我可以帮你判断是否该用顺序锁、RCU 或其他同步机制,并给出代码模板!

发表于 2025-10-21 22:31:44 回复(0)