使用 C 预处理器宏在核心模块中注册子模块
Register a sub-module in a core module with a C preprocessor macro
我正在用 C 语言为微控制器实现一个小型系统。该系统有多个传感器。受 Linux 内核的启发,我想为每种类型的传感器创建传感器核心模块和分离传感器。
在内核中实现一个新模块时,有一个宏module_init
。该宏采用结构指针并将其存储在预定义的内存部分中。在内核启动时,所有模块的所有 init 函数都会根据带有函数指针的内存部分被一个接一个地调用。
我正在尝试用我的传感器和传感器核心模块做一些类似的事情。假设我的传感器核心模块有一个指针数组。每个传感器创建自己的配置结构。我想编写一个宏来复制这种结构的指针并将其放置在传感器核心模块的数组中——全部在编译时完成。
传感器-core.h:
struct sensor_config {
void (*init)(void) init;
...
};
传感器-core.c:
#include "sensors-core.h"
struct sensor_config *sensors[SENSORS_MAX_NUM];
sensor.c
#include "sensors-core.h"
void Init(void)
{
...
}
struct sensor_config config = {
.init = Init
};
SENSOR_INIT(config);
- 如何编写这样的宏?可能吗?它是特定于编译器的还是我可以这样做以便代码可以移植?
- 预处理器能否处理 SENSOR_INIT() 宏的使用次数并动态(在编译时)调整传感器数组大小?我知道数组是浪费内存。在 Linux 内核中,初始化后,包含指针列表的内存部分被释放用于其他用途。目前我不关心那个,那将是下一步。
我发现了一些类似但不完全是我正在寻找的解决方案。 Plugin system for statically linked modules in C?
这里我们可以给一个要在main
.
之前调用的函数添加属性
内核不是uC。 module_init
采用函数,而不是结构,为此重写接口可能是个好主意。内核加载一个专门准备的文件并对其进行解析,并从中找到要调用的正确函数。
How can I write such macro?
将指向变量的指针放在节内。
#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;
然后How do you get the start and end addresses of a custom ELF section?遍历节中的指针并调用。
元素似乎是常量,您可能只是将元素存储在部分中。
#define SENSOR_SECTION \
__attribute__((__section__("sensors"))) \
__attribute__((__used__))
SENSOR_SECTION
struct sensor_config config = { stuff; }
Would it be compiler specific
非常好。
or can I do that so it the code will be portable?
没有
您可以在构建过程中使用外部实用程序来生成数组初始化。例如,执行 #define SENSOR_INIT(x) /*nothing*/
然后用外部程序(awk
、Perl、Python)遍历所有源文件以找到所有 SENSOR_INIT(config);
语句,并从中生成 sensors-core.c
个文件引用了所有文件中的所有结构。
Can preprocessor take care of how many times the SENSOR_INIT() macro is used and dynamically (at the compilation time) adjust sensors array size?
没有
我正在用 C 语言为微控制器实现一个小型系统。该系统有多个传感器。受 Linux 内核的启发,我想为每种类型的传感器创建传感器核心模块和分离传感器。
在内核中实现一个新模块时,有一个宏module_init
。该宏采用结构指针并将其存储在预定义的内存部分中。在内核启动时,所有模块的所有 init 函数都会根据带有函数指针的内存部分被一个接一个地调用。
我正在尝试用我的传感器和传感器核心模块做一些类似的事情。假设我的传感器核心模块有一个指针数组。每个传感器创建自己的配置结构。我想编写一个宏来复制这种结构的指针并将其放置在传感器核心模块的数组中——全部在编译时完成。
传感器-core.h:
struct sensor_config {
void (*init)(void) init;
...
};
传感器-core.c:
#include "sensors-core.h"
struct sensor_config *sensors[SENSORS_MAX_NUM];
sensor.c
#include "sensors-core.h"
void Init(void)
{
...
}
struct sensor_config config = {
.init = Init
};
SENSOR_INIT(config);
- 如何编写这样的宏?可能吗?它是特定于编译器的还是我可以这样做以便代码可以移植?
- 预处理器能否处理 SENSOR_INIT() 宏的使用次数并动态(在编译时)调整传感器数组大小?我知道数组是浪费内存。在 Linux 内核中,初始化后,包含指针列表的内存部分被释放用于其他用途。目前我不关心那个,那将是下一步。
我发现了一些类似但不完全是我正在寻找的解决方案。 Plugin system for statically linked modules in C?
这里我们可以给一个要在main
.
内核不是uC。 module_init
采用函数,而不是结构,为此重写接口可能是个好主意。内核加载一个专门准备的文件并对其进行解析,并从中找到要调用的正确函数。
How can I write such macro?
将指向变量的指针放在节内。
#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;
然后How do you get the start and end addresses of a custom ELF section?遍历节中的指针并调用。
元素似乎是常量,您可能只是将元素存储在部分中。
#define SENSOR_SECTION \
__attribute__((__section__("sensors"))) \
__attribute__((__used__))
SENSOR_SECTION
struct sensor_config config = { stuff; }
Would it be compiler specific
非常好。
or can I do that so it the code will be portable?
没有
您可以在构建过程中使用外部实用程序来生成数组初始化。例如,执行 #define SENSOR_INIT(x) /*nothing*/
然后用外部程序(awk
、Perl、Python)遍历所有源文件以找到所有 SENSOR_INIT(config);
语句,并从中生成 sensors-core.c
个文件引用了所有文件中的所有结构。
Can preprocessor take care of how many times the SENSOR_INIT() macro is used and dynamically (at the compilation time) adjust sensors array size?
没有