Linux2.6内核--对块IO层操作的讨论
当一个块被调入内存时(也就是说,在读入后或等待写出时),它要存储在缓冲区中。每个缓冲区与一个块对应,它相当于是磁盘块在内存中的表示。块包含一个或多个扇区,但大小不能超过一页,所以一页可以容纳一个或多个内存块。由于内核在处理数据时需要一些相关的控制信息(比如块属于哪个设备,块对应于哪个缓冲区),所以,每一个缓冲区都有一个对应的描述符。该描述符用 buffer_head 结构体表示,称作缓冲区头,在文件 <linux/buffer_head.h> 中定义,它包含了内核操作缓冲区的全部信息。
下面给出缓冲区头结构体和其中每一个域的说明:
struct buffer_head {
unsigned long b_state; /* buffer state bitmap (see above) */
struct buffer_head *b_this_page;/* circular list of page's buffers */
struct page *b_page; /* the page this bh is mapped to */
sector_t b_blocknr; /* start block number */
size_t b_size; /* size of mapping */
char *b_data; /* pointer to data within the page */
struct block_device *b_bdev;
bh_end_io_t *b_end_io; /* I/O completion */
void *b_private; /* reserved for b_end_io */
struct list_head b_assoc_buffers; /* associated with another mapping */
struct address_space *b_assoc_map; /* mapping this buffer is
associated with */
atomic_t b_count; /* users using this buffer_head */
};
缓冲区头的目的在于描述磁盘块和物理内存缓冲区之间的映射关系。这个结构体在内核中只是扮演一个描述符的角色,说明从缓冲区到块的映射关系。
在2.6内核以前,缓冲区头的作用比现在还要重要。因为缓冲区头作为内核中的 IO 操作单元,不仅仅描述了从磁盘块到物理内存的映射,而且还是所有块 IO 操作的容器。但是在2.6内核以后改变了这种策略,它使用一个新的结构 -- bio 来作为操作容器。
bio 结构体定义于 <linux/bio.h> 中,下面给出 bio 结构体和每个域的描述:
struct bio {
sector_t bi_sector; /* associated sector on disk */
struct bio *bi_next; /* list of requests */
struct block_device *bi_bdev; /* associated block device */
unsigned long bi_flags; /* status and command flags */
unsigned long bi_rw; /* read or write? */
unsigned short bi_vcnt; /* number of bio_vecs off */
unsigned short bi_idx; /* current index in bi_io_vec */
unsigned short bi_phys_segments; /* number of segments after coalescing */
unsigned short bi_hw_segments; /* number of segments after remapping */
unsigned int bi_size; /* I/O count */
unsigned int bi_hw_front_size; /* size of the first mergeable segment */
unsigned int bi_hw_back_size; /* size of the last mergeable segment */
unsigned int bi_max_vecs; /* maximum bio_vecs possible */
struct bio_vec *bi_io_vec; /* bio_vec list */
bio_end_io_t *bi_end_io; /* I/O completion method */
atomic_t bi_cnt; /* usage counter */
void *bi_private; /* owner-private method */
bio_destructor_t *bi_destructor; /* destructor method */
};
使用 bio 结构体的目的主要是代表正在现场执行的 IO 操作,所以该结构体中的主要域都是用来管理相关信息的,其中最重要的几个域是 bi_io_vecs , bi_vcnt 和 bi_idx 。下图显示了 bio 结构体及其他结构体之间的关系。
说明:每一个块 IO 请求都通过一个 bio 结构体表示。每个请求包含一个或多个块,这些块存储在 bio_vec 结构体数组中。这些结构体描述了每个片段在物理页中的实际位置,并且像向量一样被组织在一起。 IO 操作的第一个片段由 b_io_vec 结构体所指向,其他的片段在其后依次放置,共有 bi_vcnt个片段。当块 IO 层开始执行请求,需要使用各个片段时, bi_idx 域会不断更新,从而指向当前片段。
新老方法的比较:
缓冲区头和新的 bio 结构体之间存在显著差别。bio 结构体代表的是 IO操作,它可以包括内存中的一个或多个页;而另一方面,buffer_head 结构体代表的是一个缓冲区,它描述的仅仅是磁盘中的一个块,所以他可能会引起不必要的分割,将请求按块为单位划分,只能靠以后再重新组合。由于 bio 结构体是轻量级的,它描述的块可以不需要连续存储区,并且不需要分割 IO 操作。
Linux2.6内核--对块IO层操作的讨论的更多相关文章
- Linux3.10.0块IO子系统流程(7)-- 请求处理完成
和提交请求相反,完成请求的过程是从低层驱动开始的.请求处理完成分为两个部分:上半部和下半部.开始时,请求处理完成总是处在中断上下文,在这里的主要任务是将已完成的请求放到某个队列中,然后引发软终端让中断 ...
- Linux3.10.0块IO子系统流程(0)-- 块IO子系统概述
前言:这个系列主要是记录自己学习Linux块IO子系统的过程,其中代码分析皆基于Linux3.10.0版本,如有描述错误或不妥之处,敬请指出! 参考书籍:存储技术原理分析--基于Linux 2.6内核 ...
- Linux2.6 内核的 Initrd 机制解析(转)
from: https://www.ibm.com/developerworks/cn/linux/l-k26initrd/ 简介: Linux 的 initrd 技术是一个非常普遍使用的机制,lin ...
- Windows内核原理-同步IO与异步IO
目录 Windows内核原理-同步IO与异步IO 背景 目的 I/O 同步I/O 异步I/O I/O完成通知 总结 参考文档 Windows内核原理-同步IO与异步IO 背景 在前段时间检查异常连接导 ...
- 聊聊Netty那些事儿之从内核角度看IO模型
从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...
- Linux2.6内核实现的是NPTL
NPTL是一个1×1的线程模型,即一个线程对于一个操作系统的调度进程,优点是非常简单.而其他一些操作系统比如Solaris则是MxN的,M对应创建的线程数,N对应操作系统可以运行的实体.(N<M ...
- Hadoop基础-通过IO流操作HDFS
Hadoop基础-通过IO流操作HDFS 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.上传文件 /* @author :yinzhengjie Blog:http://www ...
- (笔记)Linux内核中内存相关的操作函数
linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...
- Linux2.6 内核的 Initrd 机制解析
文章来自:www.ibm.com/developerworks/cn/linux/l-k26initrd/ 1.什么是 Initrd initrd 的英文含义是 boot loader initial ...
随机推荐
- DataGridView的DataGridViewComboBoxColumn列点击一次,自动处于编辑状态
本文转载:http://www.cnblogs.com/Johnny_Z/archive/2012/02/12/2348235.html Winform中的DataGridView数据绑定控件有时会用 ...
- android AppWidgwtProvider学习
实现AppWidgwtProvider: onUpdate() //在达到制定的更新时间之后或者当用户向桌面添加 App Widget时会调用该方法. onDeleted() //当App Wid ...
- 【Cocos2d-X开发学习笔记】第29期:游戏中数据的存储(上)
本系列学习教程使用的是cocos2d-x-2.1.4(最新版为3.0alpha0-pre) ,PC开发环境Windows7,C++开发环境VS2010 一般游戏中都需要记录玩家数据,便于玩家下次登录时 ...
- Note | javascript权威指南[第六版] 第2章:词法结构
语法结构规定了诸如变量名是什么样的.怎么写注释,以及程序语句之间如何分隔等规则.本章用很短的篇幅来介绍JavaScript的词法结构. 2.1.字符集 JavaScript程序是用Unic ...
- 从 ReactiveCocoa 中能学到什么?不用此库也能学以致用
从知道ReactiveCocoa开始就发现对这个库有不同的声音,上次参加<T>技术沙龙时唐巧对在项目中已全面使用FRP的代码家提出为什么这种编程模型出现了这么长时间怎么像ReactiveC ...
- Python多线程锁
[Python之旅]第六篇(四):Python多线程锁 python lock 多线程 多线程使用方法 多线程锁 摘要: 在多线程程序执行过程中,为什么需要给一些线程加锁以及如何加锁,下面就来 ...
- codevs4203山区建小学
/* 状态:f[i][j] 前i个村庄已经建了j个学校 转移:f[i][j]=min(f[i][j],f[ii][j-1]+s[ii+1][i]) 1<=ii<=i-1 */ #inclu ...
- Android中Application全局方法(变量)的调用
Application和Actovotu,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息.通常我们是 ...
- Android中的缓存机制与实现
分步阅读 Android开发本质上就是手机和互联网中的web服务器之间进行通信,就必然需要从服务端获取数据,而反复通过网络获取数据是比较耗时的,特别是访问比较多的时候,会极大影响了性能,Android ...
- Google2016开发者大会
Android主讲: 一.吴晶:android笔记博主(博客:http://www.race604.com/) 主题:Android低功耗蓝牙(BLE)实践 低功耗蓝牙在可穿戴和智能家居里边用的比较多 ...