image.png
缓存IO:大多数文件系统使用缓存IO,对于读操作来讲,操作系统会先检查,内核的缓冲区有没有需要的数据。如果已经缓存了,那就直接从缓存中返回;否则从磁盘中读取,然后缓存在操作系统的缓存中。对于写操作来讲,操作系统会先将数据从用户空间复制到内核空间的缓存中。这时对用户程序来说,写操作就已经完成。至于什么时候再写到磁盘中由操作系统决定,除非显式地调用了 sync 同步命令。
直接IO:就是应用程序直接访问磁盘数据,而不经过内核缓冲区,从而减少了在内核缓存和用户程序之间数据复制。
-
write 过程
- 调用 genric_perform_write 它里面是一个循环,每次写入对应的页
-
调用 write_begin 对系统进行初始化工作,主要是ext4_journal_start 即日志文件系统准备,然后调用grab_cache_page_write 获取需要写入的缓存页
-
日志系统模式:
- jnuranl模式:这种模式在将数据写入文件系统前,必须等待元数据和数据的日志已经落盘才能发挥作用。这样性能比较差,但是最安全。
- order 模式:这个模式不记录数据的日志,只记录元数据的日志,但是在写元数据的日志前,必须先确保数据已经落盘。这个折中,是默认模式。
- writeblack模式:不记录数据的日志,仅记录元数据的日志,并且不保证数据比元数据先落盘。这个性能最好,但是最不安全。 -
iov_iter_copy_form_user_atmoic 即通过kmap_atomic 映射内核虚拟地址,然后将用户态数据拷贝到内核态。再使用kumap_atmoic 删除映射
-
- ext4_write_end 结束日志写入,将数据写入缓存。
- balance_dirty_pages_ratelimited 查看脏页数量是否超过限制
-
脏页写入内存情况:
用户主动调用 sync,将缓存刷到硬盘上去,最终会调用 wakeup_flusher_threads,同步脏页;
当内存十分紧张,以至于无法分配页面的时候,会调用 free_more_memory,最终会调用 wakeup_flusher_threads,释放脏页;
脏页已经更新了较长时间,时间上超过了 timer,需要及时回写,保持内存和磁盘上数据一致性。
- 调用 genric_perform_write 它里面是一个循环,每次写入对应的页
-
read 过程
- genric_file_buffer_read 直接查看page cache是否有缓存,假如不存在,然后读入该页,并进行预读。
- copy_page_to_iter 将内容从内核态复制到用户态。
网友评论