内核空间访问字符设备:set_fs()替代方案及跨模块文件交互
内核空间文件交互的两个问题
我已经把问题做了泛化处理,之前社区里有不少关于内核空间中打开/交互文件的讨论,相关实现方法大多诞生于set_fs()被弃用之前。以下是两个具体问题及对应方案:
一、set_fs()弃用后的替代技术
出于好奇,目前有没有能替代set_fs()的技术,来完成之前那些方案里的内核文件操作?
目前内核提供了更安全、无需手动切换地址空间的替代方案:
- 使用封装好的内核文件操作API,比如
kernel_read()、kernel_write(),这些函数已经内置了安全的地址空间处理,不需要手动调用set_fs() - 直接调用
vfs_read()、vfs_write()等VFS层函数,现在内核在调用这些函数时,会自动处理内核态的地址空间上下文,无需手动设置fs结构体 - 对于更复杂的操作,可以使用
file_read_actor()这类回调式函数,或者直接操作struct file对应的f_op接口,只要确保传入的缓冲区是内核地址空间的合法指针即可
二、无导出接口的内核模块间文件通信方案
存在这样的场景:某个内核模块只提供基于文件的接口,没有导出任何其他符号,但另一个内核模块需要和它交互,且无法修改原模块。比如kcov,它通过debugfs文件做IO,核心的struct kcov只存在于filp->private_data中。这种情况下,或许不需要完整执行open等流程,只需获取struct file_operations指针,再构造/获取合适的file/inode/dentry作为参数调用对应函数即可,有没有可行的方案?
可行的思路如下:
- 定位目标文件的内核对象:通过
kern_path()函数传入目标文件的路径(比如kcov的debugfs路径),获取对应的struct path,从中可以拿到dentry和inode对象 - 获取/构造struct file实例:可以使用
filp_open()打开目标文件(当前版本无需set_fs()),得到合法的struct file指针;也可以通过alloc_file()构造文件对象,但需要正确设置inode、f_op等参数,同时注意管理引用计数 - 直接调用文件操作函数:拿到
file->f_op后,可以直接调用其中的read、write、ioctl等函数,传入对应的内核态参数。比如对于kcov,打开文件后filp->private_data就是struct kcov结构体,可直接用于后续交互 - 注意事项:操作过程中要严格管理文件对象的引用计数(用
fput()释放),避免内存泄漏;确保操作在允许的上下文执行(比如部分文件操作不能在中断上下文进行);注意内核版本兼容性,部分函数的参数或行为可能随版本变化
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

