我尝试使用proc_fs函数进行操作,但对我来说有点模糊,通常示例是创建一个proc文件,然后读取它,就这样。我需要实际使用proc文件中的数据。
我也尝试了好用的fopen,但似乎在模块中不起作用。
我应该怎么做呢?我真的很新手。 我正在goldfish Android内核上工作。
谢谢。
Procfs是一个内存文件系统。它是用户空间获取信息并将(配置)信息放入内核数据结构的接口。换句话说,procfs使得用户空间可以在运行时查看和与内核数据结构交互。
因此,/proc中的任何文件不适合从内核或内核模块内部读取。为什么有人想要这样做呢?在像Linux这样的单片内核中,您可以通过另一个子系统直接访问一个子系统的数据结构或通过预定义函数访问。
下面的函数调用可能会有所帮助:
struct timespec uptime;
do_posix_clock_monotonic_gettime(&uptime);
procfs
中的文件。
我发现以下链接是一个有用的参考: https://elixir.bootlin.com/linux/latest/source/fs/proc/proc_sysctl.c#L1790
我认为这是从内核命令行设置sysctl
值。该序列似乎如下:
A. 挂载procfs
文件系统
proc_fs_type = get_fs_type("proc");
*proc_mnt = kern_mount(proc_fs_type);
B. 打开相对于procfs
根目录的路径下的文件
file = file_open_root((*proc_mnt)->mnt_root, *proc_mnt, path, O_WRONLY, 0);
C. 读写文件
int kernel_read_file(struct file *file, loff_t offset, void **buf, size_t buf_size, size_t *file_size, enum kernel_read_file_id id)
读取内核文件wret = kernel_write(file, val, len, &pos);
写入文件D. 关闭文件
err = filp_close(file, NULL);
关闭文件D. 清理文件系统挂载
kern_unmount(proc_mnt);
卸载文件系统put_filesystem(proc_fs_type);
释放文件系统资源是的,procfs
主要提供用户空间读/写内核级别数据的访问。由于内核模块运行在内核中,如果存在更直接的API调用序列允许模块访问这些数据,则使用此类API将更可取,因为它很可能更清晰、代码更少、效率更高。
但是,动态加载的内核模块无法(干净地)直接访问内核中的所有符号(或数据结构)。
内核模块只能访问函数和变量,这些函数和变量是:
完全定义在头文件中,可包含在内核模块源代码中
或通过/include/asm-generic/export.h
中的宏之一显式地暴露给内核模块:
EXPORT_SYMBOL
EXPORT_SYMBOL_GPL
EXPORT_DATA_SYMBOL
EXPORT_DATA_SYMBOL_GPL
内核模块需要访问未通过这种EXPORTED
API公开但可以通过procfs
或任何其他特殊文件系统中的文件访问数据的情况似乎是合法的。
作为一般的设计原则,我理解内核的目标是实现机制,而不强制执行特定策略。以用户空间可以访问数据但内核模块不能访问数据的方式实现的任何功能都是设计不良的。
内核模块代码按设计原则与内核的其余部分在同一特权级别上运行。没有绝对可靠的方法来拒绝内核模块访问任何其他部分的内核可以访问的数据。任何此类尝试都可以用美丽而丑陋的黑客技巧规避。
作为一个极端的例子,在x86机器上,内核模块可以使用内联汇编直接访问控制寄存器、遍历页表,并且可以随意处理任何内存区域。中断和异常处理程序也是如此。我使用了 top 命令来完成这个任务,因为它可以给出 CPU 使用率的百分比。我使用的代码如下:
Process process = Runtime.getRuntime().exec("top -n 1");
//Get the output of top so that it can be read
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
//Read every line of the output of top that contains data
while (((line = bufferedReader.readLine()) != null)) {
//Break the line into parts. Any number of spaces greater than 0 defines a new element
numbersC = line.split("[ ]+");
if (i > 6) {
//Some lines start with a space, so their indices are different than others
if (numbersC[0].equals("")){
//If name contains the string com.android, then it is a process that we want to take values for
if (numbersC[numbersC.length - 1].toLowerCase().contains("com.android".toLowerCase())){
//Add the name of the process to the Name arraylist, excluding the com.android. part
Name.add(numbersC[numbersC.length - 1].replace("com.android.", ""));
//Add the CPU value of the process to the CPU arraylist, without the % at the end
CPU.add(Long.parseLong(numbersC[3].replace("%", "")));
}
}
else {
//This is basically the same as above, except with different index values, as there is no leading space in the numbers array
if (numbersC[numbersC.length - 1].toLowerCase().contains("com.android.".toLowerCase())){
Name.add(numbersC[numbersC.length - 1].replace("com.android.", ""));
CPU.add(Long.parseLong(numbersC[2].replace("%", "")));
}
}
}
i++;
}
top
,相对于直接读取/proc条目而言,这是相当间接的。其次,您正在编写Java代码,该代码无法在内核上下文中运行。第三,基本问题在于,既不应从内核上下文中使用/proc(如已接受的答案所述),也不应使用 top
。 - Chris Stratton