【问题标题】:User space buffer and Kernel buffer用户空间缓冲区和内核缓冲区
【发布时间】:2015-11-10 12:22:35
【问题描述】:

我最近正在研究 linux 中的文件系统。我了解到,当我们调用 fopen() 时,库调用将调用 malloc() 为 FILE 结构分配空间,并且在这个 FILE 结构内部将有一个用于 I/0 的缓冲区。但是后来我发现write系统调用实际上是把数据写入内核缓冲区,那么这两个缓冲区有什么区别呢?

【问题讨论】:

  • 别介意,你得先读一本书。
  • 我确实有一本书,它是高级 UNIX 编程。只是想把事情弄清楚

标签: c linux buffer


【解决方案1】:

你必须明白两件事:fwrite() 是标准库的例程在FILE 结构上运行,而write() 是系统调用。我打赌fwrite() 在内部使用write()。没有什么可以阻止 fwrite() 提供用户空间 IO 缓冲,直到它准备好将您的数据传递给 write() 系统调用。

write() syscall 直接进入内核并说:“嘿内核,我这里有这个用户空间缓冲区。你能帮我把这个写入存储吗?”。这取决于内核接下来要做什么:它要么直接去存储写入数据,要么很可能将数据复制到内核缓冲区,直到它决定是时候修改存储数据为止。

回到你的问题。进行任何类型的缓冲以累积数据以推迟转向更昂贵的操作:标准库可能会考虑在每个 len-byte 上调用 syscall 昂贵,内核认为在每个 syscall 上都去硬盘昂贵等等。

您可能想阅读这篇文章以了解缓冲能走多远https://fgiesen.wordpress.com/2015/10/25/reading-and-writing-are-less-symmetric-than-you-probably-think/

【讨论】:

  • 那么库函数有自己的缓冲区还是在FILE结构中?
  • 我猜它在FILE 结构中。看,库在每个文件的基础上缓冲 IO。为了完成每个文件的工作,它为应用程序提供了一些不透明的FILE * 文件句柄,这样当您转到库的例程时,您将传递该句柄。这个句柄告诉例程的所有内容,后者必须知道才能完成它的工作(包括缓冲)。
【解决方案2】:

FILE 结构包含有关打开文件的数据(模式、流位置等)。它是 C 标准 I/O 接口的一部分。 作为FILE 的一部分分配的缓冲区只占用有限数量的数据(例如,当流被缓冲时)。它在fclose() 上被释放。您甚至可以使用 setvbuf() 提供您自己的用户空间 stdio 缓冲区。

内核缓冲区接收write()写入的文件内容,无论何时刷新流或关闭关联的文件描述符。

【讨论】:

  • 这是否意味着如果流被缓冲,数据首先写入用户空间缓冲区,然后写入内核空间缓冲区?但是如果流没有被缓冲,例如stderr,这是否意味着输出直接进入错误消息并且甚至没有存储在内核缓存中?
  • @lplouis 是的,如果流被缓冲,它首先进入FILE 缓冲区。这就是重点:避免昂贵的系统调用只占用少量字节。如果它是无缓冲的,则任何操作都直接转到 read() 或 write()。后一种是您通常需要的诊断消息:一旦出现问题,您希望得到通知。
【解决方案3】:

FILE 结构包含有关打开文件的信息。this defines the FILE struct members。但是在内核级别,inodebuffer cache 访问了一个文件。

数据正在使用copy_to_usercopy_from_user 方法通过缓冲区缓存从用户空间读取/写入磁盘。

【讨论】:

    【解决方案4】:

    这两个缓冲区有很大的区别,一个是kernel缓冲区,另一个是user缓冲区。因此,当您执行 I/O 时,基本上发生的事情是将用户空间的缓冲区复制到内核空间的缓冲区中。函数copy_from_user() 执行此任务。

    现在出现的问题是,当内核可以访问用户空间时,为什么我们需要两个缓冲区?原因是内核不想直接读取用户缓冲区,因为内核和用户空间都有不同的地址空间,因此用户空间中的有效地址可能不是内核中的有效地址。

    在内核中,如果访问了一个无效的地址,那么系统将立即崩溃,因此函数copy_from_user 执行映射用户空间地址和内核空间地址的任务,并检查该地址是否可访问。如果不是,那么它只是返回EFAULT(错误地址)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-26
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多