前言

本来想继续顺着数据包的处理流程分析upcall调用的,但是发现在分析upcall调用时必须先了解linux中内核和用户空间通信接口Netlink机制,所以就一直耽搁了对upcall的分析。如果对openVswitch有些了解的话,你会发现其实openVswitch是在linux系统上运行的,因为openVswitch中有很多的机制,模块等都是直接调用linux内核的。比如:现在要分析的RCU锁机制、upcall调用、以及一些结构体的定义都是直接从linux内核中获取的。所以如果你在查看源代码的一些结构(或者模块,机制性代码)时,发现在openVswitch中没有定义(我用的是Source Insight来查看和分析源码,可以很好的查看是否定义过),那么很可能就是openVswitch包含了linux头文件引用了linux内核的一些定义。

RCU是linux的新型锁机制(RCU是在linux 2.6内核版本中开始正式使用的),本来一直纠结要不要用篇blog来说下这个锁机制。因为在openVswitch中有很多的地方用到了RCU锁,我开始分析的时候都是用一种锁机制一笔带过(可以看下openVswitch(OVS)源代码分析之数据结构里面有很多地方都用到了RCU锁机制)。后来发现有很多地方还用到了该锁机制的链表插入和删除操作,而且后面分析的代码中也有RCU的出现,所以就稍微的说下这个锁机制的一些特性和操作。

RCU运行原理

我们先来回忆下读写锁(rwlock)运行机制,这样可以分析RCU的时候可以对照着分析。读写锁分为读锁(也称共享锁),写锁(也称排他锁,或者独占锁)。分情况来分析下读写锁:

第一、要操作的数据区被上了读锁;1、若请求是读数据时,上读锁,多个读锁不排斥(即,在访问数据的读者上线未达到时,可以对该数据区再上读锁);2、若请求是写数据,则不能马上上写锁,而是要等到数据区的所有锁(包括读锁和写锁)都释放掉后才能开始上写访问。

第二、要操作的数据区上了写锁;则不管是什么请求都必须等待数据区的写锁释放掉后才能上锁访问。

同理来分析下RCU锁机制: RCU是read copy udate的缩写,按照单词意思就知道这是一种针对数据的读、复制、修改的保护锁机制。锁机制原理:

第一、写数据的时候,不需要像读写锁那样等待所有锁的释放。而是会拷贝一份数据区的副本,然后在副本中修改,等待修改完后。用这个副本替换原来的数据区,替换的时候就要像读写锁中上写锁那样,等到原数据区上所有访问者都退出后,才进行数据的替换;根据这种特性可以推断出,用RCU锁可以有多个写者,拷贝了多份数据区数据,修改后各个写着陆续的替换掉原数据区内容。

第二、读数据的时候,不需要上任何锁,也几乎不需要什么等待(读写锁中如果数据区有写锁则要等待)就可以直接访问数据。为什么说几乎不需要等待呢?因为写数据中替换原数据时,只要修改个指针就可以,消耗的时间可以说几乎不算,所以说读数据不需要其他额外开销。

总结下RCU锁机制特性,允许多个读者和多个写者同时访问共享数据区的内容。而且这种锁对多读少写的数据来说是非常高效的,可以让CPU减少些额外的开销。如果写得操作多了的话,这种机制就没读写锁那么好了。因为RCU写数据开销还是很大的,要拷贝数据,然后还要修改,最后还要等待替换。其实这个机制就好比我们在一台共享服务器上放了个文件,有很多个人一起使用。如果你只是看看这个文件内容,那么直接在服务器上cat查看就可以。但如果你要修改该文件,那么你不能直接在服务器上修改,因为你这样操作会影响到将要看这个文件或者写这个文件的人。所以你只能先拷贝到自己本机上修改,当最后确认保证正确时,然后就替换掉服务器上的原数据。

RCU写者工作图示

下面看下RUC机制下修改数据(以链表为例)

