Linux 内核模块中的文件 I/O
我正在编写一个需要打开和读取文件的 Linux 内核模块。 实现这一目标的最佳方法是什么?
I'm writing a Linux kernel module that needs to open and read files. What's the best way to accomplish that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我能问一下你为什么要打开文件吗?
我喜欢关注Linux开发(出于好奇,我不是内核开发人员,我是做Java的),而且我以前看过关于这个问题的讨论。 我找到了关于此的 LKML 消息,基本上提到了这通常是个坏主意。 我几乎可以肯定 LWN 去年曾报道过它,但我找不到这篇文章。
如果这是一个私有模块(例如某些自定义硬件,并且该模块不会分发),那么您可以这样做,但我的印象是,如果您要将代码提交到主线,那么它可能不会被接受。
Evan Teran 提到了 sysfs,这对我来说似乎是个好主意。 如果你确实需要做更难的自定义事情,你总是可以创建新的 ioctrls。
编辑:
好的,我找到了我正在寻找的文章,它来自 Linux Journal。 它解释了为什么做这种事情通常是一个坏主意,然后继续告诉您到底如何做。
Can I ask why are you trying to open a file?
I like to follow Linux development (out of curiosity, I'm not a kernel developer, I do Java), and I've seen discussion of this question before. I was able to find a LKML message about this, basically mentioning it's usually a bad idea. I'm almost positive that LWN covered it in the last year, but I'm having trouble finding the article.
If this is a private module (like for some custom hardware and the module won't be distributed) then you can do this, but I'm under the impression that if you are going to submit your code to the mainline then it may not be accepted.
Evan Teran mentioned sysfs, which seems like a good idea to me. If you really need to do harder custom stuff you could always make new ioctrls.
EDIT:
OK, I found the article I was looking for, it's from Linux Journal. It explains why doing this kind of stuff is generally a bad idea, then goes on to tell you exactly how to do it anyway.
假设您可以获得指向
open
/read
/close
系统调用的相关函数指针,您可以执行以下操作:需要创建我已经展示的“
syscall_*
”函数指针。 我确信有更好的方法,但我相信这会起作用。assuming you can get pointers to the relavent function pointers to the
open
/read
/close
system calls, you can do something like this:you will need to create the "
syscall_*
" function pointers I have shown though. I am sure there is a better way, but I believe that this would work.一般来说,如果您需要从内核模块读取/写入文件,那么您在架构上就做错了。
存在允许内核模块与用户空间帮助程序进程对话的机制(例如 netlink - 或者只是注册字符设备)。 该用户空间帮助进程可以做任何它想做的事情。
您还可以实现系统调用(或类似的)来获取在用户空间中打开的文件描述符并从内核读取/写入它。
这可能比尝试在内核空间中打开文件更简洁。
还有一些其他东西已经从内核空间打开文件,您可以查看它们(想到了循环驱动程序?)。
Generally speaking, if you need to read/write files from a kernel module, you're doing something wrong architecturally.
There exist mechanisms (netlink for example - or just register a character device) to allow a kernel module to talk to a userspace helper process. That userspace helper process can do whatever it wants.
You could also implement a system call (or such like) to take a file descriptor opened in userspace and read/write it from the kernel.
This would probably be neater than trying to open files in kernel space.
There are some other things which already open files from kernel space, you could look at them (the loop driver springs to mind?).
/proc 文件系统也适合私人使用,而且很简单。
http://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x773.html
/proc filesystem is also good for private use, and it's easy.
http://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x773.html
所有内核开发人员都说来自内核空间的文件 I/O 很糟糕(特别是如果您通过路径引用这些文件),但主流内核在加载固件时会这样做。 如果您只需要从文件中读取,请使用
固件加载程序代码使用的函数,在
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()< /code>),但没有
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 指针中。
All of the kernel developers say that file I/O from kernel space is bad (especially if you're referring to these files by their paths) but the mainstream kernel does this when you load firmware. If you just need to read from files, use the
function, which is what the firmware loader code uses, declared in
include/linux/fs.h
. This function returns a negative value on error.I'm not really sure of the point of the
id
variable at the end, if you look at the code it's not really used, so just put something likeREADING_FIRMWARE
there (no quotes).buf
is not null terminated, instead refer to its size insize
. If you need it to be null terminated, create a stringsize + 1
bytes long and copy it over or rewrite thekernel_read_file()
function (used bykernel_read_file_from_path()
, defined infs/exec.c
) and add one toi_size
where memory is allocated. (If you want to do this, you can redefine thekernel_read_file()
function in your module with a different function name to avoid modifying the whole kernel.)If you need to write to files, there is a
kernel_write()
function (analogous tokernel_read()
, which is used bykernel_read_file()
and therefore also bykernel_read_file_from_path()
), but there is nokernel_write_file()
orkernel_write_file_from_path()
function. You can look at the code in thefs/exec.c
file in the Linux kernel source tree wherekernel_read_file()
andkernel_read_file_from_path()
are defined to write your ownkernel_write_file()
andkernel_write_file_from_path()
functions that you can include in your module.And as always, you can store a file's contents in a char pointer instead of a void pointer with this function by casting it.
您还可以在此 Linux 内核模块编程指南< 中找到有关 sys_call_open 的一些信息/a>.
You can also find some informations about sys_call_open in this Linux Kernel Module Programing Guide.