Linux内核模块文件读写问题:内核线程执行时异常
内核线程中执行文件读写的路径问题分析与解决
首先得说,你遇到的这个问题核心在于内核线程和模块初始化函数(__init)的运行环境不一样,尤其是当前工作目录的差异。
问题根源
当你在__init函数里执行文件操作时,此时内核是在响应用户空间的insmod/modprobe命令,它会继承用户执行该命令时的当前工作目录——也就是你的.ko文件所在的目录,所以直接写test.txt会在这个目录下创建/更新文件。
但内核线程(kthread)是独立运行在内核态的执行流,它的默认当前工作目录是根目录(/),而不是你加载模块时的用户目录。这就导致你在kthread里写test.txt时,文件其实被创建到了根目录下,而不是你预期的.ko所在目录,看起来像是“没生效”。
解决方案
这里给你两个可行的处理方式:
1. 使用绝对路径(最稳妥)
直接在代码里指定文件的完整绝对路径,从根源上避免工作目录的影响:
struct file *file = filp_open("/home/your-user/path/to/test.txt", O_RDWR | O_CREAT, 0644); if (IS_ERR(file)) { // 处理打开失败的情况 return PTR_ERR(file); } // 后续执行kernel_read/kernel_write等操作 filp_close(file, NULL);
2. 保存模块加载时的工作目录,线程中复用
如果你必须用相对路径,可以在__init函数里先获取当前工作目录的路径并保存,内核线程里再用这个路径拼接文件名。示例代码如下:
static char *module_work_dir = NULL; static int __init my_module_init(void) { struct path pwd; char *buf; // 获取模块加载时的当前工作目录 get_fs_pwd(current->fs, &pwd); buf = (char *)__get_free_page(GFP_KERNEL); if (!buf) { return -ENOMEM; } // 将路径复制到缓冲区,保存供线程使用 module_work_dir = d_path(&pwd, buf, PAGE_SIZE); // 注意:不同内核版本的路径获取接口可能有差异,需按需调整 return 0; } static int my_kthread_func(void *data) { char file_path[256]; struct file *file; // 拼接保存的工作目录和目标文件名 snprintf(file_path, sizeof(file_path), "%s/test.txt", module_work_dir); file = filp_open(file_path, O_RDWR | O_CREAT, 0644); if (IS_ERR(file)) { return PTR_ERR(file); } // 执行读写操作... filp_close(file, NULL); return 0; }
注意:要记得在模块退出时释放分配的内存,避免内存泄漏。
额外提醒
- 内核态文件操作一定要严格检查返回值:比如
filp_open可能返回错误指针,必须先判断IS_ERR(file)再继续。 - 务必使用
kernel_read/kernel_write进行读写,不要直接调用用户态的read/write函数。 - 内核线程中执行文件IO要警惕死锁:不要在持有自旋锁等不可睡眠锁的情况下执行文件操作,因为文件系统操作可能会触发睡眠。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

