copy_from_user 和分段

4 c linux linux-kernel

我正在阅读“ The Linux Kernel Module Programming Guide ”中的一段,我对以下段落有一些疑问。

copy_from_user 或 get_user 的原因是 Linux 内存(在 Intel 架构上,在某些其他处理器下可能不同)是分段的。这意味着指针本身并不引用内存中的唯一位置,仅引用内存段中的位置,您需要知道它是哪个内存段才能使用它。内核有一个内存段,每个进程有一个内存段。

然而,我的理解是 Linux 使用分页而不是分段,并且 0xc0000000 及以上的虚拟地址具有内核映射。

  1. 我们是否使用 copy_from_user 来适应旧内核?
  2. 当前的 linux 内核是否以任何方式使用分段?如果是这样怎么办?
  3. 如果 (1) 不正确,使用 copy_from_user 还有其他好处吗?

Gil*_*ton 5

是的。我也不喜欢这种解释。从技术意义上讲,细节基本上是正确的(另请参阅为什么 x86 上的 Linux 对用户进程和内核使用不同的段?)但正如您所说,linux 通常映射内存以便内核代码可以直接访问它,所以我不不认为这是对为什么copy_from_user等实际存在的一个很好的解释。

海事组织,主要使用原因copy_from_user/ copy_to_user(朋友)很简单,就是有要查了大量的东西(危害到被防御),并且是有意义的把所有这些检查在同一个地方。您不希望每个需要从用户空间复制数据进出的地方都必须重新实施所有这些检查。特别是当细节可能因一种架构而异于另一种架构时。

例如,当您需要复制到该内存或从该内存复制时,实际上可能不存在用户空间页面,因此从可以容纳页面错误的上下文中进行调用很重要(因此被置于睡眠状态) )。

此外,需要仔细检查用户空间数据指针,以确保它们实际上指向用户空间并指向数据区域,并且副本长度不会超出有效区域的末尾,等等.

最后,用户空间实际上可能与内核共享相同的页面映射。曾经有一个 32 位 x86 的 linux 补丁,它使用户空间进程可以使用完整的 4G 虚拟地址空间。在这种情况下,内核代码无法假设用户空间指针可以直接访问,并且这些函数可能需要一次映射单个用户空间页面才能访问它们。(请参阅4GB/4GB 内核 VM 拆分