根据上面的图会发现其实替换的时候只要修改下指针就可以,原数据区内容在被替换后,默认会被垃圾回收机制回收掉。

linux内核RCU机制API

了解了RCU的这些机制原理,下面来看下linux内核中常使用的一些和RCU锁有关的操作。注意,本blog并不会过多的去深究RCU最底层的实现机制,因为分享RCU工作机制的目的只是为了更好的了解openVswitch中使用到的那部分代码的理解,而不是为了分析linux内核源代码,不要本末倒置。如果遇到个知识点就拼命的深挖,那么你看一份源代码估计得几个月。

rcu_read_lock();看到这里有人可能会觉得和上面有矛盾,不是说好的读者不需要锁吗?其实这不是和上读写锁的那种上锁,这仅仅只是标识了临界区的开始位置。表明在临界区内不能阻塞和休眠,也不能让写者进行数据的替换(其实这功能远不止这些)。rcu _read_unlock()则是和上面rcu_read_lock()对应的,用来界定一个临界区(就是要用锁保护起来的数据区)。

synchronize_rcu();当该函数被一个CPU调用时(一般是有写者替换数据时调用),而其他的CPU都在RCU保护的临界区读数据,那么synchronize_rcu()将会保证阻塞写者,直到所有其它读数据的CPU都退出临界区时,才中止阻塞,让写着开始替换数据。该函数作用就是保证在替换数据前,所有读数据的CPU能够安全的退出临界区。同样,还有个call_rcu()函数功能也是类似的。如果call_rcu()被一个CPU调用,而其他的CPU都在RCU保护的临界区内读数据,相应的RCU回调的调用将被推迟到其他读临界区数据的CPU全部安全退出后才执行(可以看linux内核源文件的注释,在Rcupdate.h文件中rcu_read_look()函数前面的注释)。

rcu_dereference(); 获取在一个RCU保护的指针,指向RCU读端临界区。他的指针以后可能会被安全地解除引用。说到底就是一个RCU保护指针。

list_add_rcu();往RCU保护的数据结构中添加一个数据节点进去。这个和一般的往链表中增加一个节点操作是类似的,唯一不同的是多了这条代码:rcu_assign_pointer(prev->next, new); 代码大概含义:分配指向一个新初始化的结构指针,将由RCU读端临界区被解除引用,返回指定的值。(说实话我也不太懂这个注释是什么意思)大概的解释下:就是让插入点的前一个节点的next指向新增加的new节点,为什么要单独用一条这个语句来实现,而不是用 prev->next = new;直接实现呢?这是因为prev->next本来是指向其他值得,有可能有CPU通过prev->next去访问其他RCU保护的数据了,所以如果你要插入一个RCU保护的数据结构中必要要调用这个语句,它里面会帮你处理好一些细节(比如有其他CPU使用后面的数据,直接使用prev->next可能会使读数据的CPU断开,产生问题),并且让刚加入的新节点也受到RCU的保护。这类的插入有很多,比如从头部插入,从尾 部插入等,实现都差不多,这里不一一细讲。

list_for_each_entry_rcu();这是个遍历RCU链表的操作,和一般的链表遍历差不多。不同点就是必须要进入RCU保护的CPU(即:调用了rcu_read_lock()函数的CPU)才能调用这个操作,可以和其他CPU共同遍历这个RCU链表。以此相同的还有其他变相的遍历及哈希链表的遍历,不细讲。

如果在openVswitch源代码分析中发现了有关RCU的分析和这里的矛盾,可以以这里为准,当然我也会校对下。

转载请注明作者和原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/40115559
若有不正确之处,望大家指正,共同学习!谢谢!!!

