为什么在cfg80211扫描请求中为具有灵活数组成员的结构分配了更多内存(超过所需内存)?

为什么在cfg80211扫描请求中为具有灵活数组成员的结构分配了更多内存(超过所需内存)?,c,struct,linux-kernel,flexible-array-member,C,Struct,Linux Kernel,Flexible Array Member,我正在学习linux wifi驱动程序,并在cfg80211子系统中探索扫描请求的代码 我不明白为什么下面的struct分配的内存比需要的多。 或者,我无法理解要分配的内存大小是如何以这种方式计算的 结构的定义如下所示: struct cfg80211\u扫描请求{ 结构cfg80211_ssid*ssid; int n_SSID; u32 n_频道; 枚举nl80211_bss_扫描宽度扫描宽度; 常数u8*ie; 尺寸; u16持续时间; bool-duration_强制性; u32旗; u

我正在学习linux wifi驱动程序,并在
cfg80211
子系统中探索扫描请求的代码

我不明白为什么下面的
struct
分配的内存比需要的多。 或者,我无法理解要分配的内存大小是如何以这种方式计算的

结构的定义如下所示:

struct cfg80211\u扫描请求{
结构cfg80211_ssid*ssid;
int n_SSID;
u32 n_频道;
枚举nl80211_bss_扫描宽度扫描宽度;
常数u8*ie;
尺寸;
u16持续时间;
bool-duration_强制性;
u32旗;
u32速率[NUM_NL80211_频带];
struct wireless_dev*wdev;
u8 mac地址[ETH\u ALEN]\uu对齐(2);
u8 mac地址掩码[ETH\u ALEN]\u对齐(2);
u8 bssid[ETH_ALEN]\u__对齐(2);
/*内部的*/
结构wiphy*wiphy;
无符号长扫描开始;
结构CFG8011\u扫描信息;
布勒通知;
布尔诺克;
/*放在最后*/
结构ieee80211_通道*通道[0];
};
在文件中,内存分配给
struct
,如下所示:

静态int nl80211_触发器_扫描(结构sk_buff*skb,结构genl_info*info)
{
// ...
结构cfg80211_扫描_请求*请求;
// ...
请求=kzalloc(sizeof(*请求)
+sizeof(*请求->SSID)*n\u SSID
+sizeof(*请求->通道)*n\u通道
+绿色荧光蛋白内核);
// ...
}
我怀疑分配的内存是否超过了要求。或者,在
kzalloc
中计算大小的方式对我来说没有意义

我希望代码是这样的:

静态int nl80211_触发器_扫描(结构sk_buff*skb,结构genl_info*info)
{
// ...
结构cfg80211_扫描_请求*请求;
// ...
请求=kzalloc(sizeof(*请求)
+sizeof(*请求->频道)*n\u频道,
绿色荧光蛋白(GFP);
// ...
}
那么为什么要分配这么大的内存呢?
我所理解的是
kzalloc(struct+flexible\u array\u member+extra\u len\u but\u why)
大概是
kzalloc
之后的代码设置指针
请求->ssid
请求->ie
的值,以便它们指向新分配的内存,就在结构之后

这样,只需为三个阵列分配一块内存

EDIT:我找到了有问题的函数,事实上,就在OP中显示的kzalloc调用之后,我们找到了以下设置
SSID
ie
指针的方法:

if (n_ssids)
    request->ssids = (void *)&request->channels[n_channels];
request->n_ssids = n_ssids;
if (ie_len) {
    if (n_ssids)
        request->ie = (void *)(request->ssids + n_ssids);
    else
        request->ie = (void *)(request->channels + n_channels);
}

大概是
kzalloc
之后的代码设置了指针
请求->ssid
请求->ie
的值,以便它们指向新分配的内存,就在结构之后

这样,只需为三个阵列分配一块内存

EDIT:我找到了有问题的函数,事实上,就在OP中显示的kzalloc调用之后,我们找到了以下设置
SSID
ie
指针的方法:

if (n_ssids)
    request->ssids = (void *)&request->channels[n_channels];
request->n_ssids = n_ssids;
if (ie_len) {
    if (n_ssids)
        request->ie = (void *)(request->ssids + n_ssids);
    else
        request->ie = (void *)(request->channels + n_channels);
}

我猜那是因为在那之后有额外的数据,那实际上不是一个
结构ieee80211_通道;这只是一个错误,因为零大小的数组是非法的,而FAM的维度是空的:
struct ieee80211u channel*channels[]。它使用的是一个GCC扩展——它是一个还是两个扩展都有争议,但这并不重要。OTOH,它是有效的,Linux内核肯定依赖于GCC。我猜这是因为在那之后有额外的数据,实际上它不是一个
结构ieee80211_通道;这只是一个错误,因为零大小的数组是非法的,而FAM的维度是空的:
struct ieee80211u channel*channels[]。它使用的是一个GCC扩展——它是一个还是两个扩展都有争议,但这并不重要。OTOH,它可以工作,Linux内核肯定依赖于GCC。