|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 thinkfunny 于 2020-4-17 18:35 编辑 4 K1 G# _$ K; I) c0 n6 j
1 `# V9 [8 c) d: ?
以下内容的分析是基于2.6.32及其后的内核.! f8 C/ P5 C7 z; R' ~
7 ~% Z5 S; c9 Y5 \我们在linux上总是要保存数据,数据要么保存在文件系统里(如ext3),要么就保存在裸设备里。我们在使用这些数据的时候都是通过文件这个抽象来访问的,操作系统会把我们需要的数据提交给我们,而我们则无需和块设备打交道。) Z1 V7 X# P) R' U0 x" ]
+ I3 {- t& H. r/ r/ V从下图,我们可以清除的看到:
; U1 Z* \3 T$ x, D' D' Y; h! i; W. T) ?, a: R6 \ m3 U7 @, y2 i
( K9 g% p: }" T+ O$ n" }
6 h) q |; g& x/ ?) F7 c) `3 \0 M
I/O子系统是个层次很深的系统,数据请求从用户空间最终到达磁盘,经过了复杂的数据流动。8 m* w. D. V$ j& s# _
9 o+ F& l2 y) Y/ v对设驱开发人员或与此相关的设计人员,特别是IO很密集,我们就需要搞清楚IO具体是如何动作的,免得滥用IO和导致设计问题。* _& f* U- U/ T2 F7 k* E
2 c. E1 n6 b+ Z: Y9 g3 d
/ M# R! O/ g/ m5 h7 B2 x. u1 I
1 f, r1 N) R |0 S! _IBM developworks中,〈read系统调用剖析〉阐述就很清楚。 j' O9 q7 F. F$ `0 b) o: Y* ]' D- I
- ~6 m5 c9 ^3 I3 x1 X. S# x+ S
read系统调用的处理分为用户空间和内核空间处理两部分。其中,用户空间处理只是通过0x80中断陷入内核,接着调用其中断服务例程,即sys_read以进入内核处理流程。$ U4 V7 r/ L) t, y2 A
n6 Q( j U s/ _8 u/ D对于read系统调用在内核的处理,如上图所述,经过了VFS、具体文件系统,如ext2、页高速缓冲存层、通用块层、IO调度层、设备驱动层、和设备层。其中,VFS主要是用来屏蔽下层具体文件系统操作的差异,对上提供一个统一接口,正是因为有了这个层次,所以可以把设备抽象成文件。具体文件系统,则定义了自己的块大小、操作集合等。引入cache层的目的,是为了提高IO效率。它缓存了磁盘上的部分数据,当请求到达时,如果在cache中存在该数据且是最新的,则直接将其传递给用户程序,免除了对底层磁盘的操作。通用块层的主要工作是,接收上层发出的磁盘请求,并最终发出IO请求(BIO)。IO调度层则试图根据设置好的调度算法对通用块层的bio请求合并和排序,回调驱动层提供的请求处理函数,以处理具体的IO请求。驱动层的驱动程序对应具体的物理设备,它从上层取出IO请求,并根据该IO请求中指定的信息,通过向具体块设备的设备控制器发送命令的方式,来操纵设备传输数据。设备层都是具体的物理设备。8 }4 P) J- J+ V% q; p5 D9 f# X
6 ]/ C" S. @" _# \7 l6 J: I
( _6 \3 c8 B/ L: K$ Q8 N
" G5 m% w" |* ~3 b/ g9 K3 G% ~* ZVFS层:
! p( F3 s+ {( s4 ]
# E9 F/ X6 N6 G' ^) G' [ V8 t内核函数sys_read是read系统调用在该层的入口点。
: n5 N7 T5 N2 D( ~) M2 d% q% P% ]" R) B* F% q/ ^! P, ?
它根据文件fd指定的索引,从当前进程描述符中取出相应的file对象,并调用vfs_read执行文件读取操作。" g- h9 Y5 I& V, d \) n6 B7 S
+ p4 P9 }( Q# ]vfs_read会调用与具体文件相关的read函数执行读取操作,file->f_op.read。
% }" |; C) V% b+ T6 P1 M
4 t( `5 d$ m4 ?8 ^+ ?* E4 e" I3 @然后,VFS将控制权交给了ext2文件系统。(ext2在此作为示例,进行解析)" Q( n ]- @6 Z! J# v
4 w+ J5 _# M; T8 ]* u' @& T3 w( f; w" T2 }1 ]0 U
$ r6 ~8 B$ s6 z& i
Ext2文件系统层的处理
; c; O* I4 F; _- a, n" s8 p' i/ N# w/ a X
通过ext2_file_operations结构知道,上述函数最终会调用到do_sync_read函数,它是系统通用的读取函数。所以说,do_sync_read才是ext2层的真实入口。* f% A# o! e+ ^) |9 _
, b! c" |7 C( F O6 ^" E1 [
该层入口函数 do_sync_read 调用函数 generic_file_aio_read ,后者判断本次读请求的访问方式,如果是直接 io (filp->f_flags 被设置了 O_DIRECT 标志,即不经过 cache)的方式,则调用 generic_file_direct_IO 函数;如果是 page cache 的方式,则调用 do_generic_file_read 函数。它会判断该页是否在页高速缓存,如果是,直接将数据拷贝到用户空间。如果不在,则调用page_cache_sync_readahead函数执行预读(检查是否可以预读),它会调用mpage_readpages。如果仍然未能命中(可能不允许预读或者其它原因),则直接跳转readpage,执行mpage_readpage,从磁盘读取数据。
" [# r% k) N) p% l
# K, M% ~( N7 k* ~! e! b在mpage_readpages(一次读多个页)中,它会将连续的磁盘块放入同一个BIO,并延缓BIO的提交,直到出现不连续的块,则直接提交BIO,再继续处理,以构造另外的BIO。) c; V: e/ O ?, d
/ N! `4 ?/ }6 v+ G1 D
2 X, u& U3 i2 i# J8 }6 s! Z1 U$ O: |2 w* ^2 G9 e5 p8 }
文件的 page cache 结构 `( s8 w" [# a! F0 f j& d5 W
& A7 z) d0 e, q! @- \图5显示了一个文件的 page cache 结构。文件被分割为一个个以 page 大小为单元的数据块,这些数据块(页)被组织成一个多叉树(称为 radix 树)。树中所有叶子节点为一个个页帧结构(struct page),表示了用于缓存该文件的每一个页。在叶子层最左端的第一个页保存着该文件的前4096个字节(如果页的大小为4096字节),接下来的页保存着文件第二个4096个字节,依次类推。树中的所有中间节点为组织节点,指示某一地址上的数据所在的页。此树的层次可以从0层到6层,所支持的文件大小从0字节到16 T 个字节。树的根节点指针可以从和文件相关的 address_space 对象(该对象保存在和文件关联的 inode 对象中)中取得(更多关于 page cache 的结构内容请参见参考资料)。
R% q% H' I9 F( y
; X5 q* r1 _; r: ^, m
; m* i3 C8 h X; n
1 [! o, O% A2 k% P# K; X! i: G& ~' Impage处理机制就是page cache层要处理的问题。
- R. j% Q: C" x9 w0 I$ y; y# L5 u1 V* d6 S
# V; `7 H6 S! Q& R7 c8 f9 O
3 f( h0 z* S" \: Z
通用块层 X& r4 T G* H/ _3 W! P/ e
) x" f. T! i: D' l5 y6 y' `: E9 y( r/ N在缓存层处理末尾,执行mpage_submit_bio之后,会调用generic_make_request函数。这是通用块层的入口函数。4 u/ L6 W4 s5 N$ p7 D/ f& O( g
, w! Y' j' A4 ?: k+ J, I它将bio传送到IO调度层进行处理。
7 K& W2 E$ L9 a' h% w. l
6 Y0 O: h/ f) ~5 h7 c6 d! M# d5 V
2 ]6 l+ v r Q: ^+ ^" r
+ Y( D, r! c3 C6 P/ X0 PIO调度层
, j. _0 |1 S, O2 Q
4 F2 ?3 k$ F P3 d P: f+ b5 R* C对bio进行合并、排序,以提高IO效率。然后,调用设备驱动层的回调函数,request_fn,转到设备驱动层处理。
% [+ c* p, C/ o/ l5 z5 Q7 K, K. j, u$ v
0 r. [ m( v! F2 E- K5 u9 G( [
, C( j% y/ F+ l6 Q X设备驱动层' [* {4 h, u* h9 v+ @$ v8 m1 y- ~
4 d3 |. L1 c# rrequest函数对请求队列中每个bio进行分别处理,根据bio中的信息向磁盘控制器发送命令。处理完成后,调用完成函数end_bio以通知上层完成。: `' m& k/ J" I2 ^! ^; R# d5 P
; a1 J" H+ a$ D$ V/ ?/ V* a+ o$ f, n: T5 v" `' C. F
/ @2 S( Y( o- L, T+ K
; i7 @! G4 q& H8 B |
|