Технические вопросы и ответы QA1197

Выделение и совместное использование памяти с пространством пользователя от драйвера Набора 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.