块I/O层

块I/O层

前言

Linux的块I/O层

一、剖析一个块设备

  1. 系统中可以随机访问的固定大小数据片(chunks)的硬件设备称为块设备。
  2. 块设备的最小的可寻址单位是扇区,扇区的大小是设备的物理属性,块设备无法对比它还小的单元进行寻址和操作。
  3. 软件有自己的最小逻辑可寻址单元-块,块是文件系统的一种抽象,只能基于块来访问文件系统。
  4. 物理磁盘寻址是按照扇区级进行,内核执行的操盘操作是按照块来执行;块不能比扇区小。
  5. 扇区别名:硬扇区,设备块;
  6. 块别名:文件块,IO块。

二、缓冲区和缓冲区头

  1. 当一个块被调入到内存时,他要存储在一个缓冲区中,每个缓冲区与一个块相对应,是磁盘在内存中表示;一个块可以包含多个扇区,但是大小不能超过一个页面,一个页面可以容纳一个或者多个内存中的块。
  2. 每个缓冲区都有一个对应的描述符号,用来描述块属于哪一个块设备,块对应于哪个缓冲区等。描述符用buffer_head来表示,称为缓冲区头;弊端:
    • 内核倾向于以页面为单位进行处理, 但是buffer_head尺寸可能小;
    • 如果数据比较大,则需要对多个buffer_head结构体进行操作;
struct buffer_head {
	/* First cache line: */
	unsigned long b_state;		/* buffer state bitmap 描述缓存区状态 */
	atomic_t b_count;		/* users using this block 缓存区引用计数*/
	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;		/* block number 与缓冲区对应的块设备中的逻辑块号*/
	u32 b_size;			/* block size 块的大小*/
	char *b_data;			/* pointer to data block 块在页面中的位置, 一个页面中可能有多个块*/

	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 */
};
// 还有unsigned long b_state; 缓冲区状态标志, BH_PrivateStart是不可用的标志,使用它是为了知名可被其他的代码使用的起始位置;块I/O层不会使用BH_PrivateStart或更高的位置;某些驱动程序可以通过b_state域存储信息是可以安全的使用这些位。
  1. 目前内核中的I/O操作的基本容器通过bio结构体表示,该结构体表示了正在现场以片断链表的形式组织的块I/O操作。一个片断是一个小块连续的内存缓冲区,单个缓冲区不一定连续。
/*
 * main unit of I/O for the block layer and lower layers (ie drivers and
 * stacking drivers)
 */
struct bio {
	sector_t		bi_sector;// 磁盘上的相关扇区
	struct bio		*bi_next;	/* request queue link 请求链表*/  
	struct block_device	*bi_bdev;
	unsigned long		bi_flags;	/* status, command, etc */
	unsigned long		bi_rw;		/* bottom bits READ/WRITE,
						 * top bits priority
						 */

	unsigned short		bi_vcnt;	/* how many bio_vec's */
	unsigned short		bi_idx;		/* current index into bvl_vec */

	/* Number of segments in this BIO after
	 * physical address coalescing is performed.
	 */
	unsigned short		bi_phys_segments;

	/* Number of segments after physical and DMA remapping
	 * hardware coalescing is performed.
	 */
	unsigned short		bi_hw_segments;

	unsigned int		bi_size;	/* residual I/O count */
	unsigned int		bi_max_vecs;	/* max bvl_vecs we can hold */

	struct bio_vec		*bi_io_vec;	/* the actual vec list */

	bio_end_io_t		*bi_end_io;
	atomic_t		bi_cnt;		/* pin count */

	void			*bi_private;

	bio_destructor_t	*bi_destructor;	/* destructor */
};

struct bio_vec {
	struct page	*bv_page;
	unsigned int	bv_len;
	unsigned int	bv_offset;
};
- bio包含了一个特定的IO操作需要使用的所有片断,每个bio_vec结构都是一个形式为<page, offset, len>的向量,描述一个特定的片断;片断所在的物理页、块所在物理页的偏移位置、从给定偏移位置开始的块长度。
- bi_vcnt描述vio_vec数组中的向量数目;当io操作完成之后,bi_idx指向数组的当前索引;
- bi_cnt记录bio结构体的使用计数;

在这里插入图片描述
4. bio与buffer_head
- bio结构体代表的是一个IO操作,可以包括内存中的一个或者多个页;buffer_head代表一个缓冲区,描述磁盘中的一个块;
- 因为缓冲区头关联的是单独页中的单独磁盘块,请求如果按照块划分,以后才能够重新组合;而bio不需要连续的存储区;
- 缓冲区描述磁盘块到页面的映射,描述缓冲区信息;bio仅仅描述进行io操作时需要的信息;

三、请求队列

  1. 块I/O请求保存在请求队列中,由reques_queue结构体表示,队列中的请求用request表示;每个请求可能包含多个磁盘块,可以由多个bio结构体表示;

四、IO调度程序

  1. 内核中负责提交I/O请求的子系统称为I/O调度程序;
  2. 电梯调度:
    • 请求合并;
    • 按照扇区增长的方向有序排列;
  3. linux电梯:
    • 请求合并;
    • 按照扇区增长的方向有序排列;
    • 当队列中有超时请求不在合并队列;
  4. 最终期限I/O调度程序
    • 写操作完全和他的应用程序异步执行;写请求的超时时间是5s;
    • 读操作和提交它的应用程序是同步执行的;读请求的超时时间是500ms
    • 需要三条队列协同处理:
      - 排序队列:请求合并,按照扇区的增长的方向有序排列;
      - 写FIFO队列:按照deadline排序;
      - 读FIFO队列:按照deadline排序;
      - 无超时,则使用排序队列,有超时,则使用对应的FIFO队列;
      - 最终的派发队列做请求提交;
  5. 预测IO调度程序
    • 基础为最后期限I/O调度程序;
    • 在每次新的读请求处理时,进行空闲片刻,可以使得新来的请求进行合并处理(局部性原理);
    • 如果等待可以减少读请求带来的向后再向前的寻址操作,则值得,否则带来轻微的性能损失;依赖于预测准确率;
  6. 完全公平的排队I/O调度程序
    • 每个提交I/O进程的有自己的队列;以时间片轮转调度队列,从每个队列中选择4个进行处理;对预定工作负荷的可以较好的处理,如多媒体;
  7. 空操作的I/O调度程序
    • 随机访问设备不需要考虑扇区增长这个特点;
    • 进行请求合并;

五、总结

  1. bio表示活动的I/O操作;
  2. buffer_head:表示块到页的映射;
  3. 请求结构:表示具体的I/O请求;
  4. I/O调度程序:as, cfq,deadline,noop
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值