首页 > 编程语言 >深入理解并行编程-读书笔记 rcu

深入理解并行编程-读书笔记 rcu

时间:2024-03-21 17:46:16浏览次数:18  
标签:读取 读书笔记 RCU 编程 链表 线程 rcu 节点

 

在当前的Linux内核中发挥着重要的作用。RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用RCU机制读取数据的时候不对链表进行耗时的加锁操作。这样在同一时间可以有多个线程同时读取该链表,并且允许一个线程对链表进行修改(修改的时候,需要加锁)。RCU适用于需要频繁的读取数据,而相应修改数据并不多的情景,例如在文件系统中,经常需要查找定位目录,而对目录的修改相对来说并不多,这就是RCU发挥作用的最佳场景。

RCU(Read-Copy Update),是 Linux 中比较重要的一种同步机制。顾名思义就是“读,拷贝更新”,再直白点是“随意读,但更新数据的时候,需要先复制一份副本,在副本上完成修改,再一次性地替换旧数据”。这是 Linux 内核实现的一种针对“读多写少”的共享数据的同步机制。

RCU机制解决了什么

在RCU的实现过程中,我们主要解决以下问题:

1、在读取过程中,另外一个线程删除了一个节点。删除线程可以把这个节点从链表中移除,但它不能直接销毁这个节点,必须等到所有的读取线程读取完成以后,才进行销毁操作。RCU中把这个过程称为宽限期(Grace period)。

2、在读取过程中,另外一个线程插入了一个新节点,而读线程读到了这个节点,那么需要保证读到的这个节点是完整的。这里涉及到了发布-订阅机制(Publish-Subscribe Mechanism)。

3、保证读取链表的完整性。新增或者删除一个节点,不至于导致遍历一个链表从中间断开。但是RCU并不保证一定能读到新增的节点或者不读到要被删除的节点。

RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝一个副本,然后对副本进行修改,最后使用一个回调(callback)机制在适当的时机把指向原来数据的指针重新指向新的被修改的数据。那么这个“适当的时机”是怎么确定的呢?这是由内核确定的,也是我们后面讨论的重点。

 

 

 

 

 

 

 

编写一个需要访问随时变化的数据的并行实时程序的问题

读-复制-更新(RCU)是一种同步机制

RCU允许读操作可以与更新操作并发执行,这一点提升了程序的可 扩展性。常规的互斥锁让并发线程互斥执行,并不关心该线程是读者 还是写者,而读/写锁在没有写者时允许并发的读者,相比于这些常规 锁操作,RCU在维护对象的多个版本时确保读操作保持一致,同时保证 只有所有当前读端临界区都执行完毕后才释放对象。RCU定义并使用了 高效并且易于扩展的机制,用来发布和读取对象的新版本,还用于延 后旧版本对象的垃圾收集工作。这些机制恰当地在读端和更新端分布 工作,让读端非常快速。在某些场合下(比如非抢占式内核里),RCU 读端的函数完全是零开销。

不幸的是,这块代码无法保证编译器和CPU会按照顺序执行最后4 条赋值语句。如果对gp的赋值发生在初始化p的各字段之前,那么并发 的读者会读到未初始化的值。这里需要内存屏障来保证事情按顺序发 生,可是内存屏障又向来以难用而闻名。所以这里我们用一句 rcu_assign_pointer()原语将内存屏障封装起来,让其拥有发布的 语义。最后4行代码如下。

p->a = 1;

rcu_assign_pointer(gp , p);

 

 

本节由一系列小问题组成,让你可以尝试运用本书之前提到的各 种RCU例子。每个小问题的答案都会给出一些提示,后续章节会给出详 细 的 解 决 办 法 。 rcu_read_lock ( ) 、 rcu_read_unlock ( ) 、 rcu_dereference ( ) 、 rcu_assign_pointer ( ) 和 synchronize_rcu()原语足以应付这些练习了。 小问题9.76:图5.9(count_end.c)中实现的统计计数用一把全 局锁来保护read_count()中的累加过程,这对性能和可扩展性影响 很大。该如何用RCU改造read_count(),让其拥有良好的性能和极佳 的可扩展性呢?(请注意,read_count()的可扩展性受到统计计数 需要扫描所有线程计数的限制。) 小问题9.77:5.5节给出了一段奇怪的代码,用于统计在可移除设 备上发生的I/O访问次数。这段代码的快速路径(启动一次I/O)开销 较大,因为需要获取一把读/写锁。该如何用RCU来改造这个例子,让 其拥有良好的性能和极佳的可扩展性呢?(请注意,一般情况下,I/O 访问代码的性能要比设备移除代码的性能重要。)

 

