См. Гибкие массивы Дэйва Хансена, добавленные к 2.6.31-rc5
https://lwn.net/Articles/345273/
Создание гибкого массива выполняется с помощью:
#include <linux/flex_array.h>
struct flex_array *flex_array_alloc(int element_size, int total, gfp_t flags);
Размер отдельного объекта предоставляется element_size, а total - это максимальное количество объектов, которое может храниться в массиве. Аргумент flags передается непосредственно вызовам выделения внутренней памяти. В текущем коде использование флагов для запроса большого объема памяти может привести к особенно неприятным побочным эффектам.
Сохранение данных в гибкий массив выполняется с помощью вызова:
int flex_array_put(struct flex_array *array, int element_nr, void *src, gfp_t flags);
Этот вызов скопирует данные из src в массив в позиции, указанной element_nr (которая должна быть меньше максимальной, указанной при создании массива). Если какие-либо выделения памяти должны быть выполнены, будут использоваться флаги. Возвращаемое значение равно нулю в случае успеха, в противном случае - отрицательный код ошибки.
Возможно, может потребоваться сохранение данных в гибком массиве при работе в некотором атомарном контексте; в этой ситуации спать в распределителе памяти было бы плохо. Этого можно избежать, используя GFP_ATOMIC для значения флагов, но часто есть лучший способ. Хитрость заключается в том, чтобы убедиться, что все необходимые выделения памяти сделаны перед входом в атомарный контекст, используя:
int flex_array_prealloc(struct flex_array *array, int start, int end, gfp_t flags);
Эта функция обеспечит выделение памяти для элементов, проиндексированных в диапазоне, определенном параметрами start и end. После этого вызов flex_array_put () для элемента в этом диапазоне гарантированно не блокируется.
Получение данных из массива выполняется с помощью:
void *flex_array_get(struct flex_array *fa, int element_nr);
Возвращаемое значение - указатель на элемент данных или NULL, если этот конкретный элемент никогда не был выделен.
Обратите внимание, что можно получить верный указатель на элемент, который никогда не сохранялся в массиве. Память для элементов массива выделяется по одной странице за раз; одиночное распределение может обеспечить память для нескольких смежных элементов. Код гибкого массива не знает, был ли записан конкретный элемент; он только знает, присутствует ли связанная память. Таким образом, вызов flex_array_get () для элемента, который никогда не был сохранен в массиве, может вернуть указатель на случайные данные. Если у вызывающей стороны нет отдельного способа узнать, какие элементы на самом деле были сохранены, было бы целесообразно, по крайней мере, добавить GFP_ZERO в аргумент flags, чтобы гарантировать, что все элементы обнуляются.
Нет способа удалить отдельный элемент из массива. Однако можно удалить все элементы с помощью вызова:
void flex_array_free_parts(struct flex_array *array);
Этот вызов освобождает все элементы, но оставляет сам массив на месте. Освобождение всего массива выполняется с помощью:
void flex_array_free(struct flex_array *array);
На момент написания этой статьи в основном ядре не было пользователей гибких массивов. Описанные здесь функции также не экспортируются в модули; это, вероятно, будет исправлено, когда кому-то возникнет необходимость в этом.