C语言 在另一个模块linux上使用函数EXPORT_SYMBOL

xkftehaa  于 2023-05-06  发布在  Linux
关注(0)|答案(1)|浏览(188)

我正在尝试执行我创建的linux模块的一个函数。但我没有成功。这是project
我创建了一个小函数来将int转换为str float:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>

#include "service.h"
#include "fp_printk.h"

#define OURMODNAME "fp_printk"

MODULE_AUTHOR("Guilherme Giacomo Simoes <trintaeoitogc@gmail.com>");
MODULE_DESCRIPTION("This lib will show float-point in printk()");
MODULE_LICENSE("MIT");
MODULE_VERSION("0.4.1");

void fp_printk(int number, int decimal_places, char* destination)
{
    static char buffer[32] = { 0 };
    int buf_index = 30;
    int count_decimal_place = 0;
    int point_include = 0;

    for (; number && buf_index; --buf_index, number /= 10) {
        count_decimal_place++;
        if (!point_include && count_decimal_place > decimal_places) {
            buffer[buf_index] = '.';
            buf_index--;
            point_include = 1;
        }

        buffer[buf_index] = "0123456789"[number % 10];
    }

    strcpy(destination, &buffer[buf_index + 1]);
}

static int __init fp_printk_init(void)
{
    printk(KERN_INFO "%s: initial execute module", OURMODNAME);
    return 0;
}

static void __exit fp_printk_exit(void)
{
    printk(KERN_INFO "%s: module end", OURMODNAME);
}

module_init(fp_printk_init);
module_exit(fp_printk_exit);

EXPORT_SYMBOL(fp_printk);

转换后,将str复制到目标参数。
在我的测试模块中,我调用:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/fpu/api.h>
#include <linux/slab.h>

#include "../fp_printk.h"

MODULE_AUTHOR("Guilherme Giacomo Simoes <trintaeoitogc@gmail.com>");
MODULE_DESCRIPTION("LKP book:ch5/fp_in_lkm: no performing FP \
(floating point) arithmetic in kernel mode");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_VERSION("0.1");

static int __init fp_in_lkm_init(void)
{
    const int number = 1234;
    const int decimal_places = 2;

    char *r = (char*) kmalloc(sizeof("12.34"), GFP_KERNEL);

    printk(KERN_INFO "antes de executar\n");
    extern void fp_printk(number, decimal_places, r);
    printk(KERN_INFO "teste apos a conversao");
    printk(KERN_INFO "%s",r);
    printk(KERN_INFO "teste apos o printk");

    return 0;
}

static void __exit fp_in_lkm_exit(void)
{
    printk(KERN_INFO "removed\n");
}

module_init(fp_in_lkm_init);
module_exit(fp_in_lkm_exit);

但是当我运行sudo dmesg查看printks时,我只查看:

[1210228.128703] test_fp_printk: antes de executar
[1210228.128712] test_fp_printk: teste apos a conversao

它不打印字符串
如果我在module_init中调用fp_printk(),它就会工作。

static int __init fp_printk_init(void)
{
    printk(KERN_INFO "%s: initial execute module", OURMODNAME);
    char *dest = kmalloc(sizeof("12.34"), GFP_KERNEL);
    fp_printk(1243, 2, dest); 
    printk(KERN_INFO, "%s", dest);
    return 0;
}
anauzrmj

anauzrmj1#

fp_in_lkm_init()函数中,您试图调用fp_printk()。就像这样:

extern void fp_printk(number, decimal_places, r);

但是,这不是调用函数的正确方法。在这里,您只是(不必要地)为函数添加一个函数原型,而不是调用它。
您只需要:

fp_printk(number, decimal_places, r);

请注意,测试模块需要知道fp_printk模块导出了哪些符号。通常,符号在内核附带的Module.symvers文件中可用。但你的新符号在那里是不存在的。
有几个选项,可以在内核模块文档的6.3 Symbols From Another External Module部分看到。对你来说最简单的方法可能是:
使用额外的Module.symvers文件构建外部模块时,会生成一个Module.symvers文件,其中包含内核中未定义的所有导出符号。要访问bar.ko中的符号,请将编译bar.ko的Modular.symvers文件复制到构建foo.ko的目录中。在模块构建期间,kbuild将读取外部模块目录中的Module.symvers文件,当构建完成时,将创建一个新的Module.symvers文件,其中包含所有定义的符号的总和,而不是内核的一部分。

相关问题