内核同步机制 - 读写锁 read_lock()/write_lock

本文详细探讨了内核同步机制中的读写锁,包括其变量初始化、工作原理、底层实现以及操作方法。同时对比了读写锁与RCU锁的区别和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  
读写锁的基本原理类似自旋锁,它区分读取和写入场景,允许多个读线程同时访问共享数据,而保持读-写和写-写互斥,适用频繁读取数据,而修改相对较少的场景;

1. 读写锁变量

内核使用rwlock_t表示读写锁变量,raw_lock成员是架构相关的,其它成员用于锁调试和死锁检查等:
typedef struct {
    arch_rwlock_t raw_lock;
#ifdef CONFIG_GENERIC_LOCKBREAK
    unsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
    unsigned int magic, owner_cpu;
    void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lockdep_map dep_map;
#endif
} rwlock_t;

raw_lock成员和架构相关,以arm为例,lock成员是一个无符号整形变量:
typedef struct {
    volatile unsigned int lock;
} arch_rwlock_t;

注意:使用volatile类型声明lock变量,目的在于消除编译器优化,优化器在用到这个变量时必须每次都小心的重新读取这个变量的值,而不是使用保存在寄存器里的备份;

2. 初始化读写锁

使用DEFINE_RWLOCK宏来初始化读写锁,锁变量的初值是
<think>我们正在讨论RCU(Read-Copy-Update)机制,它是一种用于同步的机制,特别适用于读多写少的场景。根据引用[^1],RCU被描述为一种改进的读写锁(rwlock),它几乎消除了读者的同步开销。读者不需要获取锁,不使用原子指令,因此不会导致锁竞争、内存延迟和流水线停滞。同时,由于读者不需要锁,也避免了死锁问题。 引用[^2]展示了一个RCU同步函数`synchronize_rcu`的实现,它调用了`synchronize_sched`,然后根据情况选择等待一个宽限期(graceperiod)或者使用加速版本的同步。这个宽限期是RCU机制中的关键概念,它确保所有在更新开始之前已经开始的读操作完成之后,才释放旧数据。 引用[^3]提到了在Linux内核初始化过程中,在调度器初始化之后会进行RCU的初始化(`rcu_init`)。现在,我将详细解释RCU的读写锁使用和机制。###RCU机制概述RCU的核心思想是:在更新共享数据时,先创建数据的副本,修改副本,然后在适当的时机用修改后的副本替换原数据。这个“适当的时机”就是当所有正在使用旧数据的读者都完成之后(即宽限期结束)。这样,读者可以无锁地访问数据,而写者则需要等待宽限期结束才能释放旧数据。 ###读者操作读者在访问共享数据时,只需要在读取数据前后分别加上`rcu_read_lock()`和`rcu_read_unlock()`(或者使用其他等效的RCU原语,如`rcu_read_lock_bh`等)。注意,这两个函数并不实际加锁,它们主要是禁止和重新启用内核抢占,并标记进入和退出RCU读端临界区。读者在临界区内可以安全地访问共享数据,因为写者会等待所有在更新开始前进入临界区的读者离开临界区后才释放旧数据。 ###写者操作写者需要执行以下步骤: 1.分配新内存,复制要更新的数据。 2.修改新数据。3.用新数据替换旧数据(通常是通过原子指针替换)。 4.等待宽限期结束(通过`synchronize_rcu()`或类似的函数),以确保所有可能持有旧数据引用的读者都已经退出临界区。5.释放旧数据。 ###宽限期(Grace Period) 宽限期是RCU机制中一个关键概念。它是指从更新操作(替换指针)开始,到所有在更新操作之前已经开始的读操作都结束为止的时间段。写者必须等待宽限期结束后才能释放旧数据,以确保没有读者还在使用旧数据。###示例代码以下是一个简化的RCU使用示例(注意:实际内核代码中会使用更复杂的结构,但原理相同):```c//读者rcu_read_lock();struct data*d= rcu_dereference(global_ptr);//使用d进行读取操作rcu_read_unlock(); //写者struct data*new_ptr =kmalloc(sizeof(*new_ptr), GFP_KERNEL);//初始化new_ptr,复制数据并修改rcu_assign_pointer(global_ptr, new_ptr);//替换全局指针synchronize_rcu(); //等待宽限期结束kfree(old_ptr); //释放旧数据```###机制分析-**读者开销小**:因为读者不需要锁,也不使用原子操作,所以读操作非常高效。 -**写者开销较大**:写者需要复制数据、等待宽限期,并且可能阻塞。因此,RCU适用于读多写少的场景。- **内存回收延迟**:旧数据不会立即释放,而是等待宽限期结束后才释放,这可能导致内存占用增加。 -**无死锁**:由于读者不会阻塞写者,写者也不会阻塞读者(写者只阻塞在等待宽限期),所以不会出现死锁。###相关问题1.RCU中的宽限期是如何确定的?它如何知道所有读者已经离开临界区? 2.在哪些场景下RCU比传统的读写锁更有优势?3.RCU机制在内核中除了同步之外还有哪些应用?</think>### RCU读写锁机制详解 RCU(Read-Copy-Update)是Linux内核中一种高效的同步机制,特别适用于**读多写少**的场景。其核心思想是通过**延迟回收旧数据**来实现无锁读取,大幅降低读者开销。 #### 一、核心机制 1. **读者操作** - 无需获取锁,直接访问共享数据 - 使用`rcu_read_lock()`/`rcu_read_unlock()`标记临界区 - 示例代码: ```c rcu_read_lock(); struct data *d = rcu_dereference(ptr); // 安全获取指针 /* 读取数据操作 */ rcu_read_unlock(); ``` **开销**:仅需禁用内核抢占(非原子操作),无锁竞争[^1] 2. **写者操作** - 分三步完成更新: ```c // 1. 创建新副本 struct data *new = kmalloc(...); memcpy(new, old, ...); new->value = updated_value; // 2. 原子替换指针 rcu_assign_pointer(ptr, new); // 发布新数据 // 3. 延迟回收旧数据 synchronize_rcu(); // 等待宽限期结束 kfree(old); // 安全释放旧数据 ``` - 关键函数`synchronize_rcu()`会阻塞直到**所有现存的读临界区退出**[^2] #### 二、关键设计 1. **宽限期(Grace Period)** - 定义:从指针更新到所有旧读者退出的时间段 - 实现原理: - 内核维护所有CPU的**静止状态(Quiescent State)** - 当所有CPU至少经历一次上下文切换时,宽限期结束[^3] - 等待机制: ```c void synchronize_sched(void) { if (rcu_blocking_is_gp()) return; wait_rcu_gp(call_rcu_sched); // 核心等待函数[^2] } ``` 2. **无锁读取优势** | 特性 | 传统读写锁 | RCU | |------------|------------|-----------| | 读者开销 | 原子操作 | 零原子操作| | 内存屏障 | 需要 | 仅写者需要| | 死锁风险 | 存在 | 无 | | 适用场景 | 均衡读写 | 读密集型 | #### 三、典型应用场景 1. **内核数据结构** - 路由表、进程描述符等频繁读取的结构 2. **网络协议栈** - 连接状态表的快速查询 3. **文件系统** - VFS dentry缓存等高频读取对象 #### 四、使用注意事项 1. **读者限制** - 临界区内不能休眠 - 必须使用`rcu_dereference()`访问指针 2. **写者开销** - 内存复制成本(需权衡更新频率) - 宽限期等待可能阻塞(毫秒级) > **设计哲学**:通过空间换时间(数据副本)和延迟回收(宽限期),实现读操作零锁竞争[^1]。 ### 相关问题 1. RCU中的宽限期检测如何在内核中具体实现? 2. 在哪些场景下RCU比传统的读写锁性能更差? 3. RCU机制如何处理嵌套读取的情况? 4. 如何验证RCU保护的数据访问的正确性?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值