作者:YouChuang
本文主要介绍学习块IO层的基本原理
整体结构
I/O设备
* 基本概念
“an input/output device is a hardware device that accepts inputted information and also has the capability of outputting that information.”
常见的就是打印机、硬盘、软盘、光盘、键盘和鼠标
分类字符设备和块设备
区分方法:是不是能够随机的访问数据,字符设备是顺序访问,而块设备可以任意访问指定位置
块设备
块设备的最小可寻址单元是扇区,一般是512字节,大小是设备的物理属性,对于小于扇区的单元设备无法寻址
块设备需要文件系统和块驱动来管理
而为了上层的统一访问,文件系统把设备空间的最小逻辑可寻址单元设定为块,块肯定要大于扇区,不然物理上寻址不到,内核要求块的大小是扇区的2的整数倍,并且不能超过页的大小。
* 缓冲区
块由块设备调入内存时存储在缓冲区中,每个缓冲区和一个块对应
缓冲区的描述符称为缓冲区头,由buffer_head结构体来描述,主要用来描述磁盘块和物理内存缓冲区之间的映射关系
后来又引入了新的描述方式
struct buffer_head {
62 unsigned long b_state; /* buffer state bitmap (see above) */
63 struct buffer_head b_this_page;/ circular list of page’s buffers */
64 struct page b_page; / the page this bh is mapped to */
65
66 sector_t b_blocknr; /* start block number 起始块号 */
67 size_t b_size; /* size of mapping */
68 char b_data; / pointer to data within the page */
69
struct block_device *b_bdev;
71 bh_end_io_t b_end_io; / I/O completion */
72 void b_private; / reserved for b_end_io */
73 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 */
};
b_count为缓冲区的使用计数,由get_bh和put_bh两个方法来增减
/* 用在操作缓冲区之前 */
252 static inline void get_bh(struct buffer_head *bh)
253 {
254 atomic_inc(&bh->b_count);
255 }
/* 用在操作缓冲区之后 */
257 static inline void put_bh(struct buffer_head *bh)
258 {
259 smp_mb__before_atomic_dec();
260 atomic_dec(&bh->b_count);
261 }
* bio结构体
bio结构体代表了正在活动的以片段链表形式组织的块I/O操作,表示一个块I/O请求,每个请求包含一个或者多个块,一个片段是一小块连续的内存缓冲区,这样就不需要保证单个缓冲区一定要连续,可以分散在内存的多个位置上
struct bio {
sector_t bi_sector; /* device address in 512 byte sectors / / 磁盘上相关的扇区 */
struct bio bi_next; / request queue link */
struct block_device bi_bdev; / 指向块设备描述符 */
67 unsigned long bi_flags; /* status, command, etc */
68 unsigned long bi_rw; /* bottom bits READ/WRITE, top bits priority*/
unsigned short bi_vcnt; /* how many bio_vec’s */
unsigned short bi_idx; /* 分割bio结构体,current index into bvl_vec */
78 unsigned int bi_phys_segments;
80 unsigned int bi_size; /* residual I/O count */
86 unsigned int bi_seg_front_size;
87 unsigned int bi_seg_back_size;
88
89 unsigned int bi_max_vecs; /* max bvl_vecs we can hold */
90
91 unsigned int bi_comp_cpu; /* completion CPU */
92
93 atomic_t bi_cnt; /* pin count */
94
struct bio_vec bi_io_vec; / 描述IO操作的一个片段(Page,offset,Len),the actual vec list 指向bio_vec结构体的第一个元素 */
96
97 bio_end_io_t *bi_end_io;
98
99 void *bi_private;
104 bio_destructor_t bi_destructor; / destructor */
struct bio_vec bi_inline_vecs[0];
};
bio_vec结构体
struct bio_vec {
47 struct page *bv_page;
48 unsigned int bv