前言

做存储开发,一定会经常涉及到 IO 相关的操作。而现在的高级编程语言,往往会帮助我们屏蔽 IO 操作的底层细节,虽然这样能降低开发门槛,提升效率,但是却也导致我们对 IO 底层操作实现的理解不够系统和深入。 所以呢,我一直想抽时间来系统整理一下 Linux IO 涉及的系统调用,以及相互之间的区别和联系,以加深对 IO 操作的理解。

IO 操作

fwrite

fwrite 是 c 语言标准库中的文件写入函数,其作用是向指定的文件中写入若干数据。调用 fwrite 实际上是将数据写入到了 c 标准库的 IO Buffer 中。

mmap

mmap 将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap 在用户空间映射调用系统中作用很大。

fflush

fflush 就是将 c 标准库中的 IO Buffer 中的数据写入到参数 stream 指定的文件中。

fsync

fsync 系统调用就是将内核缓冲区中的数据同步到存储介质(如硬盘)。也可以在 open 文件的时候通过开启O_SYNC来开启同步 I/O.

各 IO 操作的区别与联系

图片引用自 https://oscimg.oschina.net/oscnet/51a17cc9aa34eba47971af609fdecabf398.jpg

图片引用自 https://oscimg.oschina.net/oscnet/51a17cc9aa34eba47971af609fdecabf398.jpg

上图非常清晰的展示了 Linux IO 操作相互之间的区别和联系。

  1. fwrite 写入的数据会先存放到 c 标准库的 IO Buffer 中,可以通过 fflush 将其写入到内核的 Page Buffer 中。也就是说即使 fwrite 写成功,程序崩溃了数据仍然可能会丢失。
  2. fflush 就是将程序 IO Buffer 中的数据写入到内核的 Page Buffer,此时应用程序的崩溃不会导致数据丢失,但是如果内核崩溃的话,仍然可能会造成数据丢失。
  3. 通过 mmap 映射的文件,数据直接写入到内核的 Page Buffer 中。
  4. fsync 可以将内核 Page Buffer 中的数据写入到存储介质的 Disk Cache 中。

参考资料

Linux 中如何保证数据安全落盘