将带有空格字符的字符串参数传递给内核模块

15
模块名称:params.ko


#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/stat.h>
MODULE_LICENSE("Dual BSD/GPL");

static char *mystring = "this is my char string";
module_param(mystring, charp, S_IRUGO | S_IWUSR); 
MODULE_PARM_DESC(mystring, "A char string");

static int __init params_init(void)
{
  printk("驱动已加载\n");
  printk("   我的字符串(mystring): %s\n", mystring);
  return 0;
}

static void __exit params_exit(void) { printk("驱动已卸载\n"); }

module_init(params_init); module_exit(params_exit);

这是一个Linux内核模块,它定义了一个静态字符指针变量`mystring`,并使用`module_param()`函数将其注册为可由用户空间修改的内核参数。驱动程序提供了两个函数:`params_init()`和`params_exit()`,分别在加载和卸载模块时被调用。这个驱动程序还使用了一些Linux内核头文件库和`printk()`函数用于输出信息。当我使用默认设置时,在加载驱动程序时可以看到"this is my char string"。但是,如果我使用命令行传递带有空格的字符串,则会出现以下错误: Ex1: # insmod ./params.ko mystring="Hello World" insmod: error inserting './params.ko': -1 Unknown symbol in module dmesg显示了以下信息: params: Unknown parameter 'World' Ex2: # insmod ./params.ko mystring="HelloWorld" 如果我使用没有空格的“HelloWorld”,则不会出现问题来显示字符串。 我还尝试使用\或''来查看是否可以忽略空格以避免该空间,但失败了。 想请教任何知道如何将包含空格的字符串传递给内核模块的人? 谢谢并感谢您的帮助。

有趣。我猜“world”被解析为参数,因此出现了错误。只是为了试试,你能否尝试mystring = Hello\ World,即省略双引号并转义空格。 - Greycon
其实,我认为这可能是一个普遍的问题...请看http://lists.busybox.net/pipermail/busybox/2011-February/074611.html - Greycon
@Greycon 感谢您提供更多信息。看起来这确实是一个普遍存在的问题,目前还没有解决方案。 - rickhau
@Greycon我尝试按照您的建议使用mystring=Hello\ World。# insmod: error inserting './params.ko': -1 Unknown symbol in moduledmesg输出:params: Unknown parameter 'World' - rickhau
好的,我认为这是一个普遍性问题。我猜你将不得不传递一个带连字符的字符串,然后在内核驱动程序代码中解析它们。 - Greycon
1个回答

16
当您运行insmod ./params.ko mystring="Hello World"时,引号会被shell吃掉,而insmod二进制文件的参数将是mystring=Hello World。它将其原样传递给内核,然后一切都转到内核parse_args函数(在kernel/params.c中),该函数又调用next_arg将下一个参数分割成名称和值。
它绝对可以处理空格,因为我们在代码中看到以下注释:
/* You can use " around spaces, but can't escape ". */
/* Hyphens and underscores equivalent in parameter names. */

以下是条件语句的示例代码:
static char *next_arg(char *args, char **param, char **val)
{
    ...
    for (i = 0; args[i]; i++) {
        if (isspace(args[i]) && !in_quote)
            break;
    ...
}

所以,思路就是你需要将引号传递给内核,而不是 shell。我现在没有 Linux 系统来检查内核模块插入情况,但我猜以下命令应该可以工作:

# insmod ./params.ko mystring='"Hello World"'

在这里,shell将消耗单引号,并且insmod二进制文件的参数将是mystring="Hello World",因此这些引号将原封不动地传递给内核,使得解析该值与您期望的方式相符。尝试一下,应该可以工作。


1
如果您的字符串存储在环境变量中,则可以直接将字符串传递给模块参数。例如 - insmod ./params.ko mystring=$STRVAL - shashank arora

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