内核模块结构体数组合法性及初始化警告修正咨询
内核驱动struct数组编译问题解答
问题背景
编写内核驱动时,硬编码部分值简化了struct数组,驱动代码如下:
#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #define MODULE_NAME ("test-module") #define BOARD_VER 3 #define BOARD_SAM 2 struct foo { int variant; char *str[3]; }; struct bar { int sample; struct foo fooarr[3]; }; static int __init dtcprop_init(void) { unsigned int board_sample, board_variant; int i = 0; board_sample = BOARD_SAM; board_variant= BOARD_VER; struct bar bar_array[6] = { -1, { 0, NULL,NULL,NULL }, }; if (bar_array[board_sample].sample != -1 && bar_array[board_sample].fooarr[board_variant].variant != -1) { while (bar_array[board_sample].fooarr[board_variant].str[i] != NULL) { pr_info("%s: %s\n", MODULE_NAME, bar_array[board_sample].fooarr[board_variant].str[i++]); } } else { pr_info("%s: unsupported board\n", MODULE_NAME); } return 0; } arch_initcall(dtcprop_init);
编译时出现两个被视为错误的警告:
41:35: warning: missing braces around initializer [-Wmissing-braces] 41:9: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 41 | struct bar bar_array[6] = { | ^~~~~~
问题解答
1. 在内核模块中编写struct数组是否合法?
完全合法。内核源码里大量使用结构体数组来组织硬件配置、设备参数等数据,这是非常常见且合规的写法。
2. 如何修正上述驱动代码?
针对两个警告分别处理:
警告1:ISO C90 forbids mixed declarations and code
Linux内核默认采用C90编译标准,该标准要求代码块内的变量声明必须放在所有可执行代码之前。原代码中struct bar bar_array[6]的声明放在了赋值语句之后,违反了规则,需要把它移到代码块开头的变量声明区域。警告2:missing braces around initializer
结构体嵌套时,初始化器的大括号要和结构体层级一一对应。struct bar包含一个int和struct foo数组,struct foo又包含int和指针数组,原代码的初始化写法没有匹配嵌套结构,需要通过嵌套大括号明确层级。
修正后的完整代码如下:
#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #define MODULE_NAME ("test-module") #define BOARD_VER 3 #define BOARD_SAM 2 struct foo { int variant; char *str[3]; }; struct bar { int sample; struct foo fooarr[3]; }; static int __init dtcprop_init(void) { unsigned int board_sample, board_variant; int i = 0; // 移到代码块开头,符合C90声明规则 struct bar bar_array[6] = { // 嵌套大括号匹配struct bar的结构:int + struct foo数组 { -1, // sample字段 { // fooarr数组的第一个元素 {0, {NULL, NULL, NULL}} // struct foo的variant和str数组 // 其余未显式初始化的成员会被编译器自动置为0/NULL } } }; board_sample = BOARD_SAM; board_variant = BOARD_VER; if (bar_array[board_sample].sample != -1 && bar_array[board_sample].fooarr[board_variant].variant != -1) { while (bar_array[board_sample].fooarr[board_variant].str[i] != NULL) { pr_info("%s: %s\n", MODULE_NAME, bar_array[board_sample].fooarr[board_variant].str[i++]); } } else { pr_info("%s: unsupported board\n", MODULE_NAME); } return 0; } arch_initcall(dtcprop_init);
补充说明
如果需要初始化bar_array的更多元素,只需按照相同的嵌套结构继续添加大括号即可。编译器会将未显式初始化的结构体成员自动置为0或NULL,符合内核代码的安全要求。
内容的提问来源于stack exchange,提问作者mrigendra
相关产品推荐
相关产品推荐

