WINCE驅(qū)動(dòng)分析以及MapPtrToProcess 用法 3_第1頁(yè)
WINCE驅(qū)動(dòng)分析以及MapPtrToProcess 用法 3_第2頁(yè)
WINCE驅(qū)動(dòng)分析以及MapPtrToProcess 用法 3_第3頁(yè)
WINCE驅(qū)動(dòng)分析以及MapPtrToProcess 用法 3_第4頁(yè)
WINCE驅(qū)動(dòng)分析以及MapPtrToProcess 用法 3_第5頁(yè)
已閱讀5頁(yè),還剩14頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

精品文檔-下載后可編輯WINCE驅(qū)動(dòng)分析以及MapPtrToProcess用法3

對(duì)于wince驅(qū)動(dòng)或者linux驅(qū)動(dòng),或者其他操作系統(tǒng)驅(qū)動(dòng)。基本上就是兩個(gè)部分,1,訪問(wèn)硬件寄存器。2,編寫(xiě)操作系統(tǒng)接口。從訪問(wèn)硬件上來(lái)說(shuō),可以有總線驅(qū)動(dòng),一般的I/O驅(qū)動(dòng)等。從操作系統(tǒng)來(lái)說(shuō),就wince而言,可以分為,built-driver和streamdriver,也可以從另外的一個(gè)角度,分為L(zhǎng)ayeredDeviceDriver和Monolithicdriver??傊?,驅(qū)動(dòng)的叫法和種類(lèi)很多,一般都要根據(jù)具體開(kāi)發(fā)的驅(qū)動(dòng)再仔細(xì)研究。其實(shí)大多數(shù)工作都是要看E文的datasheet,了解硬件的工作原理,對(duì)CPU工作方式有一定的理解,問(wèn)題就不大了。這里簡(jiǎn)單介紹一下如何編寫(xiě)wince下的streamdriver。

首先講一下框架,很簡(jiǎn)單,按照wince的聯(lián)機(jī)幫助文檔,完成下面的接口函數(shù)就好了。

XXX_Close(DeviceManager)

XXX_Deinit(DeviceManager)

XXX_Init(DeviceManager)

XXX_IOControl(DeviceManager)

XXX_Open(DeviceManager)

……

   無(wú)非就是一些讀寫(xiě),IOCTL,POWER管理的接口而已。

   通過(guò)前面的學(xué)習(xí)我們已經(jīng)對(duì)MapPtrToProcess用法WINCE驅(qū)動(dòng)分析有了初步了解,接下來(lái)我們要使用下面的應(yīng)用程序代碼測(cè)試這個(gè)driver,我們將使用evc編譯。

#include<windows.h>

#include<Windev.h>

#include<stdio.h>

#include"objbase.h"

#include"initguid.h"

#include"foo.h"

//chardata1[10];

int WinMain(void)

{

HANDLEhnd;

COPY_STRUCTcs[1];

inti;

//staticchardata1[10];

autochardata1[10];

autochardata2[10];

staticchar*p1,*p2;

//cs.pBuffer1=(char*)malloc(10);

//cs.pBuffer2=(char*)malloc(10);

//cs.nLen=10;

p1=(char*)LocalAlloc(LPTR,10);

p2=(char*)malloc(10);

//cs[0].pBuffer1=(char*)malloc(10);

//cs[0].pBuffer2=(char*)malloc(10);

cs[0].pBuffer1=&data1[0];

cs[0].pBuffer2=&data2[0];

cs[0].nLen=10;

memset(cs[0].pBuffer1,'a',10);

hnd=CreateFile(FOO_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,0,0,NULL);

if(hnd==NULL)

{

printf("OpendevicefALIed!\n");

return;

}

DeviceIoControl(hnd,IOCTL_FOO_XER,&cs[0],sizeof(COPY_STRUCT),NULL,0,NULL,NULL);

//for(i=0;i<9;i++)

//{

//printf("%c",*(cs.pBuffer2++));

//}

printf("\n");

CloseHandle(hnd);

// free(cs[0].pBuffer1);

// free(cs[0].pBuffer2);

}

我們可以通過(guò)evc的單步調(diào)試看結(jié)果。等到一切都完成了,我們就來(lái)看看系統(tǒng)是怎么工作的吧,從應(yīng)用程序開(kāi)始,

CreateFile(FOO_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,NULL,0,0,NULL);

會(huì)調(diào)用到

FOO_Open(DWORDdwContext,DWORDAccessCode,DWORDShareMode)

而FOO_DEV_NAME名字定義在foo.h里面。

#define      FOO_DEV_NAMEL"Foo1:"

