为什么在 cfg80211 扫描请求中为具有灵活数组成员的结构分配了更多内存(超出要求)?
Why more memory (than being required) is allocated to a struct with flexible array member in cfg80211 scan request?
我正在学习 linux wifi 驱动程序,并且正在探索 cfg80211
子系统中的代码以获取扫描请求。
我不明白为什么下面的 struct
分配的内存比需要的多。
或者,我无法理解要分配的内存大小的计算方式。
struct
定义在include/net/cfg80211.h
:
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
int n_ssids;
u32 n_channels;
enum nl80211_bss_scan_width scan_width;
const u8 *ie;
size_t ie_len;
u16 duration;
bool duration_mandatory;
u32 flags;
u32 rates[NUM_NL80211_BANDS];
struct wireless_dev *wdev;
u8 mac_addr[ETH_ALEN] __aligned(2);
u8 mac_addr_mask[ETH_ALEN] __aligned(2);
u8 bssid[ETH_ALEN] __aligned(2);
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
struct cfg80211_scan_info info;
bool notified;
bool no_cck;
/* keep last */
struct ieee80211_channel *channels[0];
};
在文件 /net/wireless/nl80211.c
中,内存分配给 struct
如下:
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
// ...
struct cfg80211_scan_request *request;
// ...
request = kzalloc(sizeof(*request)
+ sizeof(*request->ssids) * n_ssids
+ sizeof(*request->channels) * n_channels
+ ie_len, GFP_KERNEL);
// ...
}
我怀疑分配的内存比需要的多。或者,kzalloc
中计算大小的方式对我来说没有意义。
这是我期望的代码:
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
// ...
struct cfg80211_scan_request *request;
// ...
request = kzalloc(sizeof(*request)
+ sizeof(*request->channels) * n_channels,
GFP_KERNEL);
// ...
}
那为什么要分配那么大的内存?
我的理解是 kzalloc(struct + flexible_array_member + extra_len_but_why)
.
大概 kzalloc
之后的代码设置了指针 requests->ssids
和 requests->ie
的值,以便它们指向新分配的内存,就在结构之后。
这样三个数组只需要分配一块内存
EDIT:我找到了有问题的函数,事实上,就在 OP 中显示的 kzalloc 调用之后,我们找到了以下内容,它设置了 ssids
和 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);
}
我正在学习 linux wifi 驱动程序,并且正在探索 cfg80211
子系统中的代码以获取扫描请求。
我不明白为什么下面的 struct
分配的内存比需要的多。
或者,我无法理解要分配的内存大小的计算方式。
struct
定义在include/net/cfg80211.h
:
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
int n_ssids;
u32 n_channels;
enum nl80211_bss_scan_width scan_width;
const u8 *ie;
size_t ie_len;
u16 duration;
bool duration_mandatory;
u32 flags;
u32 rates[NUM_NL80211_BANDS];
struct wireless_dev *wdev;
u8 mac_addr[ETH_ALEN] __aligned(2);
u8 mac_addr_mask[ETH_ALEN] __aligned(2);
u8 bssid[ETH_ALEN] __aligned(2);
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
struct cfg80211_scan_info info;
bool notified;
bool no_cck;
/* keep last */
struct ieee80211_channel *channels[0];
};
在文件 /net/wireless/nl80211.c
中,内存分配给 struct
如下:
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
// ...
struct cfg80211_scan_request *request;
// ...
request = kzalloc(sizeof(*request)
+ sizeof(*request->ssids) * n_ssids
+ sizeof(*request->channels) * n_channels
+ ie_len, GFP_KERNEL);
// ...
}
我怀疑分配的内存比需要的多。或者,kzalloc
中计算大小的方式对我来说没有意义。
这是我期望的代码:
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
// ...
struct cfg80211_scan_request *request;
// ...
request = kzalloc(sizeof(*request)
+ sizeof(*request->channels) * n_channels,
GFP_KERNEL);
// ...
}
那为什么要分配那么大的内存?
我的理解是 kzalloc(struct + flexible_array_member + extra_len_but_why)
.
大概 kzalloc
之后的代码设置了指针 requests->ssids
和 requests->ie
的值,以便它们指向新分配的内存,就在结构之后。
这样三个数组只需要分配一块内存
EDIT:我找到了有问题的函数,事实上,就在 OP 中显示的 kzalloc 调用之后,我们找到了以下内容,它设置了 ssids
和 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);
}