如何在 linux 设备驱动程序中避免 copy_from_user 和 copy_to_user

How to avoid copy_from_user and copy_to_user in linux device driver

我正在编写一个设备驱动程序,它使用字符设备文件从用户 space 缓冲区复制数据,该缓冲区是使用 malloc 分配给内核缓冲区的。当前使用 copy_from_user api 将用户数据复制到内核缓冲区。试图找到一种方法来避免用户和内核之间的数据复制 spaces。有什么方法可以在不使用 copy_from_user 的情况下访问内核 space 中的用户 space 缓冲区(由 malloc 分配)?

让我们先回答您提出的问题。是的,您可以从内核访问用户 space 分配的内存。我不确定如何操作的技术细节,但是如果您的内核代码在调用线程的上下文中运行,则可以简单地使用提供给您的用户 space 指针。

但是请不要那样做。

你不应该这样做的原因是如果用户 space 指针错误,或者内存太短,或者存在任何其他问题,用户 space 进程可能需要因分段错误而崩溃。可悲的是,你不是 运行 用户 space 代码,你是 运行 内核 space。内核段错误相当于内核恐慌。不要将这种情况强加给您的用户。

更好的方法是使用一种机制,用户space写入一次数据,然后字符设备就可以简单地使用它。让用户 space mmap 在评论中提到该页面。一种可能更符合文件描述符工作方式标准的方法是在设备的文件操作结构中实现 splice_read

现在,splice 不是一个容易使用的界面,但主要优点是,如果您的源也支持 splice,则用户可以将数据直接从源传递到您的驱动程序,而无需通过用户 space.

如果您想保存副本,我建议您使用其中一种解决方案。同样,不要 直接访问用户提供的指针,除非您知道自己在做什么。

get_user_pages() API可以用来固定用户页从物理内存中换出,内核可以通过访问相应虚拟地址的物理页来访问该内存区域。