.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\n");

    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\n",s->kset.kobj.name);

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

这里主要代码就是kset_add,而kset_add在其它篇已经有说了这里不再解释;

Linux内核系列之Block块层(一)的更多相关文章

  1. Linux文件IO与通用块层的请求合并

    本文参考https://mp.weixin.qq.com/s/Imt4BW-zoHPpcOpcKZs_AQ, 公众号“Linux阅码场” 请求合并就是将进程内或者进程间产生的在物理地址上连续的多个IO ...

  2. linux内核系列(一)编译安装Linux内核 2.6.18

    1.配置环境 操作系统:CentOS 5.2 下载linux-2.6.18版本的内核,网址:http://www.kernel.org 说明:该编译文档适合2.6.18以上的Linux内核版本,只需所 ...

  3. linux内核系列(二)内核数据结构之链表

    双向链表 传统链表与linu内核链表的区别图: 图一 图二 从上图中看出在传统链表中各种不同链表间没有通用性,因为各个数据域不同,而在linux内核中巧妙将链表结构内嵌到数据域结构中使得不同结构之间能 ...

  4. Linux内核设计笔记14——块I/O层

    块I/O层 基本概念 系统中可以随机访问固定大小数据片的硬件设备称做块设备,这些固定大小的数据片称之为块.还有一种基本的设备称之为字符设备,其需要按照顺序访问,比如键盘. 扇区:块设备中最小的寻址单元 ...

  5. Linux内核系列设备模型(一) Kobject与Kset

    1.Kobject Kobject是设备驱动模型的核心结构,它使所有设备在底层都有统一的接口.在内核注册的kobject对象都会对应sysfs文件系统中的一个目录(目录名称有Kobject结构中k_n ...

  6. Linux内核系列—C语言中内嵌汇编 asm __volatile__,asm__volatile_【转】

    转自:http://www.bkjia.com/Androidjc/1109412.html 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器, ...

  7. core dump + LINUX 内核系列博客

    参考:http://www.cnblogs.com/ahuo/category/72819.html http://blog.csdn.net/tenfyguo/article/details/815 ...

  8. 24小时学通LINUX内核系列

    http://www.cnblogs.com/lihuidashen/category/667475.html

  9. 2017-2018-1 20179205《Linux内核原理与设计》第八周作业

    <Linux内核原理与设计>第八周作业 视频学习及操作分析 预处理.编译.链接和目标文件的格式 可执行程序是怎么来的? 以C语言为例,经过编译器预处理.编译成汇编代码.汇编器编译成目标代码 ...

随机推荐

  1. web2py--------------用web2py写 django的例子 --------建立一个投票应用(2)

    建立模型 我们在models下及那里polls.py 文件内容如下 # -*- coding: utf-8 -*- pollsdb=DAL(uri='sqlite://polls.db') polls ...

  2. FatFsVersion0.01源码分析

    目录 一.API的函数功能简述 二.FATFS主要数据结构 1.FAT32文件系统的结构 2.FATFS主要数据结构 ①   FATFS ②   DIR ③  FIL ④  FILINFO ⑤  wi ...

  3. Cygwin下设置ls显示颜色

    vi ~/.bashrc 找到alias ls="xxxxxxxxxxxxxxxxxxxxxxxx"这一项,把注释去掉 修改后的这一行为: alias ls='ls -hF --c ...

  4. C# const和statci readonly区别

    1.const 是属于编译时的变量,它定义的常量是在对象初始化时赋值,以后不能改变他的值. 它适用于两种场景:1.取值永久不变(比如圆周率.一天包含的小时数.地球的半径等)  2.对程序性能要求非常苛 ...

  5. iOS 中SQLite数据库操作

    在iOS中实现SQLite数据库的操作:1.导入框架(libsqlite3.0.tbd) 2.导入头文件<sqlite3.h> 3.实现数据的增删改查 实现简单 SQLite数据库操作 的 ...

  6. [转载]C# HashTable 遍历与排序

    private void Form1_Load(object sender, EventArgs e) { Hashtable ht = new Hashtable(); ht.Add("j ...

  7. Adaboost原理及目标检测中的应用

    Adaboost原理及目标检测中的应用 whowhoha@outlook.com Adaboost原理 Adaboost(AdaptiveBoosting)是一种迭代算法,通过对训练集不断训练弱分类器 ...

  8. Fast CGI 工作原理

    http://www.cppblog.com/woaidongmao/archive/2011/06/21/149092.html 一.FastCGI是什么? FastCGI是语言无关的.可伸缩架构的 ...

  9. QT做界面真是绝美,并且还可嵌入HTML与JS做界面(许多案例)

    1. 这年头想要酷炫, 还是用web最方便, QT自带嵌入式webkit, 然后用d3.js D3.js - Data-Driven Documents什么的, 各种酷炫的互动表随手而来.这里有各种各 ...

  10. Yii CDbCriteria

    Yii的Active Recorder包装了很多. 特别是把SQL中 把where,order,limit,IN/not IN,like等常用短句都包含进CDbCriteria这个类中去,这样整个代码 ...