内核模块未加载(但 insmod returns 0)

kernel module in not loaded (but insmod returns 0)

我必须向现有设备添加一些功能 (mips arch) - 我已经尝试了几个 SDK,目前我取得了一些进展,但是: insmod returns 0(success) 和 lsmod 显示它们,但是 printk 和 create_proc_entry 都不起作用....但我已经查看了部分 .gnu.linkonce.this_module: 除了模块名称 - 那里没有有用的信息 - 部分充满了 0x0's

我发现在本机 .ko 文件中,设备大小的 .gnu.linkonce.this_module 小到 8 个字节 - 但根据该部分用于临时加载信息以构建模块的事实 - 那里在我看来无关紧要...

https://ufile.io/eco1s 有几个文件:khelloworld.ko - 我的 helloworld 模块 - 尝试创建 procfs 条目 khelloworld.ko - 尝试在 rootfs 中创建文件(/tmp/test.file ) 本机模块:xt_mark.ko md5.ko cbc.ko

我没有内核配置 - 但我需要编译那个模块...我只知道版本

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>  /* Necessary because we use the proc fs */
#include <linux/init.h>     /* Needed for the macros */

#define procfs_name "khelloworld"


MODULE_LICENSE("GPL");
MODULE_INFO(vermagic, "2.6.32.68 mod_unload MIPS32_R2 32BIT ");
MODULE_AUTHOR     ("XAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");


struct proc_dir_entry *Our_Proc_File;

static int
procfile_read(char *buffer,
      char **buffer_location,
      off_t offset, int buffer_length, int *eof, void *data);

    static int __init khelloworld_init( void ) {
    printk(KERN_INFO "try to create /proc \n"); 
    Our_Proc_File = create_proc_entry(procfs_name, 0644, NULL);

    if (Our_Proc_File == NULL) {
        remove_proc_entry(procfs_name, NULL);
        printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
           procfs_name);
        return -ENOMEM;
    }

    Our_Proc_File->read_proc = procfile_read;
    Our_Proc_File->owner     = THIS_MODULE;
    Our_Proc_File->mode      = S_IFREG | S_IRUGO;
    Our_Proc_File->uid       = 0;
    Our_Proc_File->gid       = 0;
    Our_Proc_File->size      = 37;

    printk(KERN_INFO "/proc/%s created\n", procfs_name);    
    return 3;   /* everything is ok */
}

static void __exit khelloworld_exit( void ) {
    remove_proc_entry(procfs_name, NULL);
    printk(KERN_INFO "/proc/%s removed\n", procfs_name);
}


module_init(khelloworld_init);
module_exit(khelloworld_exit);

int
procfile_read(char *buffer,
      char **buffer_location,
      off_t offset, int buffer_length, int *eof, void *data)
{
    int ret;

    printk(KERN_INFO "procfile_read (/proc/%s) called\n", procfs_name);

    /* 
     * We give all of our information in one go, so if the
     * user asks us if we have more information the
     * answer should always be no.
     *
     * This is important because the standard read
     * function from the library would continue to issue
     * the read system call until the kernel replies
     * that it has no more information, or until its
     * buffer is filled.
     */
    if (offset > 0) {
        /* we have finished to read, return 0 */
        ret  = 0;
    } else {
        /* fill the buffer, return the buffer size */
        ret = sprintf(buffer, "HelloWorld!\n");
    }

    return ret;
}

readelf -a 表明您的 init 函数的重定位条目与本机模块案例中的不同:

xt_mark.ko

Relocation section '.rel.gnu.linkonce.this_module' at offset 0x958 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
000000bc  00001502 R_MIPS_32         00000000   init_module
00000130  00001402 R_MIPS_32         00000000   cleanup_module


khelloworld.ko

Relocation section '.rel.gnu.linkonce.this_module' at offset 0xafc contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
000000ac  00002502 R_MIPS_32         00000000   init_module
0000010c  00002402 R_MIPS_32         00000000   cleanup_module

请注意,对于本机模块,init_module 指针位于 module 结构的偏移量 0xbc 中,而在您的模块中它位于偏移量 0xac 中。结果,加载器没有找到你的 init 函数,也没有调用它。

如解释的那样 , this is likely the result of a kernel configuration difference between your build environment and the native build environment. It's very likely that CONFIG_UNUSED_SYMBOLS is the culprit (see the module definition here)。

或者,您可以(风险自负!)对生成的模块应用二进制补丁,将 0xac 更改为 0xbc。