-
进程写文件(使用缓冲 IO)过程中,写一半的时候,进程发生了崩溃,已写入的数据会丢失吗?
-
不会的
-
进程在执行 write (使用缓冲 IO)系统调用的时候,实际上是将文件数据写到了内核的 page cache,它是文件系统中用于缓存文件数据的缓冲
-
即使进程崩溃了,文件数据还是保留在内核的 page cache
-
读数据的时候,也是从内核的 page cache 读取,因此还是依然读的进程崩溃前写入的数据。
-
内核会找个合适的时机,将 page cache 中的数据持久化到磁盘。
-
如果 page cache 里的文件数据,在持久化到磁盘化到磁盘之前,系统发生了崩溃,那这部分数据就会丢失了。
-
可以在程序里调用 fsync 函数,在写文文件的时候,立刻将文件数据持久化到磁盘,这样就可以解决系统崩溃导致的文件数据丢失的问题。
-
-
Page Cache
-
可见 Page Cache 的本质是由 Linux 内核管理的内存区域。
-
通过 mmap 以及 buffered I/O 将文件读取到内存空间实际上都是读取到 Page Cache 中。
-
page与page cache
-
page 是内存管理分配的基本单位
-
Page Cache 由多个 page 构成。
-
page 在操作系统中通常为 4KB 大小(32bits/64bits),而 Page Cache 的大小则为 4KB 的整数倍。
-
并不是所有 page 都被组织为 Page Cache。
-
为什么 Linux 不把 Page Cache 称为 block cache,这不是更好吗?
-
因为从磁盘中加载到内存的数据不仅仅放在 Page Cache 中,还放在 buffer cache 中。
-
-
Linux 系统上供用户可访问的内存分为两个类型
-
File-backed pages:文件备份页也就是 Page Cache 中的 page,对应于磁盘上的若干数据块;对于这些页最大的问题是脏页回盘;
-
Anonymous pages:匿名页不对应磁盘上的任何磁盘数据块,它们是进程的运行是内存空间(例如方法栈、局部变量表等属性);
-
-
-
swap与缺页中断
-
Swap 机制指的是当物理内存不够用,内存管理单元(Memory Mangament Unit,MMU)需要提供调度算法来回收相关内存空间,然后将清理出来的内存空间给当前内存申请方。
-
Swap 机制存在的本质原因是 Linux 系统提供了虚拟内存管理机制
-
每一个进程认为其独占内存空间
-
因此所有进程的内存空间之和远远大于物理内存
-
所有进程的内存空间之和超过物理内存的部分就需要交换到磁盘上。
-
操作系统以 page 为单位管理内存
-
当进程发现需要访问的数据不在内存时,操作系统可能会将数据以页的方式加载到内存中。被称为缺页中断
-
当操作系统发生缺页中断时,就会通过系统调用将 page 再次读到内存中。
-
主内存的空间是有限的,当主内存中不包含可以使用的空间时,操作系统会从选择合适的物理内存页驱逐回磁盘,为新的内存页让出位置
-
选择待驱逐页的过程在操作系统中叫做页面替换,替换操作又会触发 swap 机制。
-
Swap 在这种情况下还是有一定优势
-
对于有发生内存泄漏几率的应用程序(进程),Swap 交换分区更是重要,这可以确保内存泄露不至于导致物理内存不够用,最终导致系统崩溃。
-
内存泄露会引起频繁的 swap,此时非常影响操作系统的性能。
-
-
Linux 通过一个 swappiness 参数来控制 Swap 机制:这个参数值可为 0-100,控制系统 swap 的优先级:
-
高数值:较高频率的 swap,进程不活跃时主动将其转换出物理内存。
-
低数值:较低频率的 swap,这可以确保交互式不因为内存空间频繁地交换到磁盘而提高响应延迟。
-
-
为什么 SwapCached 也是 Page Cache 的一部分?
-
因为当匿名页(Inactive(anon) 以及 Active(anon))先被交换(swap out)到磁盘上后,然后再加载回(swap in)内存中,由于读入到内存后原来的 Swap File 还在,所以 SwapCached 也可以认为是 File-backed page,即属于 Page Cache
-
-
-
Page cache与buffer cache
-
Page Cache 用于缓存文件的页数据,buffer cache 用于缓存块设备(如磁盘)的块数据。
-
页是逻辑上的概念,因此 Page Cache 是与文件系统同级的;
-
块是物理上的概念,因此 buffer cache 是与块设备驱动程序同级的。
-
-
Page Cache 与 buffer cache 的共同目的都是加速数据 I/O:
-
写数据时首先写到缓存,将写入的页标记为 dirty,然后向外部存储 flush,也就是缓存写机制中的 write-back(另一种是 write-through,Linux 默认情况下不采用);
-
读数据时首先读取缓存,如果未命中,再去外部存储读取,并且将读取来的数据也加入缓存。操作系统总是积极地将所有空闲内存都用作 Page Cache 和 buffer cache,当内存不够用时也会用 LRU 等算法淘汰缓存页。
-
-
2.4 版本内核之后,两块缓存近似融合在了一起:如果一个文件的页加载到了 Page Cache,那么同时 buffer cache 只需要维护块指向页的指针就可以了。
-
现在提起 Page Cache,基本上都同时指 Page Cache 和 buffer cache 两者,本文之后也不再区分,直接统称为 Page Cache。
-
Page Cache 中的每个文件都是一棵基数树(radix tree,本质上是多叉搜索树),树的每个节点都是一个页。根据文件内的偏移量就可以快速定位到所在的页
-
-
Page Cache与预读
-
基于 Page Cache 的读缓存机制提供预读机制
-
-
Page cache 与 文件持久化的一致性可靠性
-
任何系统引入缓存,就会引发一致性问题:内存中的数据与磁盘中的数据不一致
-
文件 = 数据 + 元数据
-
元数据用来描述文件的各种属性,也必须存储在磁盘上。
-
保证文件一致性其实包含了两个方面:数据一致+元数据一致。
-
文件的元数据包括:文件大小、创建时间、访问时间、属主属组等信息。
-
如果发生写操作并且对应的数据在 Page Cache 中,那么写操作就会直接作用于 Page Cache 中,此时如果数据还没刷新到磁盘,那么内存中的数据就领先于磁盘,此时对应 page 就被称为 Dirty page。
-
-
两种方式实现文件一致性
-
Write Through(写穿):向用户层提供特定接口,应用程序可主动调用接口来保证文件一致性;
-
Write back(写回):系统中存在定期任务(表现形式为内核线程),周期性地同步文件系统中文件脏数据块,这是默认的 Linux 一致性方案;
-
-
Write Through 与 Write back 在持久化的可靠性上有所不同:
-
Write Through 以牺牲系统 I/O 吞吐量作为代价,向上层应用确保一旦写入,数据就已经落盘,不会丢失;
-
Write back 在系统发生宕机的情况下无法确保数据已经落盘,因此存在数据丢失的问题。
-
-
-
-
Page cache 的劣势
-
最直接的缺点是需要占用额外物理内存空间,物理内存在比较紧俏的时候可能会导致频繁的 swap 操作,最终导致系统的磁盘 I/O 负载的上升。
-
另一个缺陷是对应用层并没有提供很好的管理 API,几乎是透明管理。
-
最后一个缺陷是在某些应用场景下比 Direct I/O 多一次磁盘读 I/O 以及磁盘写 I/O。
-
Direct I/O 即直接 I/O。
-
缓存文件 I/O:用户空间要读写一个文件并不直接与磁盘交互,而是中间夹了一层缓存,即 page cache;
-
直接文件 I/O:用户空间读取的文件直接与磁盘交互,没有中间 page cache 层;
-
“直接”在这里还有另一层语义:其他所有技术中,数据至少需要在内核空间存储一份,但是在 Direct I/O 技术中,数据直接存储在用户空间中,绕过了内核。
-
-
Direct I/O 的读写非常有特点:
-
Write 操作:由于其不使用 page cache,所以其进行写文件,如果返回成功,数据就真的落盘了(不考虑磁盘自带的缓存);
-
Read 操作:由于其不使用 page cache,每次读操作是真的从磁盘中读取,不会从文件系统的缓存中读取。
-
-
-
-
进程写文件的时候,如果进程突然崩溃了,写入的内容是否会丢失呢?
最新推荐文章于 2024-09-29 15:36:45 发布
文章探讨了进程在使用缓冲IO写文件时,如果中途崩溃,数据是否会丢失。指出数据通常暂存于内核的PageCache,除非进程崩溃前未调用fsync,否则数据不会丢失。同时讨论了PageCache、buffercache、WriteThrough和Writeback在一致性处理上的差异,以及PageCache的优缺点和与DirectI/O的区别。
摘要由CSDN通过智能技术生成