Почему в запросе на сканирование cfg80211 выделено больше памяти (чем требуется) для структуры с гибким членом массива? - PullRequest
0 голосов
/ 05 апреля 2020

Я изучаю linux драйверы Wi-Fi и изучал код в 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).

1 Ответ

2 голосов
/ 05 апреля 2020

Предположительно, код после kzalloc устанавливает значения указателей requests->ssids и requests->ie, чтобы они указывали на вновь выделенную память сразу после структуры.

Таким образом, только один Блок памяти должен быть выделен для трех массивов.

EDIT : я нашел соответствующую функцию, и действительно, сразу после вызова kzallo c, показанного в OP, мы найдите следующее, которое устанавливает указатели 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);
}
...