标签:读取,读书笔记,RCU,编程,链表,线程,rcu,节点
From: https://www.cnblogs.com/ycjstudy/p/18087810

相关文章

  • 解决[TSP旅行商]问题,请列出[4]个可以用[Python]编程的优化路径算法,展开写出这[4]个算
    TSP(旅行商问题)是一个经典的组合优化问题,其目标是找到访问所有城市并返回起点的最短可能路线。在Python中,有多种算法可以用来解决TSP问题,以下是四个常用的算法及其编程难度级别、时间复杂度和所需的库:回溯法(Backtracking)编程难度级别:中等时间复杂度:指数级,因为需要遍历所有......
  • 多线程并发聊天室简单实现代码详解 -- 涉及网络编程,多线程和线程同步的知识
            本项目主要完成多线程并发聊天室的基础功能,即多个客户端之间通过服务器可以实现群发消息,重点在于学习网络编程,多线程和线程同步的基础知识(基于Linux)。    下面我会详解每一部分的代码。1.主线程        1.1首先由于是自己在电脑里面测试,......
  • Linux应用编程和网络编程
    一、Linux中的文件IO..11.1应用编程框架介绍..11.1.1.什么是应用编程..11.1.2.课程思路..11.1.3.什么是文件IO..11.2文件操作的主要接口API11.2.1.什么是操作系统API11.2.2.文件操作的一般步骤..11.2.3.重要概念:文件描述符..21.3一个简单的文件读写实例........
  • 深入理解并行编程-学习笔记
    一简介1并行编程的目标并行编程(在单线程编程的目标之上)有如下三个主要目标。1.性能。2.生产率。3.通用性。线程优化:性能与扩展通用:需要牢记的是,并行编程只是提高性能的方案之一。其他熟知的方案按实现难度递增的顺序罗列如下。1.运行多个串行应用实例。2.利用现有的......
  • 颠覆传统编程:Codigger极致体验之旅
    在数字化浪潮汹涌的当下,编程已成为推动科技发展的重要引擎。而在这其中,极致编程体验无疑是每位开发者所追求的目标。它不仅代表着工具的高效能与稳定性,更映射出开发者在编程世界中的自由与创造力。Codigger,以其领先的开发框架和卓越的设计理念,正为开发者们带来前所未有的极致编......
  • Java基础内容:第七章面向对象(下)编程题详解
            建了一个群:908722740 ,欢迎小伙伴门的加入,平时可以互相学习交流,不管是学习还是工作上的都可以多多交流,本人在校学生,技术有限,错误的地方欢迎指正。目录一、多态案例素材【1】乐手弹奏乐器【2】比萨制作【3】购买饮料二、接口案例素材【1】兔子和青蛙【......
  • Java 面向对象编程进阶四(多态、抽象方法抽象类)
    目录多态(polymorphism)多态和类型转换对象的转型(casting) 类型转换异常向下转型中使用instanceof final关键字抽象方法和抽象类抽象类和抽象方法的基本用法多态(polymorphism)        多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实......
  • 编程设计模式-责任链设计模式
    责任链设计模式概述:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。责任链模式的主要角色如下:抽象处理者(Handler)角色:定义一个处理请求的接口,包含......
  • Java 面向对象编程进阶六(内部类 )
    目录内部类内部类的概念内部类的分类1、非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)2、静态内部类3、匿名内部类4、局部内部类内部类        内部类是一类特殊的类,指的是定义在一个类的内部的类。实际开发中,为了方便的使用外部类的相......
  • Java 面向对象编程进阶七(字符串 String )
    目录字符串StringString基础String类和常量池String类常用的方法String类常用方法一String类常用方法二字符串相等的判断字符串String        String是我们开发中最常用的类,我们不仅要掌握String类常见的方法,对于String的底层实现也需要掌握好......