使用C预处理器宏在核心模块中注册子模块



我正在用C为微控制器实现一个小型系统。该系统有多个传感器。受Linux内核的启发,我想为每种类型的传感器创建传感器核心模块和分离的传感器。

在内核中实现一个新模块时,有一个宏module_init。该宏获取一个结构的指针,并将其存储在预定义的内存部分中。在内核启动时,基于带有函数指针的内存段,逐个调用所有模块中的所有init函数。

我正在尝试对我的传感器和传感器核心模块做一些类似的事情。假设我的传感器核心模块有一组指针。每个传感器都创建自己的配置结构。我想写一个宏,它将复制这种结构的指针,并将其放置在传感器核心模块的数组中——所有这些都在编译时完成。

传感器核心。h:

struct sensor_config {
    void (*init)(void) init;
    ...
};

传感器核心。c:

#include "sensors-core.h"
struct sensor_config *sensors[SENSORS_MAX_NUM];

传感器.c

#include "sensors-core.h"
void Init(void)
{
    ...
}
struct sensor_config config = {
    .init = Init
};
SENSOR_INIT(config);
  1. 如何编写这样的宏?有可能吗?它是特定于编译器的,还是我可以这样做,这样代码就可以移植
  2. 预处理器是否可以处理SENSOR_INIT((宏的使用次数,并动态(在编译时(调整传感器阵列大小?我知道那个数组是在浪费内存。在Linux内核中,初始化后,包含指针列表的内存部分会释放出来供其他用途。现在我不在乎,那将是下一步

我发现了一些类似的东西,但并不完全是我想要的解决方案。C?中静态链接模块的插件系统?在这里,我们可以在main之前为要调用的函数添加属性。

内核不是uC。module_init需要一个函数,而不是一个结构,为此重写接口可能是个好主意。内核加载一个专门准备的文件并对其进行解析,然后从中找到要调用的正确函数。

如何编写这样的宏?

将指针放在节内的变量上。

#define CONCAT(a, b)  a##b
#define XCONCAT(a, b) CONCAT(a, b)
#define SENSOR_INIT(x) 
__attribute__((__section__("sensors"))) 
__attribute__((__used__)) 
const struct sensor_config *const CONCAT(sensor, __LINE__) = &x;

那么如何获得自定义ELF部分的起始地址和结束地址呢?迭代部分中的指针并调用。

元素似乎是恒定的,你可能只是把元素存储在部分中。

#define SENSOR_SECTION 
__attribute__((__section__("sensors"))) 
__attribute__((__used__))
SENSOR_SECTION
struct sensor_config config = { stuff; }

它会是编译器特定的吗

非常肯定。

或者我可以这样做吗?这样代码就可以移植了?

否。

您可以在生成过程中使用外部实用程序来生成数组初始化。例如,执行#define SENSOR_INIT(x) /*nothing*/,然后使用外部程序(awk、Perl、Python(遍历所有源文件,以查找所有SENSOR_INIT(config);语句,并由此生成引用所有文件中所有结构的sensors-core.c文件。

预处理器是否可以处理SENSOR_INIT((宏的使用次数,并动态(在编译时(调整传感器阵列大小?

否。

最新更新