Linux 文件I/O
一、多次打开同一个文件
- 一个进程内多次 open 打开同一个文件,那么会得到多个不同的文件描述符 fd,同理在关闭文件的时候也需要调用 close 依次关闭各个文件描述符。
- 一个进程内多次 open 打开同一个文件,在内存中并不会存在多份动态文件。
- 一个进程内多次 open 打开同一个文件,不同文件描述符所对应的读写位置偏移量是相互独立的,是分别写(各从各的位置偏移量开始写)。
- 多个不同的进程中调用 open()打开磁盘中的同一个文件,同样在内存中也只是维护了一份动态文件,多个进程间共享,它们有各自独立的文件读写位置偏移量。
二、文件接续写
- 如果 open 函数携带了 O_APPEND 标志,调用 open 函数打开文件,当每次使用 write()函数对文件进行写操作时,都会自动把文件当前位置偏移量移动到文件末尾,从文件末尾开始写入数据,也就是意味着每次写入数据都是从文件末尾开始。
- dup、dup2 函数用于复制文件描述符,复制得到的文件描述符与原文件描述符都指向同一个文件表,所以它们的文件读写偏移量是一样的,在不使用O_APPEND标志的情况下,可以通过文件描述符复制来实现接续写。
三、I/O缓冲
- read()和 write()系统调用在进行文件读写操作的时候并不会直接访问磁盘设备,而是仅仅在用户空间缓冲区和内核缓冲区(kernel buffer cache)之间复制数据。对于读文件而言,内核会从磁盘设备中读取文件的数据并存储到内核的缓冲区中,当调用 read()函数读取数据时,read()调用将从内核缓冲区中读取数据,直至把缓冲区中的数据读完,这时,内核会将文件的下一段内容读入到内核缓冲区中进行缓存。
- 标准read()和write()所维护的 stdio 缓冲是用户空间的缓冲区,应用程序中通过标准 I/O 操作磁盘文件时,为了减少调用系统调用的次数,标准 I/O 函数会将用户写入或读取文件的数据缓存在 stdio 缓冲区,然后再一次性将 stdio 缓冲区中缓存的数据通过调用系统调用 I/O(文件 I/O)写入到文件 I/O 内核缓冲区或者拷贝到应用程序的 buf 中。
- 直接I/O只在一些特定的需求场合,譬如磁盘速率测试工具、数据库系统等。