注意后面是1,這個(gè)是和注冊(cè)表的這一項(xiàng)匹配的,去注冊(cè)表確認(rèn)下以保證萬(wàn)無(wú)一失。

"Index"=dword:1

當(dāng)調(diào)用CreateFile發(fā)生了什么呢?slot之間的轉(zhuǎn)換,一系列系統(tǒng)操作后,調(diào)用到我們自己的driver函數(shù)FOO_Open,在這個(gè)函數(shù)里我們返回了一個(gè)句柄,它可以用來(lái)存儲(chǔ)我們的自己driver的信息。在其它I/O操作中可以使用。

Driver什么時(shí)候加載的?在注冊(cè)表里,devicemanager會(huì)一個(gè)個(gè)的加載,會(huì)調(diào)用到FOO_Init函數(shù)。這個(gè)函數(shù)返回一個(gè)指針,在調(diào)用FOO_Open又傳回來(lái)了,這樣我們就可以實(shí)現(xiàn)初始化一些自己driver的東西。

接著我們來(lái)說(shuō)一個(gè)重要的函數(shù),

DeviceIoControl(hnd,IOCTL_FOO_XER,&cs[0],sizeof(COPY_STRUCT),NULL,0,NULL,NULL);

調(diào)用到

FOO_IOControl

走到這里

caseIOCTL_FOO_XER:

if((pInBuf==NULL))

{

SetLastError(ERROR_INVALID_PARAMETER);

break;

}

pcs=(COPY_STRUCT*)pInBuf;

__try{

pMap1= MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());

pMap2= MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());

DEBUG_OUT(1,(TEXT("+FOO_IOControl(0x%x,0x%x)\r\n"),pcs->pBuffer1,pcs->pBuffer2));

memcpy(pcs->pBuffer2,pcs->pBuffer1,pcs->nLen);

bResult=TRUE;

}

__except(EXCEPTION_EXECUTE_HANDLER){

DEBUG_OUT(1,(TEXT("Exception:FOO_IOCTL\r\n")));

break;

}

break;

default:

break;

這里又很多東西要研究,這里我就不做詳細(xì)解說(shuō)了。

從應(yīng)用程序傳來(lái)的參數(shù)有,controlcode,IOCTL_FOO_XER和一個(gè)重要的輸入?yún)?shù)&cs[0],它是一個(gè)指針。cs是一個(gè)結(jié)構(gòu)體,定義在FOO.H

typedefstruct{

char*pBuffer1;

char*pBuffer2;

intnLen;

}COPY_STRUCT;

而且這個(gè)結(jié)構(gòu)體里有兩個(gè)指針。

DeviceIoControl傳過(guò)來(lái)的指針可以用嗎?它包含的兩個(gè)指針可以直接用嗎?

按照PB連接幫助文檔看,

Theoperatingsystem(OS)managespointerspasseddirectlyasparameters.Driversmustmapallpointerscontainedinstructures.DeviceIoControlbuffersareoftenstructuresthatcontaindata,someofwhichmightbepointers.

YoucanmapapointercontainedinastructurebycallingMapPtrToProcess,settingthefirstparametertothepointer,andthensettingthesecondparametertoGetCallerProcess.

cs指針已經(jīng)映射好了,但是它指向的結(jié)構(gòu)里的指針我們需要自己使用MapPtrToProcess函數(shù)映射。

這也就是:

pMap1= MapPtrToProcess(pcs->pBuffer1,GetCallerProcess());

pMap2= MapPtrToProcess(pcs->pBuffer2,GetCallerProcess());

的由來(lái),可是后面的代碼沒(méi)有使用pMap1,pMap2。而是直接使用:

memcpy(pcs->pBuffer2,pcs->pBuffer1,pcs->nLen);

而且它還工作了,沒(méi)有出現(xiàn)exception。很奇怪。我次在一個(gè)家伙的代碼里看見(jiàn)這種情況,很吃驚,但是它工作的很好,是文檔出錯(cuò)了?還是別的地方出錯(cuò)了呢?

那么我們就來(lái)分析一下吧。首先我們看看應(yīng)用程序的代碼:

COPY_STRUCTcs[1];

autochardata1[10];

autochardata2[10];

cs結(jié)構(gòu)和data1,data2數(shù)組都是自動(dòng)變量,存放在堆棧里。假設(shè)這個(gè)應(yīng)用程序被加載到0x18000000位置的slot里,那么他們的地址都是0x18XXXXXX。不熟悉wincememoryarchitecture的可以看看資料,了解一下slot。當(dāng)調(diào)用了。

