Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 3.6. Использование памяти в scull
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
Использование памяти в scull hardorsoft 19.11.10 в 10:18 |
|
|
Перед знакомством с операциями read и write мы рассмотрим получше, как и почему scull выполняет выделение памяти. "Как" необходимо, чтобы глубоко понимать код, а "почему" демонстрирует варианты выбора, который должен делать автор драйвера, хотя scull, безусловно, не типичен, как устройство. hardorsoft 19.11.10 в 10:18 |
||
|
Этот раздел имеет дело только с политикой распределения памяти в scull и не показывает навыки аппаратного управления, необходимые для написания реальных драйверов. Эти навыки будут введены в Главах 9 и 10. Таким образом, вы можете пропустить этот раздел, если вы не заинтересованы в понимании внутренней работы ориентированного на память драйвера scull. hardorsoft 19.11.10 в 10:19 |
||
|
Область памяти, используемая scull, также называемая устройством, имеет переменную длину. Чем больше вы пишете, тем больше она растёт; укорачивание производится перезаписью устройства более коротким файлом. hardorsoft 19.11.10 в 10:19 |
||
|
Драйвер scull знакомит с двумя основными функциями, используемыми для управления памятью в ядре Linux. Вот эти функции, определённые в <linux></linux>slab.h>: hardorsoft 19.11.10 в 10:19 |
||
|
void *kmalloc(size_t size, int flags); hardorsoft 29.10.10 в 23:07 |
||
|
Вызов kmalloc пытается выделить size байт памяти; возвращаемая величина - указатель на эту память или NULL, если выделение не удаётся. Аргумент flags используется, чтобы описать, как должна быть выделена память; мы изучим эти флаги подробно в Главе 8. Сейчас мы всегда используем GFP_KERNEL. Выделенная память должна быть освобождена kfree. Вы никогда не должны передавать kfree что-то, что не было получено от kmalloc. Однако, правомерно передать kfree указатель NULL. hardorsoft 19.11.10 в 10:19 |
||
|
kmalloc это не самый эффективный способ распределения больших областей памяти (смотрите Главу 8), поэтому сделанный для scull выбор не особенно умный. Исходный код для изящной реализации будет более трудным для восприятия и целью этого раздела является показать read и write, а не управление памятью. Вот почему код просто использует kmalloc и kfree, без пересортировки выделенных целых страниц, хотя такой подход был бы более эффективным. hardorsoft 19.11.10 в 10:20 |
||
|
С другой стороны, мы не хотим ограничивать размер области "устройства" по философским и практическим соображениям. Философски, это всегда плохая идея - поставить произвольные ограничения на управляемые объекты данных. Практически, scull может быть использован для временного поедания всей памяти вашей системы в целях выполнения тестов в условиях малого количества памяти. Выполнение таких тестов могло бы помочь вам понять внутренности системы. Вы можете использовать команду cp /dev/zero /dev/scull0, чтобы съесть всю реальную оперативную память с помощью scull, и вы можете использовать утилиту dd, чтобы выбрать, какой объём данных скопируется на устройство scull. hardorsoft 19.11.10 в 10:20 |
||
|
В scull каждое устройство представляет собой связный список указателей, каждый из которых указывает на структуру scull_dev. По умолчанию каждая такая структура может ссылаться на более четыре миллиона байт через массив промежуточных указателей. Реализованный исходник использует массив из 1000 указателей на области по 4000 байта. Мы называем каждую область памяти квантом (quantum), а массив (или его длину) - набором квантов (quantum set). Устройств scull и его области памяти показаны на Рисунке 3-1. hardorsoft 19.11.10 в 10:20 |
||
|
Рисунок 3-1. Схема устройства scull hardorsoft 19.11.10 в 10:20 |
||
|
Выбранные числа таковы, что запись одного байта в scull потребляет 8000 или 12000 тысяч байт памяти: 4000 для кванта и 4000 или 8000 для набора квантов (в зависимости от того, является ли на целевой платформе указатель 32-х разрядным или 64-х разрядным). Если, наоборот, вы пишете большое количество данных, накладные расходы на связный список не такие большие. Существует только один список элементов для каждых четырёх мегабайт данных и максимальный размер устройства ограничен объёмом памяти компьютера. hardorsoft 19.11.10 в 10:21 |
||
|
Выбор соответствующего значения для кванта и квантового набора - это вопрос политики, а не механизма, и их оптимальные размеры зависят от того, как используется устройство. Таким образом, драйвер scull не должен заставлять использовать какие-то определённые значения для размеров кванта и набора квантов. В scull пользователь может изменять значения размеров несколькими способами: путём изменения макросов SCULL_QUANTUM и SCULL_QSET в scull.h во время компиляции, устанавливая целочисленные значения scull_quantum и scull_qset во время загрузки модуля или изменяя текущее значение и значение по умолчанию с помощью ioctl во время выполнения. hardorsoft 19.11.10 в 10:21 |
||
|
Использование макроса и целой величины позволяют делать конфигурацию и во время компиляции и во время загрузки и напоминают выбор старшего номера. Мы используем эту технику для любого, произвольного или связанного с политикой, значения в драйвере. hardorsoft 19.11.10 в 10:21 |
||
|
Остался только вопрос, как были выбраны номера по умолчанию. В данном случае проблема состоит в нахождении лучшего соотношения между потерей памяти в результате полузаполненного кванта и квантового набора и накладных расходов на выделение, освобождения, и указатель связывания, что происходит, если кванты и наборы малы. Кроме того, должен быть принят во внимание внутренний дизайн kmalloc. (Однако, мы не будем исследовать это теперь; внутренности kmalloc рассматриваются в Главе 8.) Выбор чисел по умолчанию делается из предположения, что во время тестирования в scull могут быть записаны большие объёмы данных, хотя при обычном использовании устройства, скорее всего, будут передаваться только несколько килобайт данных. hardorsoft 19.11.10 в 10:22 |
||
|
Мы уже видели структуру scull_dev, которая является внутренним представлением нашего устройства. Это поля структуры quantum и qset, содержащие квант и размер квантового набора устройства, соответственно. Фактические данные, однако, отслеживаются другой структурой, которую мы назвали структурой scull_qset: hardorsoft 19.11.10 в 10:22 |
||
|
struct scull_qset { hardorsoft 29.10.10 в 23:07 |
||
|
Следующий фрагмент кода показывает на практике, как структуры scull_dev и scull_qset используются для хранения данных. Функция scull_trim отвечает за освобождение всей области данных и вызывается из scull_open, когда файл открывается для записи. Это просто прогулка по списку и освобождение любого кванта и набора квантов при их нахождении. hardorsoft 19.11.10 в 10:22 |
||
|
int scull_trim(struct scull_dev *dev) hardorsoft 19.11.10 в 10:22 |
||
|
scull_trim также используется в функции очистки модуля, чтобы вернуть системе память, используемую scull. hardorsoft 19.11.10 в 10:23 |
