Linux内核模块中的文件I / O.
-
07-07-2019 - |
题
我正在编写一个需要打开和读取文件的Linux内核模块。什么是实现这一目标的最佳方法?
解决方案
我可以问你为什么要打开文件?
我喜欢关注Linux开发(出于好奇,我不是内核开发人员,我做Java),之前我已经看过这个问题的讨论。我能够找到关于此的 LKML消息,基本上提到了这通常是一个坏主意。我对LWN在过去一年中的报道几乎是肯定的,但我很难找到这篇文章。
如果这是一个私有模块(比如某些自定义硬件而且模块不会被分发),那么你可以这样做,但我的印象是,如果你要将代码提交到主线那么它可能不被接受。
Evan Teran提到了sysfs,这对我来说似乎是一个好主意。如果你真的需要做更难的自定义东西,你可以随时制作新的ioctrls。编辑:
好的,我找到了我要找的文章,它来自 Linux Journal 。它解释了为什么做这种东西通常是一个坏主意,然后继续告诉你究竟该怎么做。
其他提示
假设你可以获得指向 open
/ read
/ close
系统调用的relavent函数指针的指针,你可以这样做:
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 _ *
”我已经展示过的函数指针。我相信有更好的方法,但我相信这会有效。
一般来说,如果你需要从内核模块读取/写入文件,那么你在架构上做错了。
存在机制(例如netlink - 或只注册字符设备)以允许内核模块与用户空间帮助程序进程通信。用户空间帮助程序进程可以做任何想做的事情。
您还可以实现系统调用(或类似),以获取在用户空间中打开的文件描述符,并从内核读取/写入它。
这可能比尝试在内核空间中打开文件更整洁。
还有一些其他东西已经从内核空间打开文件,你可以看一下它们(想到循环驱动程序吗?)。
/ proc filesystem也适合私人使用,而且很容易。
http://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x773.html
所有内核开发人员都说来自内核空间的文件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指针。