• Linux内核系列之Block块层(一)


    .Block块层入口函数为 genhd_device_init(),先对该函数开始分析:

    函数实现源码:

    static int __init genhd_device_init(void)
    {
        bdev_map = kobj_map_init(base_probe, &block_subsys_lock);
        blk_dev_init();
        subsystem_register(&block_subsys);
        return 0;
    }

     

    .kobj_map_init

    相关结构定义:

    struct kobj_map {
        struct probe {
            struct probe *next;
            dev_t dev;
            unsigned long range;
            struct module *owner;
            kobj_probe_t *get;
            int (*lock)(dev_t, void *);
            void *data;
        } *probes[255];
        struct mutex *lock;
    };

    作用: 申请一个struct kobj_map结构对象并完成初始化,这里的成员probes为一个散列表,而表的索引0~254对应主设备号的索引,每个散列表元素又对应一个已注册的主设备号和此设备号(即对应的设备);

    初始化过程:申请struct probe结构对象base并将get成员赋值为参数base_probe,然后依次赋值给kobj_map对象成员的probes数组赋值为base(255个相同值);

    static struct kobject *base_probe(dev_t dev, int *part, void *data)

    base_probe函数说明:获取拥有该设备号的范围,查看源代码该方法的其实什么也没做只返回了一个null,当该方法的真正意义在意定义一种格式以重载的方式来实现;

     

    .blk_dev_init

    函数实现源码:

    int __init blk_dev_init(void)
    {
        int i;

        kblockd_workqueue = create_workqueue("kblockd");
        if (!kblockd_workqueue)
            panic("Failed to create kblockd ");

        request_cachep = kmem_cache_create("blkdev_requests",
                sizeof(struct request), 0, SLAB_PANIC, NULL, NULL);

        requestq_cachep = kmem_cache_create("blkdev_queue",
                sizeof(request_queue_t), 0, SLAB_PANIC, NULL, NULL);

        iocontext_cachep = kmem_cache_create("blkdev_ioc",
                sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL);

        for_each_possible_cpu(i)
            INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));

        open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
        register_hotcpu_notifier(&blk_cpu_notifier);

        blk_max_low_pfn = max_low_pfn;
        blk_max_pfn = max_pfn;

        return 0;
    }

    create_workqueue:分配工作队列,每个CPU对应一个工作队列;

    kmem_cache_create:创建高缓存区;

    open_softirq:注册BLOCK_SOFTIRQ类型的软中断,而激活中断的是raise_softirq或raise_softirq_irqoff;

    处理中断的函数就为blk_done_softirq:

    函数实现源码:

    static void blk_done_softirq(struct softirq_action *h)
    {
        struct list_head *cpu_list, local_list;

        local_irq_disable();
        cpu_list = &__get_cpu_var(blk_cpu_done);
        list_replace_init(cpu_list, &local_list);
        local_irq_enable();

        while (!list_empty(&local_list)) {
            struct request *rq = list_entry(local_list.next, struct request, donelist);

            list_del_init(&rq->donelist);
            rq->q->softirq_done_fn(rq);
        }
    }

    过程为:先获取请求终端链表,然后获取获取请求request结构对象,再调用终端处理函数softirq_done_fn,即:request *rq ->request_queue *q ->softirq_done_fn;

    register_hotcpu_notifier:这个函数比较高端与CPU的热插拔有关,编译内核时需打开编译开关CONFIG_HOTPLUG_CPU才有效;

    blk_max_low_pfn:最大的物理帧号

    blk_max_pfn:物理内存内最后一个可用的也用的页帧号;

     

    .subsystem_register

    函数实现源码:

    int subsystem_register(struct subsystem * s)
    {
        int error;

        subsystem_init(s);
        pr_debug("subsystem %s: registering ",s->kset.kobj.name);

        if (!(error = kset_add(&s->kset))) {
            if (!s->kset.subsys)
                s->kset.subsys = s;
        }
        return error;
    }

    这里主要代码就是kset_add,而kset_add在其它篇已经有说了这里不再解释;
  • 相关阅读:
    codeforces 659F F. Polycarp and Hay(并查集+bfs)
    codeforces 659B B. Qualifying Contest(水题+sort)
    codeforces 659E E. New Reform(图论)
    codeforces 659D D. Bicycle Race(水题)
    sql_mode值的含义
    MySQL Query Cache
    Orchestrator安装
    脚本VIP更改为keepalive
    MHA软件下载地址
    MySQL中的事件调度器EVENT
  • 原文地址:https://www.cnblogs.com/jianyuan/p/4170590.html
Copyright © 2020-2023  润新知