如何使用EXPORT_SYMBOL或等效的方法在两个内核模块之间导出结构?

时间:2014-08-22 11:42:11

标签: c struct linux-kernel kernel-module

我有一个内核模块,其结构如下:

struct test {
    int a;
    int b;
    .....
}

我已经创建了这个结构的实例数组:

struct test foo[8];

我想导出这个结构或数组" foo"使用EXPORT_SYMBOL并访问其他内核模块中的foo[0].a

我在提供程序模块中尝试了EXPORT_SYMBOL(foo);,在接收器模块中尝试了extern struct test * foo;,但我无法访问该变量。请指出我犯错的地方。

以下是一些代码:

内核模块1:

#include <....>
#include "test_config.h"
....
MODULE_LICENSE("GPL");

struct test {
int a;
int b;
.....
}

test_t foo[8];
//EXPORT_SYMBOL(foo);

/*Code to create sysctl variables out of these members of the struct test*/

int init_module(void)
{
    printk(KERN_INFO "Hello World\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye Cruel World\n");
}

Kerne模块2:

#include <linux/module.h>
#include <linux/kernel.h>
#include "test_config.h"

int init_module(void)
{
    test_t foo[8];
    printk ("Value of foo is :: %d\n", foo[0].a);
    foo[0].a++;
    printk(KERN_INFO "Hello Again World\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye Again Cruel World\n");
}

以下是带有结构定义的头文件:

#ifndef __TEST_CONFIG
#define __TEST_CONFIG

typedef struct test
{
    int a;
    int b
    int c;
    int d;
    float e;
}test_t;

#endif

3 个答案:

答案 0 :(得分:8)

模块A 中,您已将其视为

struct test foo[8];

并将其作为

EXPORT_SYMBOL(foo);

因此,要在另一个模块B 中使用它,您需要添加

extern struct test foo[8];

并确保在模块B中使用它时,应首先加载模块A.


如果您不想导出整个数组但只想导出指针

在模块a

struct test foo[8];
struct *test temp = &foo(0);
EXPORT_SYMBOL(temp);

在模块B中

extern struct *test temp;

并以temp[0].a

的形式访问记忆库

又一个例子

http://lxr.free-electrons.com/source/sound/core/init.c?v=2.6.35;a=arm#L48

 48 struct snd_card *snd_cards[SNDRV_CARDS];
 49 EXPORT_SYMBOL(snd_cards);

因此它被用作

281 extern struct snd_card *snd_cards[SNDRV_CARDS];
http://lxr.free-electrons.com/source/include/sound/core.h?v=2.6.35#L281

中的


最终更新

#include <....>
#include "test_config.h"
....
MODULE_LICENSE("GPL");


test_t foo[8];
EXPORT_SYMBOL(foo);


int init_module(void)
{
    printk(KERN_INFO "Hello World\n");
    foo[0].a = 10;  // set some value.
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye Cruel World\n");
}

现在模块化2

#include <linux/module.h>
#include <linux/kernel.h>
#include "test_config.h"

extern test_t foo[8];

int init_module(void)
{
    printk ("Value of foo is :: %d\n", foo[0].a); // it should print 10
    printk(KERN_INFO "Hello Again World\n");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye Again Cruel World\n");
}

标题文件。

#ifndef __TEST_CONFIG
#define __TEST_CONFIG

typedef struct test
{
    int a;
    int b
    int c;
    int d;
    float e;
}test_t;

#endif

应首先加载模块1,然后对模块2进行加密。

答案 1 :(得分:3)

answer给出的Mr.32不知何故并没有解决我的问题。所以我在不使用结构的情况下实现了这个,并为每个成员a,b,c创建了单独的数组,以便继续我的任务......

在做了一些实验后,我能够达到导出结构的原始要求。

我修改了头文件,如下所示:

#ifndef __TEST_CONFIG
#define __TEST_CONFIG

struct test
{
    int a;
    int b
    int c;
    int d;
    float e;
};

extern struct test foo[8];

#endif

执行此操作后,我在提供程序模块中将此结构定义为:

struct test foo[8];
EXPORT_SYMBOL(foo);

并在接收器模块中包含标头并将其引用为:

extern struct test foo[8];

通过执行这些更改,我可以通过执行foo[0].a;来访问第二个模块中第一个模块的值。

答案 2 :(得分:0)

在内核模块编译期间,Module.symvers文件在同一目录中生成(默认情况下与源文件一起)。 如果在具有不同目录的某些不同源中导出和导入符号,则需要将Module.symvers文件复制到其他源文件的目录中。 有时为了清理构建,这些文件将被删除。如果导出符号,则删除文件将无法解析外部符号。