块设备

块设备

在linux下,文件的缓存习惯性的称之为Page cache,而更低一个级的设备的缓存称之为Buffer cache。Page cache用于缓存文件的内容,和文件系统比较相关。文件的内容需要映射到实际的物理磁盘,这种映射关系由文件系统来完成;Buffer cache用于缓存存储设备块(比如磁盘扇区)的数据,而不关心是否有文件系统的存在(文件系统的元数据缓存在buffer cache中)

除了传统的Buffered IO可以比较自由的用偏移+长度的方式读写文件之外,mmap和Direct IO均有数据俺也对齐的要求,Direct IO还限制读写必须是底层存储设备块大小的整数倍

mmap

syscall read

下图为读磁盘文件read系统调用在内核的路径

syscall_read.png

重要数据结构

其中重要的数据结构包含struct request结构,该结构就是struct bio结构链表的封装

struct request_queue结构中包含了struct request链表的头,在request结构中包含了bio结构的头,bio结构中包含了bi_io_vec数组头,数组中每个元素描述了io操作中的一个段,bi_vcnt是段的总数。每个struct request代表一个请求,链表组成一个队列,存放到了struct request_queue中,最终传送的数据存放在bio_io_vec数组中的元素中,经过blk_rq_map_sg()函数将要传输的数据页映射成分散聚集struct scatterlist表 cbio和buffer指向第一个没有被传送的bio结构,每个bio都标识一个磁盘存储区标识符(存储区中的起始扇区号和扇区数)和一个或者多个描述与IO操作相关的内存区的段。即要读写设备的的磁盘扇区,与内存中数据的位置

block_request

bio

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* 通用块的核心数据结构。它描述了块设备的IO操作。
* 通用块层是一个内核组件,它处理来自系统中的所有块设备发出的请求。
* 每个bio都标识一个磁盘存储区标识符(存储区中的起始扇区号和扇区数,扇区号是逻辑块号,不是真正物理上的扇区号)。
* 和一个或者多个描述与IO操作相关的内存区的段。
*/
struct bio {
/**
* 块IO操作的第一个磁盘扇区
*/
sector_t bi_sector;
/**
* 链接到请求队列中的下一个bio
*/
struct bio *bi_next; /* request queue link */
/**
* 指向块设备描述符的指针
*/
struct block_device *bi_bdev;
/**
* bio的状态标志。
* 如果是写请求,最低有效位将被设置。需要使用bio_data_dir宏来确定读写标志。
*/
unsigned long bi_flags; /* status, command, etc */
/**
* io操作标志。
*/
unsigned long bi_rw; /* bottom bits READ/WRITE,
* top bits priority
*/
/**
* bio的bio_vec数组中的数目。
*/
unsigned short bi_vcnt; /* how many bio_vec's */
/**
* bio的bio_vec数组中段的当前索引值
*/
unsigned short bi_idx; /* current index into bvl_vec */

/* Number of segments in this BIO after
* physical address coalescing is performed.
*/
/**
* 合并之后bio中物理段的数目
*/
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 */

/*
* To keep track of the max hw size, we account for the
* sizes of the first and last virtually mergeable segments
* in this bio
*/
/**
* 硬件段合并算法使用
*/
unsigned int bi_hw_front_size;
/**
* 硬件段合并算法使用
*/
unsigned int bi_hw_back_size;

/**
* bio的bio_vec数组中允许的最大段数
*/
unsigned int bi_max_vecs; /* max bvl_vecs we can hold */

/**
* 指向bio的bio_vec数组的指针,它描述了要传送的数据缓冲区。
*/
struct bio_vec *bi_io_vec; /* the actual vec list */

/**
* bio的IO操作结束时调用的方法
*/
bio_end_io_t *bi_end_io;
/**
* bio的引用计数器
*/
atomic_t bi_cnt; /* pin count */

/**
* 通用块层和块设备驱动程序的IO完成方法使用的指针
*/
void *bi_private;

/**
* 释放bio时调用的析构方法(通常是bio_destructor方法)
*/
bio_destructor_t *bi_destructor; /* destructor */
};
# 推荐文章
  1.git推送到vps
  2.http服务器搭建
  3.linux网卡命名
  4.docker使用
  5.hexo创建博客

评论


:D 一言句子获取中...

加载中,最新评论有1分钟延迟...