我正在编写一个需要打开和读取文件的Linux内核模块。什么是实现这一目标的最佳方法?
答案 0 :(得分:31)
我可以问你为什么要打开文件?
我喜欢关注Linux开发(出于好奇,我不是内核开发人员,我做Java),之前我已经看过这个问题的讨论。我能够找到LKML message这个,基本上提到它通常是一个坏主意。我对LWN在过去一年中的报道几乎是肯定的,但我很难找到这篇文章。
如果这是一个私有模块(比如某些自定义硬件而且模块不会被分发),那么你可以这样做,但我的印象是,如果你要将代码提交到主线那么它可能不被接受。
Evan Teran提到了sysfs,这对我来说似乎是一个好主意。如果你真的需要做更难的自定义东西,你可以随时制作新的ioctrls。编辑:
好的,我找到了我要找的文章,它来自Linux Journal。它解释了为什么做这种东西通常是一个坏主意,然后继续告诉你究竟该怎么做。
答案 1 :(得分:9)
假设您可以获得指向open
/ read
/ close
系统调用的相关函数指针的指针,您可以执行以下操作:
mm_segment_t fs = get_fs();
set_fs(KERNEL_DS);
fd = (*syscall_open)(file, flags, mode);
if(fd != -1) {
(*syscall_read)(fd, buf, size);
(*syscall_close)(fd);
}
set_fs(fs);
您需要创建我已经显示的“syscall_*
”函数指针。我相信有更好的方法,但我相信这会有效。
答案 2 :(得分:2)
一般来说,如果你需要从内核模块读取/写入文件,那么你在架构上做错了。
存在机制(例如netlink - 或只注册字符设备)以允许内核模块与用户空间帮助程序进程通信。用户空间帮助程序进程可以做任何想做的事情。
您还可以实现系统调用(或类似),以获取在用户空间中打开的文件描述符,并从内核读取/写入它。
这可能比尝试在内核空间中打开文件更整洁。
还有一些其他东西已经从内核空间打开文件,你可以看一下它们(想到循环驱动程序吗?)。
答案 3 :(得分:1)
您还可以在此Linux Kernel Module Programing Guide中找到有关sys_call_open的一些信息。
答案 4 :(得分:1)
/ proc filesystem也适合私人使用,而且很容易 http://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x773.html
答案 5 :(得分:0)
所有内核开发人员都说内核空间中的文件I / O不好(特别是如果您通过它们的路径引用这些文件),但是主流内核在加载固件时会这样做。如果您只需要读取文件,请使用
kernel_read_file_from_path(const char *path, void **buf, loff_t *size, loff_t max_size, enum kernel_read_file_id id)
在include/linux/fs.h
中声明的函数是固件加载器代码使用的函数。错误时此函数返回负值。
我真的不确定id
变量的结尾,如果您看一下它并没有真正使用的代码,那么只需在其中加上READING_FIRMWARE
之类的内容(无引号)
buf
不是以Null结尾的,而是在size
中引用其大小。如果需要将其终止为null,请创建一个长度为size + 1
个字节的字符串,然后将其复制或重写kernel_read_file()
函数(由kernel_read_file_from_path()
使用,在fs/exec.c
中定义),然后在分配内存的i_size
中添加一个。 (如果要执行此操作,可以在模块中使用其他函数名称重新定义kernel_read_file()
函数,以避免修改整个内核。)
如果需要写入文件,则有一个kernel_write()
函数(类似于kernel_read()
,kernel_read_file()
使用了该功能,因此kernel_read_file_from_path()
也使用了该功能),但是没有kernel_write_file()
或kernel_write_file_from_path()
函数。您可以在Linux内核源代码树的fs/exec.c
文件中查看代码,其中kernel_read_file()
和kernel_read_file_from_path()
被定义为编写自己的kernel_write_file()
和kernel_write_file_from_path()
函数您可以将其包含在模块中。
和往常一样,通过此函数,可以通过强制转换将文件的内容存储在char指针中,而不是void指针中。