Chinaunix首页 | 论坛 | 博客
  • 博客访问: 22431
  • 博文数量: 18
  • 博客积分: 810
  • 博客等级: 准尉
  • 技术积分: 205
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-10 21:09
文章分类
文章存档

2009年(15)

2008年(3)

我的朋友

分类: LINUX

2009-04-20 15:30:52

 

块设备——能随机(不需要按顺序)访问固定大小数据片(chunk)的设备。硬盘、软盘驱动器、闪存等

字符设备——按照字符流的方式被有序访问。串口、键盘等

 

块设备的管理比字符设备复杂,因为字符设备仅需要控制一个位置(当前位置),而块设备访问的位置必须能够在介质的不同区间前后移动;

此外,块设备的执行性能的要求很高。

=> 需要为块设备提供专门的服务子系统

13.1 解剖一个块设备

物理磁盘寻址按扇区进行,内核执行的所有磁盘操作是按块进行的。

扇区

设备的最小寻址单元

也称为硬扇区、设备块

2的整数倍,一般是512个字节

文件系统的最小寻址单元

也称为文件块、I/O

一个或多个扇区,不超过内存页大小

 

13.2 缓冲区和缓冲区头

块调入内存时,被存放在缓冲区中;

每个缓冲区对应一个块,相当于磁盘块在内存中的表示;

缓冲区头:记录内核操作缓冲区所需要的控制信息,描述了磁盘块和物理内存缓冲区直接的映射。

 

struct buffer_head {
        unsigned long b_state; /* buffer state flags 缓冲区状态标志*/
        atomic_t b_count; /* buffer usage counter 试用计数 get_bh()和put_bh()增加或减少*/
        struct buffer_head *b_this_page; /* buffers using this page 页面中的缓冲区*/
        struct page *b_page; /* page storing this buffer 存储缓冲区的页面*/
        sector_t b_blocknr; /* logical block number 逻辑块号*/
        u32 b_size; /* block size (in bytes) 块大小(以字节为单位)*/
        char *b_data; /* buffer in the page 页面中的缓冲区*/
        struct block_device *b_bdev; /* device where block resides 块设备*/
        bh_end_io_t *b_end_io; /* I/O completion method I/O完成方法*/
        void *b_private; /* data for completion method 完成方法数据*/
        struct list_head b_assoc_buffers; /* list of associated mappings 相关的映射链表*/
};

其中缓冲区状态b_state,定义在中的bh_state_bits枚举中:

Status Flag

Meaning

BH_Uptodate

Buffer contains valid data

BH_Dirty

Buffer is dirty (the contents of the buffer are newer than the contents of the block on disk and therefore the buffer must eventually be written back to disk)

BH_Lock

Buffer is undergoing disk I/O and is locked to prevent concurrent access

BH_Req

Buffer is involved in an I/O request

BH_Mapped

Buffer is a valid buffer mapped to an on-disk block

BH_New

Buffer is newly mapped via get_block() and not yet accessed

BH_Async_Read

Buffer is undergoing asynchronous read I/O via end_buffer_async_read()

BH_Async_Write

Buffer is undergoing asynchronous write I/O via end_buffer_async_write()

BH_Delay

Buffer does not yet have an associated on-disk block

BH_Boundary

Buffer forms the boundary of contiguous blocksthe next block is discontinuous

由于缓冲区头结构体比较大,不易控制,且只能描述单个缓冲区,因此引入更灵活的轻量级bio结构体。

13.3 bio结构体

bio结构体代表正在活动的以片断(segment)链表形式组织的块I/O操作。

一个片断就是一小块连续的内存缓冲区,这样就不需要保证单个缓冲区一定要连续,所以通过用片断来描述缓冲区,可以使一个缓冲区分散在内存的多个位置上。

 

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结构体的创建者才能使用*/
        bio_destructor_t *bi_destructor; /* destructor method */
};

需要注意的是bi_io_vecbi_vcntbi_idx直接的关系

其中:

 

struct bio_vec {
        /* pointer to the physical page on which this buffer resides指向缓冲区所驻留的物理页 */
        struct page *bv_page;
        /* the length in bytes of this buffer 这个缓冲区以字节为单位的大小*/
        unsigned int bv_len;
        /* the byte offset within the page where the buffer resides 缓冲区所驻留的页以字节为单位的偏移量*/
        unsigned int bv_offset;
};

总结:

每个块I/O请求都由一个bio结构体表示;

每个请求包含一个或多个块,块存储在bio_vec结构体数组中;

bio_vec结构体描述了每个片断在物理页中的实际位置,并像向量一样被组织在一起;

I/O操作的第一个片断由b_io_vec结构指向,其他片断会在其后依次排放,共有bio_vcnt个;

当块I/O层开始执行请求,使用各个片断时,bi_idx不断更新,指向当前片断。

13.4 请求队列

request_queue结构体

块设备将它们挂起的块I/O请求保存在请求队列中

队列中的请求由结构体request表示

一个请求可以操作多个连续磁盘块,因此每个请求可以由多个bio结构体组成

磁盘上的块必须连续,但内存中的块不一定需要连续(bio结构体可以描述多个片断)

13.5 I/O调度程序

磁盘寻址非常缓慢 => I/O调度程序

将磁盘I/O资源分配给系统中所有挂起的块I/O请求

即管理块设备的请求队列,决定队列中的请求排列顺序以及在什么时候派发请求到块设备

减少寻址时间——合并、排序

4I/O调度方法(详细见书P195198):

最终期限I/O调度程序;

预测I/O调度程序;

完全公正的排队I/O调度程序;

空操作的I/O调度程序。

I/O调度程序的选择:

Parameter

I/O Scheduler

as

Anticipatory预测

cfq

Complete Fair Queuing完全公正的排队

deadline

Deadline最终期限

noop

Noop空操作

使用方法,例如elevator=cfq

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