加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 运营中心 > 交互 > 正文

深入理解RCU实现

发布时间:2016-10-29 16:06:37 所属栏目:交互 来源:站长网
导读:副标题#e# 深入理解RCU实现 ——基于 内核2.6.21 RCU实现(lvyilong316) RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构, 读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝一个副本,然

static void __cpuinit rcu_online_cpu(int cpu) 

    struct rcu_data *rdp = &per_cpu(rcu_data, cpu); 
    struct rcu_data *bh_rdp = &per_cpu(rcu_bh_data, cpu); 


    rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp); 
    rcu_init_percpu_data(cpu, &rcu_bh_ctrlblk, bh_rdp); 
    open_softirq(RCU_SOFTIRQ, rcu_process_callbacks, NULL); 

    这个函数主要完成两个操作:初始化两个per cpu变量;注册RCU_SOFTIRQ软中断处理函数rcu_process_callbacks。我们从这里又看到了另一个per cpu变量:rcu_bh_data.有关bh的部份之后再来分析.在这里略过这些部分。 下面看下rcu_init_percpu_data()的实现。

rcu_init_percpu_data

static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, struct rcu_data *rdp) 

    memset(rdp, 0, sizeof(*rdp)); 
    rdp->curtail = &rdp->curlist; 
    rdp->nxttail = &rdp->nxtlist; 
    rdp->donetail = &rdp->donelist; 
    rdp->quiescbatch = rcp->completed; 
    rdp->qs_pending = 0; 
    rdp->cpu = cpu; 
    rdp->blimit = blimit; 

    调用这个函数的第二个参数是一个全局变量rcu_ctlblk。 在继续向下分析之前我们先看下这些函数用到的一些重要数据结构。

重要数据结构

    说明:下列数据结构只列出了主要成员。

struct rcu_ctrlblk {  

    long cur;  

    long completed;  

    cpumask_t  cpumask;   

};  

struct rcu_ctrlblk的主要作用就是定义上节提到的全局变量rcu_ctlblk,这个变量在系统中是唯一的。另外说明一下,为了记录方便,内核将从启动开始的每个grace period对应一个数字表示。

这里的cpumask是为了标识当前系统中的所有cpu,以便标记哪些cpu发生过上下文切换(经历过一个quiescent state)。而cur,completed,则用来同步。我们可以这样理解,cur和completed是系统级别的记录信息,也即系统实时经历的grace编号,一般情况下,新开一个graceperiod等待周期的话,cur会加1,当graceperiod结束后,会将completed置为cur,所以通常情况下,都是completed追着cur跑。那么我们可能会猜测,是不是如果complete= curr -1 的时候,就表示系统中graceperiod还没有结束?当completed= curr的时候,就表示系统中不存在graceperiod等待周期了?我们姑且这么理解,实际上有些许差别,但设计思想都是一样的。

struct rcu_data {  

    long quiescbatch;       

    int passed_quiesc;  

    long            batch;           

    struct rcu_head *nxtlist;  

    struct rcu_head **nxttail;  

    struct rcu_head *curlist;  

    struct rcu_head **curtail;  

    struct rcu_head *donelist;  

    struct rcu_head **donetail;  

};  

    上面的结构,要达到的作用是,跟踪单个CPU上的RCU事务。 

(1) passed_quiesc:这是一个flag标志,表示当前cpu是否已经发生过抢占了(经历过一个quiescent state),0表示为未发送过切换,1表示发生过切换;

说明:我们一直强调发生过一次cpu抢占就是经历过一个quiescent state,其实这是不严格的说法。为什么呢?因为自系统启动,各种进程频繁调度,肯定每个cpu都会发生过抢占。所以我们这里说的“发生过抢占”是指从某个特殊的时间点开始发生过抢占。那么这个特殊的时间点是什么时候呢?就是我们调用synchronize_rcu将rcu_head挂在每cpu变量上并挂起进程时,我们后面分析就会证实这一点。

(2) batch:表示一个grace periodid,表示本次被阻塞的写者,需要在哪个graceperiod之后被激活;

(3) quiescbatch:表示一个grace periodid,用来比较当前cpu是否处于等待进程切换完成。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读