Выделение и совместное использование памяти с пространством пользователя от драйвера Набора I/O
Q: Мой драйвер ядра Набора I/O отображает память на использование пространства пользователя IOMemoryDescriptor::createMappingInTask. Но createMappingInTask сбои и возвраты NULL. Как драйвер должен совместно использовать память с пользовательским процессом?
A: Мой драйвер ядра Набора I/O отображает память на использование пространства пользователя IOMemoryDescriptor::createMappingInTask. Но createMappingInTask сбои и возвраты NULL. Как драйвер должен совместно использовать память с пользовательским процессом?
IOMemoryDescriptor::createMappingInTask возвраты NULL потому что буфер не мог быть отображен в соответствии с требованиями. Существует несколько причин, почему это может произойти.
Набор I/O использует ядро zalloc объедините как его маленькое malloc ресурс. Это дает писателям драйвера быстрые выделения для локального использования. Это очень важно для new операторы и недолгие буферы.
Проблема возникает, когда писатель драйвера пытается совместно использовать память с пространством пользователя, забывая, что зональное средство выделения разработано для временных и очень частных выделений. Под покрытиями, средства выделения Набора I/O такой как IOMalloc, IOMallocAligned, и IOMallocContiguous может использовать это зональное средство выделения для улучшения производительности частых, маленьких выделений.
Кроме того, так как отображение является понятием виртуальной памяти, карты всегда измеряются к целому числу страниц.
Предпочтительный способ выделить память ядра для совместного использования состоит в том, чтобы выделить буфер и дескриптор памяти вместе с помощью IOBufferMemoryDescriptor как показано в Перечислении 1.
Использование перечисления 1 IOBufferMemoryDescriptor.
IOBufferMemoryDescriptor* memDesc; memDesc = IOBufferMemoryDescriptor::withOptions( kIODirectionOutIn | kIOMemoryKernelUserShared, alloc_bytes, page_size ); |
kIOMemoryKernelUserShared опция гарантирует, что буфер отображается на границе страницы.
Менее - предпочтительная опция состоит в том, чтобы запросить целое число страниц от IOMallocAligned или IOMallocContiguous. В этом случае любой из этих интерфейсов возвратит буфер, способный к тому, чтобы быть совместно использованным.
Как только Вы выделили свой буфер с помощью любого из этих методов, это может быть совместно использовано с использованием пространства пользователя IOMemoryDescriptor::createMappingInTask.
Строго рекомендуется создать буферы, совместно использованные ядром и пространством пользователя от ядра. Однако существуют случаи, где это не практично, таково как драйвер, читающий из или пишущий в создаваемые из приложения буферы. В той ситуации, createMappingInTask может перестать работать по другой причине. createMappingInTask может только создать отображения для памяти, описанной единственным объектом VM. Однако диапазон памяти выделяется в типичном использовании вида malloc- основанные функции могли бы быть описаны больше чем одним объектом VM.
Для выделения памяти в пространстве пользователя, которое, как гарантируют, будет описано только единственным объектом VM используйте анонимный mmap как показано в Перечислении 2.
Использование перечисления 2 анонимного mmap.
#include <sys/mman.h>
size_t bigBufferLen;
uint8_t *bigBuffer;
bigBufferLen = 54321;
// Use anonymous mmap to ensure we get a single VM object.
bigBuffer = (uint8_t *) mmap(NULL, bigBufferLen, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
if (bigBuffer == MAP_FAILED) {
perror("mmap() call error:");
}
else {
// Success.
printf("buffer is created @ %p\n", bigBuffer);
} |
История версии документа
| Дата | Примечания |
|---|---|
| 13.10.2008 | Модернизированное содержание и и внесло редакционные изменения. |
| 13.09.2002 | Новый документ, описывающий предпочтительный метод для выделения и совместного использования буферов в драйвере ядра Набора I/O. |