Windows CE下訪問實體記憶體的方法——轉載

來源:互聯網
上載者:User
Windows CE下訪問實體記憶體的方法

轉載來自http://www.cppblog.com/milkyway/articles/18269.html

嵌入式裝置與案頭PC的一個顯著不同是它的應用程式中通常需要直接存取某一段實體記憶體,這在驅動程式中對實體記憶體的訪問尤為重要,尤其是像ARM體繫結構下,I/O連接埠也被映射成某一個實體記憶體地址。因此,與案頭版本Windows相比,Windows CE提供了相對簡單的實體記憶體訪問方式。無論是驅動程式還是應用程式都可以通過API訪問某一段實體記憶體。
Windows CE的有些函數中需要用到實體記憶體結構體PHYSICAL_ADDRESS, Windows CE在ceddk.h中定義了PHYSICAL_ADDRESS,它其實是LARGE_INTEGER類型,其定義如下:
// in ceddk.h
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
// in winnt.h
typedef union _LARGE_INTEGER{
  struct{
    DWORD LowPart;
    LONG HighPart;
  };
  LONGLONG QuadPart;
} LARGE_INTEGER;
可見,Windows CE中用64個Bit來代表物理地址,對於大多數32位的CPU而言,只需要把它的HighPart設定為0就可以了。
如果要直接存取某一個地址的實體記憶體,Windows CE提供了VirtualAlloc()和VirtualCopy()函數,VirtualAlloc負責在虛擬記憶體空間內保留一段虛擬記憶體,而VirtualCopy負責把一段實體記憶體和虛擬記憶體綁定,這樣,最終對實體記憶體的訪問還是通過虛擬位址進行。它們的聲明如下:
// 申請虛擬記憶體
LPVOID VirtualAlloc(
  LPVOID lpAddress,         // 希望的虛擬記憶體起始地址
  DWORD dwSize,                 // 以位元組為單位的大小
  DWORD flAllocationType,     // 申請類型,分為Reserve和Commit
  DWORD flProtect             // 存取權限
);
// 把實體記憶體綁定到虛擬位址空間
BOOL VirtualCopy( 
  LPVOID lpvDest,             // 虛擬記憶體的目標地址
  LPVOID lpvSrc,             // 實體記憶體地址
  DWORD cbSize,                 // 要綁定的大小
  DWORD fdwProtect             // 存取權限
);
VirtualAlloc對虛擬記憶體的申請分為兩步,保留MEM_RESERVE和提交MEM_COMMIT。其中MEM_RESERVE只是在進程的虛擬位址空間內保留一段,並不分配實際的實體記憶體,因此保留的虛擬記憶體並不能被應用程式直接使用。MEM_COMMIT階段才真正的為虛擬記憶體分配實體記憶體。
下面的代碼顯示了如何使用VirtualAlloc和VirtualCopy來訪問實體記憶體。因為VirtualCopy負責把一段實體記憶體和虛擬記憶體綁定,所以VirtualAlloc的時候只需要對記憶體保留,沒有必要提交。
FpDriverGlobals = 
(PDRIVER_GLOBALS) VirtualAlloc(
    0, 
    DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE, 
    MEM_RESERVE, 
    PAGE_NOACCESS);
 if (FpDriverGlobals == NULL) {
    ERRORMSG(DRIVER_ERROR_MSG, (TEXT(" VirtualAlloc failed!/r/n")));
    return;
 }
 else {
    if (!VirtualCopy(
    (PVOID)FpDriverGlobals, 
    (PVOID)(DRIVER_GLOBALS_PHYSICAL_MEMORY_START), 
    DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE, 
    (PAGE_READWRITE | PAGE_NOCACHE))) {
       ERRORMSG(DRIVER_ERROR_MSG, (TEXT("VirtualCopy failed!/r/n")));
       return;
    }
 }
CEDDK還提供了函數MmMapIoSpace用來把一段實體記憶體直接映射到虛擬記憶體。用MmMapIoSpace申請的記憶體要用MmUnmapIoSpace釋放,此函數的原形如下:
PVOID MmMapIoSpace( 
  PHYSICAL_ADDRESS PhysicalAddress,     // 起始物理地址
  ULONG NumberOfBytes,                     // 要映射的位元組數
  BOOLEAN CacheEnable                     // 是否緩衝
);

VOID MmUnmapIoSpace( 
  PVOID BaseAddress,                     // MmMapIoSpace返回的起始虛擬位址
  ULONG NumberOfBytes                     // 
);
其實,MmMapIoSpace函數內部也是調用VirtualAlloc和VirtualCopy函數來實現物理地址到虛擬位址的映射的。MmMapIoSpace函數的原代碼是公開的,我們可以從%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/CEDDK/DDK_MAP/ddk_map.c得到。從MmMapIoSpace的實現我們也可以看出VirtualAlloc和VirtualCopy的用法:
PVOID MmMapIoSpace (
    IN PHYSICAL_ADDRESS PhysicalAddress,
    IN ULONG NumberOfBytes,
    IN BOOLEAN CacheEnable
    )
{
PVOID pVirtualAddress; ULONGLONG SourcePhys; 
ULONG SourceSize; BOOL bSuccess;

    SourcePhys = PhysicalAddress.QuadPart & ~(PAGE_SIZE - 1);
    SourceSize = NumberOfBytes + (PhysicalAddress.LowPart & (PAGE_SIZE - 1));

    pVirtualAddress = VirtualAlloc(0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
    if (pVirtualAddress != NULL)
    {
        bSuccess = VirtualCopy(
            pVirtualAddress, (PVOID)(SourcePhys >> 8), SourceSize,
            PAGE_PHYSICAL | PAGE_READWRITE | (CacheEnable ? 0 : PAGE_NOCACHE));

        if (bSuccess) {
            (ULONG)pVirtualAddress += PhysicalAddress.LowPart & (PAGE_SIZE - 1);
        }
        else {
            VirtualFree(pVirtualAddress, 0, MEM_RELEASE);
            pVirtualAddress = NULL;
        }
    }
    return pVirtualAddress;
}
此外,Windows CE還供了AllocPhysMem函數和FreePhysMem函數,用來申請和釋放一段連續的實體記憶體。函數可以保證申請的實體記憶體是連續的,如果函數成功,會返回虛擬記憶體的控制代碼和實體記憶體的起始地址。這對於DMA裝置尤為有用。在這裡就不詳細介紹了,讀者可以參考Windows CE的聯機文檔。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.