openVswitch(OVS)源代码之linux RCU锁机制分析相关推荐

  1. 带你一文解析RCU锁机制原理

    原理 Read Copy Update 读(Read):读者不需要获得任何锁就可访问RCU保护的临界区: 拷贝(Copy):写者在访问临界区时,写者"自己"将先拷贝一个临界区副本, ...

  2. MySQL事务分析和锁机制分析

    MySQL事务分析和锁机制分析 事务 事务控制语句 目的 组成 特征 概念 redo日志 undo日志 MVCC多版本并发控制Multi version concurrency control ACI ...

  3. OB锁机制分析和测试

    OB锁机制分析 OB锁机制:https://www.oceanbase.com/docs/community/observer-cn/V3.1.3/0000000000161645 ob的锁是行级锁, ...

  4. linux内核锁机制学习

    在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问.尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上 ...

  5. RCU锁机制原理解析

    背景 为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了广泛的使用.但是 ...

  6. [转载] 数据库分析手记 —— InnoDB锁机制分析

    作者:倪煜 InnoDB锁机制常常困扰大家,不同的条件下往往表现出不同的锁竞争,在实际工作中经常要分析各种锁超时.死锁的问题.本文通过不同条件下的实验,利用InnoDB系统给出的各种信息,分析了锁的工 ...

  7. 【Hive】Hive锁机制分析及任务问题处理

    1.背景 在数据仓库开发中,遇到了读取数据任务导致锁表问题,发现是因为补数据或月度大任务跨天运行,此时凌晨定时的写入操作就会被阻塞进入等待状态(如果超过最大等待时间会失败),直到读取任务完成写入任务才 ...

  8. oracle 分析锁,ORACLE锁机制分析

    Oracle 多粒度锁机制介绍 根据保护对象的不同,Oracle数据库锁可以分为以下几大类: (1) DML lock(data locks,数据锁):用于保护数据的完整性: (2) DDL lock ...

  9. Linux RCU锁简析

    最近遇到一个问题,大压力测试下咬狗了,定位出来跟RCU相关,还是先简单的捋一捋RCU,也好看看后面能否对RCU做些特定场景下的优化. 网上RCU相关的技术博客比较多,先列几个可供参考的: MagicB ...

最新文章

  1. 无需标注数据集,自监督注意力机制就能搞定目标跟踪
  2. 公众科学日|科普图书展,图灵参展啦!
  3. 21天养成习惯?不一定
  4. char,TCHAR,WCHAR区别
  5. 大型网站演化发展历程
  6. win32 输出文字时清除之前的_努力学习没效果?3个步骤,强化沟通输出,实现飞跃式成长...
  7. yunos5 linux内核,魅蓝5S、魅蓝5对比看差异 选Android还是YunOS?
  8. 只有单杀技能的飞鸽传书
  9. php导入跟引入的区别,PHP7 引入的“??” 和“?:”的区别
  10. linux下tmux
  11. c++ 在函数中传递数组和sizeof用法注意事项
  12. Win10配置Tensorflow_Object_Detection_API
  13. java fileinputstream 安全管理器校验失败_Spring Boot 如何做参数校验?
  14. linux 分析系统配置,在Linux系统上部署AWStats日志分析系统
  15. shell中的特殊符号
  16. 逆向基础 OS-specific (四)
  17. win10系统C盘出现感叹号及加密图标解除
  18. 万字+图片解析计算机网络应用层
  19. 减法公式运算法则_加减乘除运算法则
  20. 命令行把java项目打成jar包

热门文章

  1. 国家标准规范、行业标准规范,规范提取,自动提取软件
  2. Geography V.S. Geometry
  3. java中带参数的try(){}语法含义
  4. opencv——角点检测
  5. /lib和/usr/lib的区别、/lib64与/usr/lib64的区别
  6. 李广之死――浅析项目管理
  7. [机缘参悟-65]:《兵者,诡道也》-6-三十六计解读-并战计
  8. No value specified for parameter 15排查过程
  9. 糖尿病视网膜病变检测 (Diabetic Retinopathy Detection)
  10. python爬虫网易云_Python爬虫网易云音乐Top50热门歌单