免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1074 | 回复: 0
打印 上一主题 下一主题

Chap13 块I/O层 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-20 15:30 |只看该作者 |倒序浏览
  
块设备——能随机(不需要按顺序)访问固定大小数据片(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_vec、bi_vcnt和bi_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请求
即管理块设备的请求队列,决定队列中的请求排列顺序以及在什么时候派发请求到块设备
减少寻址时间——合并、排序
4种I/O调度方法(详细见书P195~198):
最终期限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


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/85048/showart_1904503.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP