2015-04-29 3 views
2

Я пишу драйвер, которому необходимо выделить непинговый пул памяти, и эта память для обеспечения эффективности должна быть непосредственно доступна из программы usermode.Доступ к памяти ядра из пользовательского режима (Windows)

В записи драйвера я выделил некоторую память с этими двумя типа методов:

pMdl = IoAllocateMdl(NULL, 
        4096, 
        FALSE, 
        FALSE, 
        NULL); 
if(!pMdl) { 
    DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_INFO_LEVEL, "Error on IoAllocateMdl. Returning from driver early.\n"); 
    return STATUS_INSUFFICIENT_RESOURCES; 
} 
MmBuildMdlForNonPagedPool(pMdl); 
userMemory = (void *)MmMapLockedPagesSpecifyCache(pMdl, UserMode, MmWriteCombined, NULL, FALSE, LowPagePriority); 

и

userMemory = ExAllocatePoolWithTag(
       NonPagedPool, 
       4096, 
       POOL_TAG); 

Теперь я не хочу, чтобы выдать DeviceIOControl каждый раз, когда мне нужно для записи/чтения из этой памяти, но вместо этого я хочу сделать что-то вроде этого:

char* sharedMem; 
..... 
transactionResult = DeviceIoControl (hDevice, 
         (DWORD) IOCTL_MMAP, 
         NULL, 
         0, 
         sharedMem, 
         sizeof(int), 
         &bRetur, 
         NULL 
         ); 
..... 
sharedMem[0]='c'; 

Использование D eviceIoControl, чтобы получить адрес в памяти ядра, а затем использовать его напрямую, как, например, mmap под Linux.

Есть ли способ сделать это в Windows?

Я сделал это:

hMapFile = OpenFileMapping(
       FILE_MAP_ALL_ACCESS,  // Read/write access 
       TRUE, 
       "Global\\SharedMemory"); // Name of mapping object 

lastError = GetLastError(); 
if (hMapFile == NULL) 
{ 
    printf("Could not create file mapping object (%d).\n" ,GetLastError()); 
    return 1; 
} 
pBuf = (char*)MapViewOfFile(hMapFile,   // Handle to map object 
          FILE_MAP_ALL_ACCESS, // Read/write permission 
          0, 
          0, 
          4096); 

if (pBuf == NULL) 
{ 
    printf("Could not map view of file (%d).\n", GetLastError()); 
    CloseHandle(hMapFile); 
    return 1; 
} 
pBuf[0] = 'c'; 
pBuf[1] = '\n'; 
CloseHandle(hMapFile); 

И я создал представление в ядре, как это:

RtlInitUnicodeString(&name, L"\\BaseNamedObjects\\SharedMemory"); 
InitializeObjectAttributes(&oa, &name, 0, 0, NULL); 
ZwCreateSection(&hsection, SECTION_ALL_ACCESS, &oa, &Li, PAGE_READWRITE, SEC_COMMIT, NULL); 

ZwMapViewOfSection(hsection, NtCurrentProcess(), 
        &userMem, 0, MEM_WIDTH, NULL, 
        &j, ViewShare, 0, PAGE_READWRITE); 

Но в ядре, когда я прочитал память пусто: как может это будет?

+0

Начать здесь: http://stackoverflow.com/q/29358848/886887 –

+0

Хорошо, я пробовал использовать «ZwCreateSection» и т. Д., А у пользователя я использовал «MapViewOfFile». Карта открывается в пользовательской программе, я могу писать в ней, но когда я ее читаю из ядра, я ничего не написал. Я отредактировал вопрос. – AlexF

+0

Вы сопоставляете вид и читаете память из системного потока? (Обратите внимание также, что, поскольку вы хотите, чтобы не загружаемая память, использование раздела может оказаться неприемлемым. Вместо этого вы можете использовать MmMapLockedPagesSpecifyCache.) –

ответ

2

Я наконец понял, как это должно работать.

Сначала я создал структуру, подобную следующей.

typedef struct _MEMORY_ENTRY 
{ 
    PVOID pBuffer; 
} MEMORY_ENTRY, *PMEMORY_ENTRY; 

Это будет использоваться для возврата виртуального адреса из пространства ядра в пространство пользователя.

В DriverEntry я использовал

userMem = ExAllocatePoolWithTag(NonPagedPool, 
           MEM_WIDTH, 
           POOL_TAG); 

настроить Невыгружаемую память.

Затем я создал IOCTL, работающий в режиме DIRECT_OUT, что делает следующий фрагмент кода:

... 
PMDL   mdl = NULL; 
PVOID  buffer = NULL; 
MEMORY_ENTRY returnedValue; 
void*  UserVirtualAddress = NULL; 
... 
buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); // Gets safely the pointer for the output in the IRP 
mdl = IoAllocateMdl(userMem, MEM_WIDTH, FALSE, FALSE, NULL); // Allocate the memory descriptor list 
MmBuildMdlForNonPagedPool(mdl); // This is needed when we're managing NonPaged memory 
UserVirtualAddress = MmMapLockedPagesSpecifyCache(
         mdl, 
         UserMode, 
         MmNonCached, 
         NULL, 
         FALSE, 
         NormalPagePriority); // Return the virtual address in the context of 
               // the user space program who called the IOCTL 

returnedValue.pBuffer = UserVirtualAddress; 
RtlCopyMemory(buffer, 
      &returnedValue, 
      sizeof(PVOID)); // I copy the virtual address in the structure that will 
          // be returned to the user mode program by the IRP 

В программе пользовательского режима, мне просто нужно, чтобы к этому

transactionResult = DeviceIoControl(
         hDevice, 
         (DWORD) IOCTL_MMAP, 
         NULL, 
         0, 
         sharedMem, 
         sizeof(void*), 
         &bRetur, 
         NULL 
         ); 

В (MEMORY_ENTRY *) sharedMem-> pBuffer мы найдем область памяти, созданную и разделяемую ядром, непосредственно доступным ядру и пользовательской программой.

Я не написал его, но мы должны помнить, чтобы обернуть весь MmGetSystemAddressForMdlSafe (...) -----> RtlCopyMemory (...) в Try ... Кроме блока, потому что мы можем встретить различные проблемы здесь, которые могут в конечном итоге привести к ошибке BugCheck, чтобы быть более безопасным, чем жаль. В любом случае, если вы компилируете этот тип кода в проверенной среде, Microsoft AutocodeReview укажет на это.

Если кто-то нуждается в дополнительных разъяснениях, или если я написал что-то неправильно, просто сообщите мне, и я буду рад изменить этот пост.

Смежные вопросы