DeviceIoControl,按照文檔的說(shuō)法,cs指針得到了轉(zhuǎn)換,因?yàn)閺膽?yīng)用程序的進(jìn)程轉(zhuǎn)到了device.exe進(jìn)程,而device進(jìn)程又是當(dāng)前的運(yùn)行的進(jìn)程,被映射到了slot0,系統(tǒng)負(fù)責(zé)轉(zhuǎn)換cs指針。而cs包含的pBuffer1和pBuffer2是沒(méi)有映射不能直接用的。

事實(shí)上,我們傳過(guò)來(lái)的指針根本就是不需要映射,因?yàn)樗麄兌际?x18xxxxxx,在應(yīng)用程序的slot里,所以只要device.exe有訪問(wèn)應(yīng)用程序的權(quán)限,就可以了。而這個(gè)權(quán)限,系統(tǒng)已經(jīng)幫我們?cè)O(shè)置好了。

那什么情況下要自己映射呢?

如果應(yīng)用程序在定義data1和data2使用static關(guān)鍵字,或者使用LocalAlloc,HeapAlloc的時(shí)候,一定要自己映射cs里的指針。

在應(yīng)用程序里這樣寫(xiě):

cs.pBuffer1=(char*)malloc(10);

cs.pBuffer2=(char*)malloc(10);

cs.nLen=10;

如果不使用MapPtrToProcess完成映射,那就出現(xiàn)dataabortexception.這是為什么呢?

因?yàn)檫@些變量都是在堆里分配的,而當(dāng)應(yīng)用程序運(yùn)行時(shí),被映射到slot0,堆的地址也就是處于slot的范圍內(nèi),傳遞到device.exe后,device.exe被映射到了slot0,這個(gè)時(shí)候必須要將應(yīng)用程序的指針映射回應(yīng)用程序所在的slot。否則訪問(wèn)的是device.exe的空間,會(huì)發(fā)生不可知道的結(jié)果。

現(xiàn)在我們來(lái)驗(yàn)證一下上面說(shuō)的地址分配問(wèn)題。

我們這樣定義:

COPY_STRUCTcs[1];

staticchardata1[10];堆里

autochardata2[10];  棧里

這樣賦值:

cs[0].pBuffer1=&data1[0];

cs[0].pBuffer2=&data2[0];

cs[0].nLen=10;

調(diào)試信息:

cs[0].pBuffer1=&data1[0];

180112D0  ldr      r2,[pc,#0xD0]

180112D4  str      r2,[sp,#0x10]

讀取&data1[0]使用的是PC作為基址,而此時(shí)的應(yīng)用程序處于運(yùn)行階段映射到slot0,那么pc也就在0~01ffffff范圍,我的調(diào)試結(jié)果是在0x000112D0+8,使用的是arm,流水線機(jī)制,當(dāng)前指令地址+8才是pc值。

143:     cs[0].pBuffer2=&data2[0];

180112D8  add      r0,sp,#0x20

180112DC  str      r0,[sp,#0x14]

讀取&data2[0]采用的是sp作為基址,sp在應(yīng)用程序加載到slot的時(shí)候就確定了的。所以保持了在應(yīng)用程序slot的值,處于0x18xxxxxx范圍。

我們看到因?yàn)閣ince的slot機(jī)制,我們有時(shí)候需要映射,有時(shí)候不需要。所以wince文檔說(shuō)結(jié)構(gòu)里的指針要映射。畢竟你不知道應(yīng)用程序怎么寫(xiě)。

當(dāng)然,你可以根本不映射,只要把那個(gè)結(jié)構(gòu)屏蔽調(diào),寫(xiě)一個(gè)STATICLIBRARY給用戶(hù)使用,自己保證使用正確的地址分配就可以了。上面我說(shuō)的那個(gè)家伙就是這么干的。

好了,接著調(diào)用:

CloseHandle(hnd);

程序就這么結(jié)束了,完成了我們進(jìn)行簡(jiǎn)單的拷貝就OK了。

這個(gè)框架完成了,driver的基本接口設(shè)計(jì),強(qiáng)調(diào)了內(nèi)存指針的使用問(wèn)題。但是相對(duì)于一個(gè)真正的driver,還缺少點(diǎn)東西,就是訪問(wèn)硬件的方法。不過(guò)我們還是先了解下驅(qū)動(dòng)程序和應(yīng)用程序之間傳遞數(shù)據(jù)時(shí)何時(shí)調(diào)用MapPtrToProcess?

因?yàn)樵O(shè)備管理器負(fù)責(zé)加載驅(qū)動(dòng)程序DLL,這意味著當(dāng)應(yīng)用程序調(diào)用驅(qū)動(dòng)程序接口函數(shù)的時(shí)候,WINCE內(nèi)核會(huì)將調(diào)用驅(qū)動(dòng)程序接口函數(shù)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論