【问题标题】:How to mmap a file inside the linux kernel?如何在 linux 内核中映射文件?
【发布时间】:2018-01-26 11:45:01
【问题描述】:

我正在使用 linux 内核中的 kprobes 挂钩一些系统调用。在此期间,我想使用mmap 读取文件。

无法在内核内部使用系统调用,但通常有其他方法可以绕过它。 (例如 sys_openvfs_read)。

这可能吗?如果可以,怎么做?

【问题讨论】:

  • mmap 在调用进程的虚拟地址空间中创建一个新映射,因为我们在内核中没有任何进程,所以让它工作起来真的很棘手。另一方面,为什么不直接在内核中打开并读取它(filp_open/vfs_read)?
  • static int file_write(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size) { mm_segment_t oldfs;诠释; oldfs = get_fs(); set_fs(get_ds()); ret = vfs_write(文件、数据、大小、&offset); set_fs(oldfs);返回 ret; } static int file_read(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size) { mm_segment_t oldfs;诠释; oldfs = get_fs(); set_fs(get_ds()); ret = vfs_read(file, (void __force __user *)data, size, &offset); set_fs(oldfs);返回 ret; }
  • 如果我正确理解了内核的内部工作原理,那么就会有一个进程,因为我正在挂钩系统调用。所以我所有的代码都在一个进程中运行。感谢您的代码。 vfs_read 确实是一个替代方案,但mmap'ed 文件可以更好地与我现有的代码一起使用,并且我可以避免复制一些内存。
  • 为了我的澄清,内核 mmap/filp_open 会返回一个位于内核空间的指针,如何避免复制一些内存?
  • 只是又想了一个办法(我没试过,但很好奇它是否有效!),在内核中分配一些物理内存,然后将其传递给 do_mmap() 并检查返回值,如果成功,请不要使用返回的地址,而是使用您为 do_mmap() 调用传递的地址来访问文件。唯一的缺点是如果文件很大,你将不得不分配大的物理内存。

标签: linux kernel memory-mapping


【解决方案1】:

据我了解,mmap() 的功能无法从内核空间使用。

虽然可以成功调用do_mmap() 或类似函数,但该函数返回用户空间地址内核不能直接使用。从内核访问用户空间内存的唯一正确方法是copy_to_user/copy_from_user。但是使用这些函数意味着复制,所以mmap()(与read()相比)的优势就丧失了。


为了在内核中使用read() 的功能,set_fs(KERNEL_DS) 技术可用于屏蔽指向内核空间的指针,传递给此函数,作为指向用户空间的指针,所以copy_to_user 可以正常工作。

但是对于mmap() 有一个相反的问题:他需要使用从函数返回的用户空间指针,就像使用指向内核空间的指针一样。而这用正常的方法是做不到的。

尝试取消引用指向尚未映射的用户空间区域的指针可能会使内核崩溃。而大多数mmap() 的实现实际上返回了未映射的内存,这是为了在第一个页面错误时被映射。

【讨论】:

  • 是的,mmap 接受一个 int 作为文件描述符,而内核没有这样的选项。您要打开的文件作为结构返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-15
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多