Chinaunix首页 | 论坛 | 博客
  • 博客访问: 232370
  • 博文数量: 27
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 213
  • 用 户 组: 普通用户
  • 注册时间: 2015-06-10 22:38
文章分类

全部博文(27)

文章存档

2016年(1)

2015年(26)

分类: LINUX

2015-06-14 00:00:03

原文地址:块设备原理与操作 作者:fireaxe

 

1.       块设备分层

VFS作用:屏蔽下层文件系统的差异,为上层提供统一接口。正是由于VFS的存在,所以可以把设备、内存、信息等一切都抽象成文件。不管底层是flash还是磁盘,接口都是一样的。

具体文件系统:不同的文件系统有不同的格式,如FATEXT3等。每种文件系统都有自己的操作集合。

Page Cache:引入cache的目的是提高访问性能。上层的访问请求通常不会是对齐的,而下层的驱动都是对齐的,每次操作最小都是按Sector进行读写。cache的作用是,不论上层读写是否只是几个字节,都会按sector来取,并存入Page Cache。如果两次的请求在同一个sector上,则第二次不会再调用底层驱动,而是直接靠Page  Cache中缓存的数据完成操作。

Generic Block Layer:接受上层发出的读写请求,并最终发送IO请求。

IO调度器:IO调度器不是必须的,作用是对IO请求进行重排,以提高磁盘访问效率。

Block Device Driver Layer:根据上层IO请求进行实际的设备读写。

Block Device Layer:具体的物理设备,定义了设备操作规范,如读写信号、时钟周期等。

  

2.       块设备读写原理

 

 

调用writeread时都会产生一个bio请求,bio中使用bvec表示buff,每个bvec指向一个page4k)。

bio->bi_sector:起始扇区号

bio->bi_size:大小

bio->bi_rw:读写操作

从上述参数看,bio的操作粒度为一个sector512Bytes),所以即使读写一个字节,也会读写一个sector。究其原因,块设备早期是为了操作磁盘设备,而磁盘设备最小粒度就是sector。同样道理,IO调度器的策略也是针对早期磁盘特性的,可以减少磁头的运动次数。现在的磁盘都支持线性读写,所以不适用IO调度器(或使用IO调度器中的NONE调度规则)效率更高一些。

bio的参数只要勇于块设备中的定位,用户buffer的信息则存储在bvec表中。

bvec->bv_pagebuffer物理页号

bvec->bv_offset:业内偏移量

bvec->bv_len:数据长度

用户buffer来自用户空间,这块空间在用户空间是连续的,但在物理空间中不需要连续。内核用bvec数组表示一个bio请求中所需要buffer对应的物理page,每个bvec对应着一个物理page。这也决定了bv_offset加上bv_len不能超过一个page大小。

使用IO调度器时,为了方便,内核会申请一块连续的内核地址空间用于映射这块buffer,所以看起来buffer还是连续的,如果我们的块设备只是一块内存,则可以用memcpy直接实现数据传送。

如果我们不用IO调度器,则我们得到的只是一堆不连续的bvec,需要驱动来完成每个bvec的拷贝。每个bvec的处理过程如下:

阅读(3268) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~