Книга: Разработка ядра Linux
Работа с данными процессоров на этапе выполнения
Работа с данными процессоров на этапе выполнения
Для динамического создания данных, связанных с процессорами, в ядре реализован специальный распределитель памяти, который имеет интерфейс, аналогичный kmalloc()
. Эти функции позволяют создать экземпляр участка памяти для каждого процессора в системе. Прототипы этих функций объявлены в файле <linux/percpu.h>
следующим образом.
void *alloc_percpu(type); / * макрос */
void *__alloc_percpu(size_t size, size_t align);
void free_percpu(const void*);
Функция alloc_percpu()
создает экземпляр объекта заданного типа (выделяет память) для каждого процессора в системе. Эта функция является оболочкой вокруг функции __alloc_percpu()
. Последняя функция принимает в качестве аргументов количество байтов памяти, которые необходимо выделить, и количество байтов, но которому необходимо выполнить выравнивание этой области памяти. Функция alloc_percpu()
выполняет выравнивание по той границе, которая используется для указанного типа данных. Такое выравнивание соответствует обычному поведению, как показано в следующем примере.
struct rabid_cheetah = alloc_percpu(struct rabid_cheetah);
что аналогично следующему вызову.
struct rabid_cheetah = __alloc_percpu(sizeof(struct rabid_cheetah),
__alignof__(struct rabid_cheetah));
Оператор __alignof__
— это расширение, предоставляемое компилятором gcc, который возвращает количество байтов, по границе которого необходимо выполнять выравнивание (или рекомендуется выполнять для тех аппаратных платформ, у которых нет жестких требований к выравниванию данных в памяти). Синтаксис этого вызова такой же как и у оператора sizeof()
. В примере, показанном ниже, для аппаратной платформы x86 будет возвращено значение 4.
__alignof__(unsigned long)
При передаче l-значения (левое значение, lvalue) возвращается максимально возможное выравнивание, которое может потребоваться для этого l-значения. Например, l-значение внутри структуры может иметь большее значение выравнивания, чем это необходимо для хранения того же типа данных за пределами структуры, что связано с особенностями выравнивания структур данных в памяти. Проблемы выравнивания более подробно рассмотрены в главе 19, "Переносимость".
Соответствующий вызов функции free_percpu()
освобождает память, которую занимают соответствующие данные на всех процессорах.
Функции alloc_percpu()
и __alloc_percpu()
возвращают указатель, который используется для косвенной ссылки на динамически созданные данные, связанные с каждым процессором в системе. Для простого доступа к данным ядро предоставляет два следующих макроса.
get_cpu_ptr(ptr); /* возвращает указатель типа void на данные,
соответствующие параметру ptr, связанные с текущим процессом */
put_cpu_ptr(ptr); /* готово, разрешаем вытеснение кода в режиме ядра */
Макрос get_cpu_ptr()
возвращает указатель на экземпляр данных, связанных с текущим процессором. Этот вызов также запрещает вытеснение кода в режиме ядра, которое снова разрешается вызовом функции put_cpu_ptr()
.
Рассмотрим пример использования этих функций. Конечно, этот пример не совсем логичный, потому что память обычно необходимо выделять один раз (например, в некоторой функции инициализации), использовать ее в разных необходимых местах, а затем освободить также один раз (например, в некоторой функции, которая вызывается при завершении работы). Тем не менее этот пример позволяет пояснить особенности использования.
void *percpu_ptr;
unsigned long *foo;
percpu_ptr = alloc_percpu(unsigned long);
if (!ptr)
/* ошибка выделения памяти ... */
foo = get_cpu_ptr(percpu_ptr);
/* работаем с данными foo ... */
put_cpu_ptr(percpu_ptr);
Еще одна функция — per_cpu_ptr()
— возвращает экземпляр данных, связанных с указанным процессором.
per_cpu_ptr(ptr, cpu);
Эта функция не запрещает вытеснение в режиме ядра. Если вы "трогаете" данные, связанные с другим процессором, то, вероятно, необходимо применить блокировки.
- Работа с данными, связанными с процессорами, на этапе компиляции
- Права для выполнения резервного копирования
- Практическая работа 53. Запуск Access. Работа с объектами базы данных
- Лекция 15. Работа с базами данных
- Работа с ресурсами локальной сети
- Эффективная работа с временными файлами сортировки
- Ускоренная работа с индексами
- HR-брендинг: Работа с поколением Y, новые инструменты для коммуникации, развитие корпоративной культуры и еще 9 эффектив...
- Упражнения для самостоятельного выполнения
- Безопасная работа с внешними таблицами
- Работа со строками
- Распараллеливание на несколько процессоров