如何从Linux内核模块中访问内核命令行?

3

我怎样才能从Linux内核模块中获取内核命令行?

可以通过读取/proc/cmdline来实现,但似乎有一种比打开和读取文件更容易访问命令行的内核模块方法。


你知道 /proc/cmdline 只是告诉你在启动时传递给内核的参数,对吧?你实际上不能使用它与内核进行交互或发送命令。https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-cmdline - charlesw
当然。我完全没有试图通过/ proc / cmdline与内核交互。我正在尝试在Linux内核模块中获取那些参数,这通常是通过读取/ proc / cmdline来完成的,但是从内核模块中没有直接的方法可以做到这一点。 - Billy
2个回答

2

您实际上需要访问整个内核命令行,还是只需要一些参数?
您可以用您的模块名称为每个重要参数添加前缀。

my_module.my_variable=value

那么您的内核模块可以使用 module_param() 宏来检索它,如 将命令行参数传递给模块 中所述。

这是一个奇怪的情况,我需要将cmdline打印到内核日志中。但我可以这样做:insmod module.ko cmdline=$(cat /proc/cmdline) - Billy
似乎仍然应该有一种直接访问命令行的方法,但是saved_command_line没有被导出。 - Billy
“我需要将cmdline打印到内核日志中。” -- 为什么?它已经在日志中了。它是内核输出的前十几行之一。 - sawdust
很奇怪。我需要使用KERN_ERR紧急性再次打印它,以便被日志记录程序显示。 - Billy

0

这是一种有点hack的方法,因此不适用于生产质量的代码,但是发现可以调用kallsyms_lookup_name来按符号名称查找内核变量或函数,而这些变量或函数并没有被导出。

get_mem_areas_from_memmap_params是一个例子,其中修改了一个模块,该模块分配物理连续内存并在内核命令行上使用memmap选项来保留一些物理内存。当模块加载时,它想要解析命令行以查找memmap条目,然后使用已保留但未被内核使用的物理内存。

例如,以下代码被用来获取访问未被导出的saved_command_line

    const char **lookup_saved_command_line;

    /* Can't find an exported way of obtaining the Kernel command line, so lookup the saved_command_line variable */
    lookup_saved_command_line = (const char **) kallsyms_lookup_name ("saved_command_line");
    if ((lookup_saved_command_line == NULL) || ((*lookup_saved_command_line) == NULL))
    {
        pr_info(CMEM_DRVNAME " Failed to lookup saved_command_line\n");
        return -EINVAL;
    }

还可以查找未导出的函数并调用它们。例如,从上面的模块中,以下代码查找并调用parse_args来解析命令行参数,避免编写解析代码:

    /* Lookup the function to parse arguments, to re-use the parsing code which handles escaping of parameters */
    parse_args_lookup = (void *) kallsyms_lookup_name ("parse_args");
    if ((parse_args_lookup == NULL) || ((*parse_args_lookup) == NULL))
    {
        pr_info(CMEM_DRVNAME " Failed to lookup parse_args\n");
        return -EINVAL;
    }
    
    cmdline = kstrdup (*lookup_saved_command_line, GFP_KERNEL);
    parse_args_lookup("cmem params", cmdline, NULL, 0, 0, 0, NULL, &cmem_boot_param_cb);
    kfree (cmdline);

这个方法被称为hack的原因是它没有类型安全性,因为必须将函数指针的预期函数原型复制到模块源文件中,所以在编译模块时没有编译时检查函数指针是否与内核匹配。唯一的运行时检查是按名称查找请求的符号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接