WinCE6.0中应用程序如何直接访问物理空间
?在實(shí)際開發(fā)過(guò)程中,經(jīng)常希望能在應(yīng)用程序中直接讀寫設(shè)備的物理空間。以前在做WinCE6.0下的MEMMgr時(shí)通過(guò)秘密加載一個(gè)內(nèi)核態(tài)驅(qū)動(dòng)實(shí)現(xiàn)了這個(gè)需求。但這種方式有一個(gè)明顯的缺陷,每次讀寫都必須經(jīng)由它才能完成。如果只是讀取GPIO,那問題不算大。如果想通過(guò)這種方式實(shí)現(xiàn)視頻播放的加速就比較困難了。估計(jì)非但不能加速,反而會(huì)變得更慢。
????? 早先曾與ZL仔細(xì)的討論過(guò)這個(gè)問題,他當(dāng)時(shí)在WinCE6.0上移植TCPMP,發(fā)現(xiàn)播放視頻不太流暢,于是想通過(guò)直接寫顯存進(jìn)行加速。目的很明確,在應(yīng)用中申請(qǐng)一段虛擬空間,通過(guò)某種方法將其映射到顯存上,視頻解碼過(guò)程中直接往映射過(guò)的虛擬空間上寫。這種方法與使用GAPI有一點(diǎn)類似。
????? 實(shí)現(xiàn)這個(gè)需求,需要用到函數(shù)VirtualCopyEx()。看看幫助中關(guān)于它的說(shuō)明,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.
????? 據(jù)此基本可以確定,我們的確可以在應(yīng)用中申請(qǐng)一段虛擬空間,然后通過(guò)這個(gè)函數(shù)將其映射到某段物理空間上。其中目標(biāo)進(jìn)程是我們的應(yīng)用,而源進(jìn)程是NK.exe。為了實(shí)現(xiàn)在NK.exe中執(zhí)行VirtualCopyEx(),可以加載一個(gè)內(nèi)核態(tài)的驅(qū)動(dòng)。更為方便的方法是移植一個(gè)OALIOCTL,并在IOControl()中添加一個(gè)case。這樣,應(yīng)用程序在做內(nèi)存映射時(shí)就無(wú)需打開某個(gè)流驅(qū)動(dòng),直接調(diào)用KernelIoControl()即可。
????? OALIOCTL中添加的關(guān)鍵代碼如下。?
?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;
?????? 應(yīng)用程序中進(jìn)行內(nèi)存映射的關(guān)鍵代碼如下。
?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模擬器中應(yīng)用程序直接寫屏
19?PBYTE?pLCDBuf?=?(PBYTE)GetVirtual(0x33f00000,0x100000);
20?memset(pLCDBuf,0,0x100000);
21?
?????? 這種方法在WinCE6.0的模擬器中測(cè)試了一下,能達(dá)到預(yù)期的效果。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的WinCE6.0中应用程序如何直接访问物理空间的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云闪付坐公交车一分钱活动还有吗?2019
- 下一篇: patch文件制作