读写更新
RCU 是一种可以管理多个进程执行的方法,可以部署到任何操作系统,其中之一是 Linux 内核。它是一种简单的进程同步方法,它将 RCU 更新分成两个阶段:删除和回收。这种机制允许读取和更新同时发生。该过程在操作系统的许多读取器和更新器之间并发发生。除了简单的过程之外,它对于同时进程的访问也可靠。
读写更新
定义
读写更新 (RCU) 是一种最佳的数据结构,它遵循并发进程同步,在多线程并发运行以读取和更新共享资源(如内存、设备或文件)时,限制了互斥量或锁的使用。
读写更新 (RCU) 的阶段
更新分为两个阶段,即:
删除
回收
在不使用 RCU 的情况下,离开或删除线程必须锁定元素,以便任何其他元素都无法访问它。但是,使用 RCU,删除阶段用于引用元素,并且可以轻松删除而不会影响遍历列表。在删除阶段从列表中删除对元素的引用后,线程必须等待所有先前的读取器完成其 RCU 读取端关键部分,然后才能继续执行回收阶段。
读/写端代码
数据结构分为读和写操作。读取端是并发类型,不会更改数据结构模型,而写入端会更改数据结构。RCU 使用进程同步来避免读取器和写入器端之间的漏洞。
只有当读取端并发代码使用与非同步代码类似的内存时,才能像后者一样快速运行。因为原子写入速度慢且会锁定内存总线,所以读取端代码不能写入共享数据结构。从本质上讲,共享数据结构中每个共享缓存行上的写入都会导致共享行从其他处理器的缓存中删除。
此逐出后,其他处理器的缓存将需要重新加载数据,这将至少需要数百个周期。缓存行弹跳是缓存行所有权在内核之间交替的问题。读取端程序无法使用其他昂贵的指令,例如内存屏障。
这些条件从本质上排除了读写锁作为选项。读取端操作必须对共享数据结构执行原子写入,在最简单的读写锁中,这些锁跟踪并发读取器的数量。
RCU 操作
在传统方法中,读取器使用锁来阻止更新删除数据项。目前,RCU 读取器可以通过等待所有读取器完成来使用更轻量级的同步,甚至根本不使用同步。
应用程序编程接口 -
下面给出了一些 RCU API:
rcu_read_lock − 它标记 RCU 保护的数据结构,在整个时间内都不能恢复,并且是关键部分的初始操作。
rcu_read_unlock − 读取器使用此函数通知它已离开关键部分。
Synchronize_rcu() − Synchronize_rcu() 函数由读取器使用,该读取器等待关键部分的读取端退出进程,并且不会立即返回。
Call_rcu − 它是一个在所有活动的 RCU 读取端关键部分完成后调用 synchronize_rcu 的函数,而不是阻塞。当禁止阻塞或更新端效率至关重要时,此回调类型特别有用。
Call_rcu − 此函数更关注安全地通知读取器更新的值。它还负责记录有关受 RCU 保护的指针的数据。
rcu_dereference − 此函数专门用于获取有关由 RCU 保护的指针的信息。在关键部分中的线程期间,这些函数仅在此函数内参与。
RCU 的实现
RCU 可以通过两种不同的方式在 Linux 操作系统中实现。其中一种是使用锁定方法,另一种是 RCU 的经典方法。
尽管锁定方法很容易,但它不能在实时使用中实现,因为它在两个读取端关键部分之间切换。在 RCU 的经典方法中,它显示更新的性能较低。
读写更新的缺点
读写更新的主要缺点是抢占,因为它不能在用户模式下使用。这些读写更新不能被树数据结构使用,因为它可能依赖于许多无法自动完成的更新。
结论
RCU 机制是一种可以在任何操作系统中使用以避免锁定方法的机制。RCU 读取从锁定函数开始,在解锁函数中结束。RCU 遵循的基本算法是进行更改,等待现有的 RCU 读取端关键部分结束,最后清理过程。