2010-11-09 644 views
5

根据x86和ppc上的linux设计,4g虚拟地址空间被划分为3:1。 用户虚拟地址是3g。为什么需要copy_to/from_user?

现在,如果用户应用程序做了一个ioctl传递指针到缓冲区,内核模块,可以直接做一个memcpy,我试过,它的工作。 =>为什么我们需要一个copy_to/copy_from用户。

注意:如果页面被换出,内核页面错误处理程序会将其返回,并且它对内核模块不可见。

需要你的想法...评论

回答

9

有几个很好的理由认为copy_to_user/copy_from_user是正确的功能,使用方法:

  • 在某些架构上简单memcpy()工作,因此使用这些功能允许您的代码在那里工作。我相信即使选择HIGHMEM配置选项的x86也在这艘船上。

  • 这些功能做一个access_ok()检查,以确保真正引用的用户空间地址是真实的用户空间地址。如果您只是执行memcpy(),则ioctl()的调用方可以提供与内核地址重叠的地址范围,这是一个安全漏洞。

  • 但是,主要的原因是要正确处理不良的用户地址。如果您仅使用memcpy(),则未处理的故障将导致内核哎呀。用户访问功能使用"fixup" mechanism,它允许处理故障(读或写很短,在这种情况下,通常EFAULT返回给用户空间)。

+0

好的,所以主要原因是处理**坏**地址。 – mSO 2010-11-09 10:22:50

+0

,如果地址有效(比如说最好的情况,没有人做任何恶作剧),memcpy应该可以工作。 – mSO 2010-11-09 10:24:04

+0

@Manish:这不一定是“恶作剧”,它可能只是用户空间中一个普通的旧bug - 这些bug应该由内核优雅地处理。而'memcpy()'只能在一些体系结构上运行。 – caf 2010-11-09 21:57:39

0

你很幸运,它的工作。

用户空间和内核空间在完全不同的地址空间中运行。当您copy_to_user时,内核会将用户空间虚拟地址转换为真实物理地址并将数据复制到那里。反过来也会发生类似的过程。

如果您的硬件支持分散/聚集DMA,则可以直接跳过复制到/从步骤直接复制。在这里,您可以将连续的虚拟内存块映射到一系列物理页面中,然后使用该信息直接将DMA写入用户空间。当然,如果任何虚拟地址空间当前没有映射到物理内存(认为交换或文件支持的mmaps),这会产生复杂性。

+0

3g:1g拆分应该照顾到这一点。 AFAIK内核不需要将va转换成pa进行复制。 – mSO 2010-11-09 10:25:09