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\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块层(一)的更多相关文章
- Linux文件IO与通用块层的请求合并
本文参考https://mp.weixin.qq.com/s/Imt4BW-zoHPpcOpcKZs_AQ, 公众号“Linux阅码场” 请求合并就是将进程内或者进程间产生的在物理地址上连续的多个IO ...
- linux内核系列(一)编译安装Linux内核 2.6.18
1.配置环境 操作系统:CentOS 5.2 下载linux-2.6.18版本的内核,网址:http://www.kernel.org 说明:该编译文档适合2.6.18以上的Linux内核版本,只需所 ...
- linux内核系列(二)内核数据结构之链表
双向链表 传统链表与linu内核链表的区别图: 图一 图二 从上图中看出在传统链表中各种不同链表间没有通用性,因为各个数据域不同,而在linux内核中巧妙将链表结构内嵌到数据域结构中使得不同结构之间能 ...
- Linux内核设计笔记14——块I/O层
块I/O层 基本概念 系统中可以随机访问固定大小数据片的硬件设备称做块设备,这些固定大小的数据片称之为块.还有一种基本的设备称之为字符设备,其需要按照顺序访问,比如键盘. 扇区:块设备中最小的寻址单元 ...
- Linux内核系列设备模型(一) Kobject与Kset
1.Kobject Kobject是设备驱动模型的核心结构,它使所有设备在底层都有统一的接口.在内核注册的kobject对象都会对应sysfs文件系统中的一个目录(目录名称有Kobject结构中k_n ...
- Linux内核系列—C语言中内嵌汇编 asm __volatile__,asm__volatile_【转】
转自:http://www.bkjia.com/Androidjc/1109412.html 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器, ...
- core dump + LINUX 内核系列博客
参考:http://www.cnblogs.com/ahuo/category/72819.html http://blog.csdn.net/tenfyguo/article/details/815 ...
- 24小时学通LINUX内核系列
http://www.cnblogs.com/lihuidashen/category/667475.html
- 2017-2018-1 20179205《Linux内核原理与设计》第八周作业
<Linux内核原理与设计>第八周作业 视频学习及操作分析 预处理.编译.链接和目标文件的格式 可执行程序是怎么来的? 以C语言为例,经过编译器预处理.编译成汇编代码.汇编器编译成目标代码 ...
随机推荐
- Python 基础篇:字典、集合、文件操作
字典 字典一种key - value 的数据类型 1. 语法: info = { 'stu1101': "TengLan Wu", 'stu1102': "LongZe ...
- OpenFileDialog组件打开文件....待续
1.常用属性 InitialDirectory 对话框的初始目录 this.openFileDialog1.InitialDirectory = "d:\\"; ...
- Network boot from AMD Am79C970A
用虚拟机安装winxp系统,出现错误信息如下: Network boot from AMD Am79C970A Copright (c)2003-2005 Vmware, Inc. Copright ...
- MVC5-Scaffolder
[转]Visual Studio.net 2013 asp.net MVC 5 Scaffolding代码生成向导开源项目 提高开发效率,规范代码编写,最好的方式就是使用简单的设计模式(MVC , R ...
- 我的第一个BAE python应用
第一步 用baidu帐号登陆开发者中心 http://developer.baidu.com/ Baidu的引导,帮助说明已经很详细, 这里不重复. 第二步,创建新版本 用svn check out ...
- objective-c常用数学方法
1. 三角函数 double sin (double);正弦 double cos (double);余弦 double tan (double);正切 2 .反三角函数 double as ...
- Python属性、方法和类管理系列之----__slots__属性
一句话说明 __slots__是用来限制实例的属性的,__slots__可以规定实例是否应该有__dict__属性:__slots__不能限制类的属性. 只有__slots__列表内的这些变量名可赋值 ...
- Automotive Security的一些资料和心得(8):Hardware Security Module (HSM)
1. Introduction - 保护软件的安全性措施,作为值得信赖的安全锚,- 安全地生成,存储和处理安全性关键材料屏蔽任何潜在的恶意软件,?- 通过运用有效的限制硬件篡改攻击的可能性篡改保护措施 ...
- Oracle数据库的下载和安装
那天分享一下Oracle的下载和安装的过程,有需要的朋友可以借鉴参考一下.如有雷同不胜感激! 首先可以到Oracle的官网下载Oracle的最次年版本的Oracle数据库.一下是个人下载的数据库版本百 ...
- Firefly官方教程之Distributed使用文档
原地址:http://bbs.gameres.com/thread_224191.html distributed使用文档1.distributed说明该模块主要封装了各个服务进程间进行通信的方法.n ...