我需要访问Android内核模块中的一些proc文件。
基本上我需要cat命令中显示的信息,比如cat /proc/uptime
。但是我需要以编程方式进行。
我尝试使用proc_fs
函数,但这对我来说有点模糊,通常示例是创建一个proc文件然后读取它就是这样。我需要实际使用proc文件中的数据。
我也记录了好fopen
,但它似乎不适用于模块。
我该怎么做?我真的是新手。 我正在研究金鱼Android内核。
感谢。
答案 0 :(得分:4)
Procfs是内存中的文件系统。它是用户空间获取信息并将(配置)信息放入内核数据结构的接口。换句话说,procfs使用户空间能够以运行时它们存在的方式进行交互并查看内核数据结构。
因此,/ proc中的任何文件都是而不是意味着要从内核或内核模块中读取。那为什么要这样做呢?在像Linux这样的单片内核中,您可以直接或通过预定义的函数访问内核中一个子系统的数据结构。
以下函数调用可能会有所帮助:
struct timespec uptime;
do_posix_clock_monotonic_gettime(&uptime);
您可以在下面的链接中参考/ proc / uptime实现,它基本上是seq_file
。
答案 1 :(得分:0)
我用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++;
}
答案 2 :(得分:0)
我正在回答最初的问题,内核模块如何访问 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 机器上,内核模块可以使用内联汇编直接访问控制寄存器、遍历页表,并随心所欲地处理任何内存区域。中断和异常处理程序也是如此。