WinCE6.0中应用程序如何直接访问物理空间
?在實際開發過程中,經常希望能在應用程序中直接讀寫設備的物理空間。以前在做WinCE6.0下的MEMMgr時通過秘密加載一個內核態驅動實現了這個需求。但這種方式有一個明顯的缺陷,每次讀寫都必須經由它才能完成。如果只是讀取GPIO,那問題不算大。如果想通過這種方式實現視頻播放的加速就比較困難了。估計非但不能加速,反而會變得更慢。
????? 早先曾與ZL仔細的討論過這個問題,他當時在WinCE6.0上移植TCPMP,發現播放視頻不太流暢,于是想通過直接寫顯存進行加速。目的很明確,在應用中申請一段虛擬空間,通過某種方法將其映射到顯存上,視頻解碼過程中直接往映射過的虛擬空間上寫。這種方法與使用GAPI有一點類似。
????? 實現這個需求,需要用到函數VirtualCopyEx()。看看幫助中關于它的說明,This function dynamically maps a virtual address to a physical address by creating a new page-table entry.This function is callable in kernel mode and in user mode, when the source and destination process handles are the active process.This function is similar to?VirtualCopy, except?VirtualCopyEx?requires handles to the source and destination process.
????? 據此基本可以確定,我們的確可以在應用中申請一段虛擬空間,然后通過這個函數將其映射到某段物理空間上。其中目標進程是我們的應用,而源進程是NK.exe。為了實現在NK.exe中執行VirtualCopyEx(),可以加載一個內核態的驅動。更為方便的方法是移植一個OALIOCTL,并在IOControl()中添加一個case。這樣,應用程序在做內存映射時就無需打開某個流驅動,直接調用KernelIoControl()即可。
????? OALIOCTL中添加的關鍵代碼如下。?
?1?typedef?struct?{?2?????void*????pvDestMem;
?3?????DWORD????dwPhysAddr;
?4?????DWORD????dwSize;
?5?}?VIRTUAL_COPY_EX_DATA;
?6?
?7?#define?IOCTL_VIRTUAL_COPY_EX?CTL_CODE?(FILE_DEVICE_UNKNOWN,3333,METHOD_BUFFERED,FILE_ANY_ACCESS)
?8?
?9?
10?case?IOCTL_VIRTUAL_COPY_EX:
11?{
12?????VIRTUAL_COPY_EX_DATA?*p?=?(VIRTUAL_COPY_EX_DATA*)pInBuf;
13?????HANDLE?hDst?=?(HANDLE)GetDirectCallerProcessId();
14?????HANDLE?hSrc?=?(HANDLE)GetCurrentProcessId();
15?????fRet?=?VirtualCopyEx(hDst,p->pvDestMem,hSrc,(LPVOID)p->dwPhysAddr,p->dwSize,
16? PAGE_READWRITE|PAGE_PHYSICAL|PAGE_NOCACHE);
17?}break;
?????? 應用程序中進行內存映射的關鍵代碼如下。
?1?volatile?LPVOID?GetVirtual(DWORD?dwPhyBaseAddress,?DWORD?dwSize)?2?{
?3?????volatile?LPVOID?pVirtual;
?4?????VIRTUAL_COPY_EX_DATA?vced;
?5?????
?6?????if(dwPhyBaseAddress&0xFFF)
?7?????{
?8?????????return?NULL;
?9?????}
10?????vced.dwPhysAddr?=?dwPhyBaseAddress>>8;
11?????pVirtual?=?VirtualAlloc(0,dwSize,MEM_RESERVE,PAGE_NOACCESS);
12?????vced.pvDestMem?=?pVirtual;
13?????vced.dwSize?=?dwSize;
14?????KernelIoControl(IOCTL_VIRTUAL_COPY_EX,&vced,?sizeof(vced),?NULL,?NULL,?NULL);
15?????return?pVirtual;
16?}
17?
18?//?WinCE6.0模擬器中應用程序直接寫屏
19?PBYTE?pLCDBuf?=?(PBYTE)GetVirtual(0x33f00000,0x100000);
20?memset(pLCDBuf,0,0x100000);
21?
?????? 這種方法在WinCE6.0的模擬器中測試了一下,能達到預期的效果。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的WinCE6.0中应用程序如何直接访问物理空间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云闪付坐公交车一分钱活动还有吗?2019
- 下一篇: patch文件制作