Нужно ли предварительно выделять указатель списка разброса, переданный функции sg_init_table()?

В модуле драйвера PCI ядра Linux.
У нас есть функция для инициализации списка разброса dma:
sg_init_table(struct scatterlist *sg, unsigned int nents);

Для указателя списка рассеивания sg мы должны выделить для него немного памяти, например, используя kcalloc; или мы просто объявляем его как: struct scatterlist * sg и затем передаем его sg_init_table?

Спасибо за продвижение.


person Cong Li    schedule 17.05.2016    source источник


Ответы (1)


Для вызывающего объекта нет никакой ценности в передаче неинициализированного или недопустимого значения указателя любого типа любой функции, кроме простого дополнения списка аргументов функции аргументом ожидаемого типа. Вызывающий объект не передает функции никакой действительной информации таким образом, и он не предоставляет функции для возврата какой-либо информации. В частности, он не предоставляет механизма, с помощью которого вызываемая функция может выделять память от имени вызывающего. Указатели, как и любые другие аргументы, передаются по значению, поэтому, когда функция изменяет один из своих параметров, это невидимо для вызывающей программы.

Представленная вами сигнатура функции имеет смысл только для инициализации существующего объекта типа struct scatterlist или массива таких объектов, или выделенной памяти, предназначенной для хранения такого объекта или массива. Если эта структура должна быть динамически выделена, тогда да, вызывающая сторона должна выполнить выделение и передать указатель на результат.

Однако при некоторых обстоятельствах вызывающей стороне может быть удобно объявить локальный объект struct и передать его адрес примерно так:

struct scatterlist sl;

sg_init_table(&sl, DEFAULT_NENTS);

или, может быть

struct scatterlist sl[DEFAULT_NENTS];

sg_init_table(sl, DEFAULT_NENTS);

, в зависимости от деталей того, как должен вести себя sg_init_table().

Точно так же может быть удобно передать адрес глобальной структуры. Помните о времени жизни локальных объектов — если они не объявлены static, локальные объекты не сохраняются после завершения вызова функции, в которой они были объявлены.

person John Bollinger    schedule 17.05.2016
comment
Разве ваше локальное хранилище не должно быть объявлено как struct scatterlist sl[DEFAULT_NENTS];? - person Ian Abbott; 17.05.2016
comment
@IanAbbott, возможно, но не обязательно; роль второго параметра функции неясна. По сравнению с тем, что я намеревался написать, я исключил оператор & (теперь исправлено), но ваш вариант может лучше соответствовать реализации функции. Я добавил его как альтернативу. - person John Bollinger; 17.05.2016
comment
Реализация достаточно проста для просмотра. Он находится в lib/scatterlist.c в исходниках ядра. Ваш struct scatterlist sl; sg_init_table(&sl, DEFAULT_NENTS); уничтожит память ядра, если DEFAULT_NENTS больше 1. И точечный список с одной записью не очень полезен, так как в этом случае вы могли бы также выполнить одну передачу (а не передачу с разбросом). - person Ian Abbott; 19.05.2016