Linux Kernel 5.11.0模块读写文本文件方法及编译报错处理
Linux内核模块读写普通文件编译报错问题说明
需求背景
我需要在Linux内核模块中读取一个txt文件并写入另一个txt文件,查阅资料后发现有filp_read()、kernel_read()、vfs_read()等多种实现方案,但多次尝试都无法完成make编译。
已有提示可执行mv make Makefile修正文件名问题。
现有代码
reverse.c
#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/uaccess.h> static char buf[] ="It's from linux kernel\n"; static char buf1[32]; int __init test_init(void) { struct file *fp; mm_segment_t fs; loff_t pos; printk("test enter\n"); fp =filp_open("/home/j0000/Desktop/file/kernel_file",O_RDWR | O_CREAT,0644); if (IS_ERR(fp)){ printk("create file error\n"); return -1; } fs =get_fs(); set_fs(KERNEL_DS); pos =0; vfs_write(fp,buf, sizeof(buf), &pos); pos =0; vfs_read(fp,buf1, sizeof(buf), &pos); printk("Write contet=%s\n",buf1); filp_close(fp,NULL); set_fs(fs); return 0; } void __exit test_exit(void) { printk("test exit\n"); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL");
Makefile
obj-m :=reverse.o read_userspace-objs:= read_userspace_file.o KVERSION := $(shell uname -r) KDIR := /usr/src/linux-headers-$(KVERSION)/ PWD := $(shell pwd) default: make -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.cmd *.ko *.mod.c .tmp_versions Module.symvers modules.order
报错信息
首次报错
j0000@ubuntu:~/Desktop/file$ make make -C /usr/src/linux-headers-5.11.0-37-generic/ M=/home/j0000/Desktop/file modules make[1]: Entering directory '/usr/src/linux-headers-5.11.0-37-generic' scripts/Makefile.build:44: /home/j0000/Desktop/file/Makefile: No such file or directory make[2]: *** No rule to make target '/home/j0000/Desktop/file/Makefile'. Stop. make[1]: *** [Makefile:1849: /home/j0000/Desktop/file] Error 2 make[1]: Leaving directory '/usr/src/linux-headers-5.11.0-37-generic' make: *** [makefile:8: default] Error 2 j0000@ubuntu:~/Desktop/file$
修正文件名后报错
这类报错我已经遇到很多次了,想请问为什么当前场景下不能使用get_fs和set_fs接口?
j0000@ubuntu:~/Desktop/file$ make make -C /usr/src/linux-headers-5.11.0-37-generic/ M=/home/j0000/Desktop/file modules make[1]: Entering directory '/usr/src/linux-headers-5.11.0-37-generic' CC [M] /home/j0000/Desktop/file/reverse.o /home/j0000/Desktop/file/reverse.c: In function ‘test_init’: /home/j0000/Desktop/file/reverse.c:20:9: error: implicit declaration of function ‘get_fs’; did you mean ‘sget_fc’? [-Werror=implicit-function-declaration] 20 | fs =get_fs(); | ^~~~~~ | sget_fc /home/j0000/Desktop/file/reverse.c:20:9: error: incompatible types when assigning to type ‘mm_segment_t’ {aka ‘struct <anonymous>’} from type ‘int’ /home/j0000/Desktop/file/reverse.c:21:5: error: implicit declaration of function ‘set_fs’; did you mean ‘sget_fc’? [-Werror=implicit-function-declaration] 21 | set_fs(KERNEL_DS); | ^~~~~~ | sget_fc /home/j0000/Desktop/file/reverse.c:21:12: error: ‘KERNEL_DS’ undeclared (first use in this function); did you mean ‘KERNFS_NS’? 21 | set_fs(KERNEL_DS); | ^~~~~~~~~ | KERNFS_NS /home/j0000/Desktop/file/reverse.c:21:12: note: each undeclared identifier is reported only once for each function it appears in cc1: some warnings being treated as errors make[2]: *** [scripts/Makefile.build:288: /home/j0000/Desktop/file/reverse.o] Error 1 make[1]: *** [Makefile:1849: /home/j0000/Desktop/file] Error 2 make[1]: Leaving directory '/usr/src/linux-headers-5.11.0-37-generic' make: *** [Makefile:8: default] Error 2
问题解答
- 首次报错原因:本地的编译配置文件名是小写的
makefile,内核编译脚本默认查找大写的Makefile,执行mv make Makefile即可修复该问题。 get_fs/set_fs相关报错原因:Linux内核从5.10版本开始正式移除了get_fs()、set_fs()接口以及KERNEL_DS宏,旧的通过修改地址空间限制调用vfs读写的方案不再适配高版本内核,你参考的教程是针对旧版本内核编写的,因此会出现未声明的错误。- 修复方案:使用
kernel_read和kernel_write接口替代vfs系列接口,这两个接口专门用于内核空间直接操作文件,不需要手动调整地址空间限制,天然支持内核虚拟地址作为缓冲区,适配5.10及以上版本内核。
修改后的核心逻辑示例:
fp = filp_open("/home/j0000/Desktop/file/kernel_file", O_RDWR | O_CREAT, 0644); if (IS_ERR(fp)) { printk("create file error\n"); return PTR_ERR(fp); } pos = 0; kernel_write(fp, buf, sizeof(buf), &pos); pos = 0; kernel_read(fp, buf1, sizeof(buf), &pos); printk("Read content=%s\n", buf1); filp_close(fp, NULL);
内容的提问来源于stack exchange,提问作者jackson
相关产品推荐
相关产品推荐

