zoukankan      html  css  js  c++  java
  • linux下数据同步、回写机制分析

    一、前言
    在linux2.6.32之前,linux下数据同步是基于pdflush线程机制来实现的,在linux2.6.32以上的版本,内核彻底删掉了pdflush机制,改为了基于per-bdi线程来实现数据同步,与pdflush线程相比,在per-bdi线程机制中,每个后备存储器拥有自己唯一的回写线程,数据同步时需要更少的线程、也不会有多个pdflush对同一个后备存储器进行回写的竞态问题,回写的效率更高。

    二、初始化默认的后备存储器default_backing_dev_info

    static int __init default_bdi_init(void)
    {
        int err;
    
        /*创建同步每个后备存储器的超级块的线程*/
        sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers");
        BUG_ON(IS_ERR(sync_supers_tsk));
    
      /*初始化一个定时器,该定时器控制同步超级块的周期,每隔dirty_writeback_interval去唤醒一次sync_supers_tsk,从而同步超级块。
        dirty_writeback_interval可以通过修改/proc/sys/vm/下的dirty_writeback_centisecs来修改,默认值是500,单位是10ms
        定时器函数sync_supers_timer_fn用于唤醒同步超级块的线程sync_supers_tsk,并且更新定时器的到期时间,具体实现如下*/
        setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0);
        /*用于更新定时器的到期时间,详见下面代码。*/
        bdi_arm_supers_timer();
    
        /*初始化default_backing_dev_info的成员变量,初始化相关的链表,相关的变量赋初值等操作,请读者自行阅读。*/
        err = bdi_init(&default_backing_dev_info);
        if (!err)
          /*调用bdi_register注册默认的后备存储器default_backing_dev_info到bdi_list链表,并创建默认的backing_dev_info管理线程,
            用于管理其他的后备存储器的数据同步线程的创建和销毁,所有的后备存储器在初始化时都会调用bdi_register注册到bdi_list链表中。
            bdi_register详见下文分析。*/
            bdi_register(&default_backing_dev_info, NULL, "default");
    
        /*初始化空的后备存储器,可以忽略。*/
        err = bdi_init(&noop_backing_dev_info);
    
        return err;
    }
    void bdi_arm_supers_timer(void)
    {
        unsigned long next;
    
        if (!dirty_writeback_interval)
            return;
    
        next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies;
        mod_timer(&sync_supers_timer, round_jiffies_up(next));
    }
    static void sync_supers_timer_fn(unsigned long unused)
    {
        wake_up_process(sync_supers_tsk);
        bdi_arm_supers_timer();
    }
    bdi_arm_supers_timer函数重设定时器

    void bdi_arm_supers_timer(void)
    {
        unsigned long next;
    
        if (!dirty_writeback_interval)
            return;
    
        next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies;
        mod_timer(&sync_supers_timer, round_jiffies_up(next));
    }
    三、bdi_register()函数分析
    bdi_register函数用于注册后备存储器到全局链表bdi_list上,并且判断如果是默认的后备存储器default_backing_dev_info则创建bdi-default线程,用于管理创建或销毁所有后备存储器相关的同步回写线程

    int bdi_register(struct backing_dev_info *bdi, struct device *parent,
            const char *fmt, ...)
    {
        va_list args;
        struct device *dev;
    
        if (bdi->dev)    /* The driver needs to use separate queues per device */
            return 0;
    
        va_start(args, fmt);
        dev = device_create_vargs(bdi_class, parent, MKDEV(0, 0), bdi, fmt, args);
        va_end(args);
        if (IS_ERR(dev))
            return PTR_ERR(dev);
    
        bdi->dev = dev;
    
        /*
         * Just start the forker thread for our default backing_dev_info,
         * and add other bdi's to the list. They will get a thread created
         * on-demand when they need it.
         */
        if (bdi_cap_flush_forker(bdi)) {
            struct bdi_writeback *wb = &bdi->wb;
    
            wb->task = kthread_run(bdi_forker_thread, wb, "bdi-%s",
                            dev_name(dev));
            if (IS_ERR(wb->task))
                return PTR_ERR(wb->task);
        }
    
        bdi_debug_register(bdi, dev_name(dev));
        set_bit(BDI_registered, &bdi->state);
    
        spin_lock_bh(&bdi_lock);
        list_add_tail_rcu(&bdi->bdi_list, &bdi_list);
        spin_unlock_bh(&bdi_lock);
    
        trace_writeback_bdi_register(bdi);
        return 0;
    }

    from:http://sunjiangang.blog.chinaunix.net/uid-9543173-id-3568434.html

  • 相关阅读:
    git或gitee 提交代码到远程仓库
    gitee 创建代码仓库,并提交本地代码
    Logback 实现日志链路追踪
    navicat 查看,设计并导出数据库 ER图
    Jackson 使用 @JsonFormat 注解进行时间格式化
    Redis 缓存常见问题
    jedis 与 redission 实现分布式锁
    Redis 集群模式搭建
    Redis 哨兵模式高可用
    Notepad++ 正则表达式提取信息
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332307.html
Copyright © 2011-2022 走看看