我最近在学习Linux文件系统。我了解到,当我们调用fopen()函数时,库函数会调用malloc()函数为FILE结构体分配空间,在这个FILE结构体中会有一个I/O缓冲区。但后来我发现,写入系统调用实际上是将数据写入内核缓冲区,那么这两个缓冲区有什么区别呢?
fwrite()
是一个操作FILE
结构的标准库例程,而write()
是一个系统调用。我打赌fwrite()
在内部使用write()
。没有什么能阻止fwrite()
提供用户空间IO缓冲,直到它准备好将你的数据传递给write()
系统调用。
write()
系统调用直接进入内核并说:“嘿,内核,我有一个用户空间缓冲区在这里。你能写入存储器吗?” 对于内核来说,接下来该做什么取决于内核:它要么直接访问存储器以写入数据,要么(最有可能的情况)将数据复制到内核缓冲区,直到它决定修改存储器数据为止。len
字节时调用系统调用,内核则认为在每次系统调用时访问硬盘是昂贵的等等。FILE
结构体中。注意,库缓冲IO是基于每个文件的。为了执行其每个文件的工作,它会提供一些不透明的FILE *
文件句柄给应用程序,这样当您调用库函数时,需要将该句柄传入。此句柄向例程指示了执行任务所需知道的一切(包括缓冲)。 - Igor S.K.FILE
结构保存了已打开文件的元数据(模式、流位置等)。它是C标准I/O接口的一部分。
作为FILE
的一部分分配的缓冲区仅包含有限量的数据(例如,当流被缓冲时)。它在fclose()
时被释放。您甚至可以使用setvbuf()
提供自己的用户空间stdio缓冲区。
内核缓冲区接收由write()
写入的文件内容,每当流被刷新或相关联的文件描述符关闭时。
FILE
缓冲区。这就是整个目的:避免仅为少量字节而进行昂贵的系统调用。如果未缓冲,则任何操作都直接进入read()或write()。后者通常用于诊断消息:您希望尽快得到有关出现问题的信息。 - Jens两个缓冲区之间有很大的区别,一个是内核
缓冲区,另一个是用户
缓冲区。因此,当进行I/O操作时,基本上是将用户空间中的缓冲区复制到内核空间中的缓冲区。函数copy_from_user()
执行此任务。
现在出现的问题是,既然内核可以访问用户空间,为什么我们需要两个缓冲区呢?原因是内核不想直接读取用户缓冲区,因为内核和用户空间具有不同的地址空间,因此用户空间中的有效地址可能不是内核中的有效地址。
如果在内核中访问了非有效地址,则系统会立即崩溃,因此函数copy_from_user
执行映射用户空间地址和内核空间地址的任务,并检查地址是否可访问。如果不可访问,则简单地返回EFAULT
(错误地址)。
FILE 结构保存了有关已打开文件的信息。 这定义了 FILE 结构成员。但在内核级别,文件是通过 inode,缓存缓冲区 访问的。
使用方法 copy_to_user 和 copy_from_user ,数据通过缓冲缓存从用户空间读取/写入磁盘。