音影先锋亚洲天堂网|电影世界尽头的爱完整版播放|国产 熟女 91|高清无码免费观看欧美日韩|韩国一区二区三区黄色录像|美女亚洲加勒比在线|亚洲综合网 开心五月|7x成人在线入口|成人网站免费日韩毛片区|国产黄片?一级?二级?三级

WINCE驅(qū)動分析以及MapPtrToProcess 用法 3

出處:互聯(lián)網(wǎng)    發(fā)布于:2011-09-04 17:35:40

  對于wince 驅(qū)動或者linux驅(qū)動,或者其他操作系統(tǒng)驅(qū)動。基本上就是兩個部分,1,訪問硬件寄存器。2,編寫操作系統(tǒng)接口。從訪問硬件上來說,可以有總線驅(qū)動,一般的I/O驅(qū)動等。從操作系統(tǒng)來說,就wince而言,可以分為,built-driver和stream driver,也可以從另外的一個角度,分為 Layered Device Driver 和 Monolithic driver??傊?qū)動的叫法和種類很多,一般都要根據(jù)具體開發(fā)的驅(qū)動再仔細研究。其實大多數(shù)工作都是要看E文的datasheet,了解硬件的工作原理,對CPU工作方式有一定的理解,問題就不大了。這里簡單介紹一下如何編寫wince下的stream driver。

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

  XXX_Close (Device Manager)

  XXX_Deinit (Device Manager)

  XXX_Init (Device Manager)

  XXX_IOControl (Device Manager)

  XXX_Open (Device Manager)

  ……

    無非就是一些讀寫,IOCTL,POWER管理的接口而已。

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

  #include <windows.h>

  #include<Windev.h>

  #include <stdio.h>

  #include "objbase.h"

  #include "initguid.h"

  #include "foo.h"

  //char data1[10];

  int  WinMain(void)

  {

  HANDLE hnd;

  COPY_STRUCT cs[1];

  int i;

  //static char data1[10];

  auto char data1[10];

  auto char data2[10];

  static char* 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("Open device fALIed!\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);

  }

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

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

  會調(diào)用到

  FOO_Open(DWORD dwContext, DWORD AccessCode, DWORD ShareMode)

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

  #define       FOO_DEV_NAME L"Foo1:"

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

  "Index"=dword:1

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

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

  接著我們來說一個重要的函數(shù),

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

  調(diào)用到

  FOO_IOControl

  走到這里

  case IOCTL_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;

  這里又很多東西要研究,這里我就不做詳細解說了。

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

  typedef struct {

  char* pBuffer1;

  char* pBuffer2;

  int nLen;

  }COPY_STRUCT;

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

  DeviceIoControl 傳過來的指針可以用嗎?它包含的兩個指針可以直接用嗎?

  按照PB連接幫助文檔看,

  The operating system (OS ) manages pointers passed directly as parameters. Drivers must map all pointers contained in structures. DeviceIoControl buffers are often structures that contain data, some of which might be pointers.

  You can map a pointer contained in a structure by calling MapPtrToProcess, setting the first parameter to the pointer, and then setting the second parameter to GetCallerProcess.

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

  這也就是:

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

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

  的由來,可是后面的代碼沒有使用pMap1,pMap2。而是直接使用:

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

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

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

  COPY_STRUCT cs[1];

  auto char data1[10];

  auto char data2[10];

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

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

  事實上,我們傳過來的指針根本就是不需要映射,因為他們都是0x18xxxxxx,在應(yīng)用程序的slot里,所以只要device.exe有訪問應(yīng)用程序的權(quán)限,就可以了。而這個權(quán)限,系統(tǒng)已經(jīng)幫我們設(shè)置好了。

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

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

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

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

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

  cs.nLen = 10;

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

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

  現(xiàn)在我們來驗證一下上面說的地址分配問題。

  我們這樣定義:

  COPY_STRUCT cs[1];

  static char data1[10]; 堆里

  auto char data2[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作為基址,而此時的應(yīng)用程序處于運行階段映射到slot0,那么pc也就在0~01ffffff范圍,我的調(diào)試結(jié)果是在0x000112D0+8,使用的是arm,流水線機制,當(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的時候就確定了的。所以保持了在應(yīng)用程序slot的值,處于0x18xxxxxx范圍。

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

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

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

  CloseHandle(hnd);

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

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

  因為設(shè)備管理器負(fù)責(zé)加載驅(qū)動程序DLL,這意味著當(dāng)應(yīng)用程序調(diào)用驅(qū)動程序接口函數(shù)的時候,WINCE內(nèi)核會將調(diào)用驅(qū)動程序接口函數(shù)的線程轉(zhuǎn)移到設(shè)備管理器的進程空間然后執(zhí)行具體的驅(qū)動程序代碼,應(yīng)用程序和設(shè)備管理器處于兩個進程空間,這就造成設(shè)備管理器無法訪問應(yīng)用程序傳遞的指針(虛擬地址),所以當(dāng)我們在應(yīng)用程序中傳遞指針給流驅(qū)動程序接口函數(shù)時,WINCE內(nèi)核從中作了一個地址映射,例如ReadFile、WriteFile、DeviceIoControl函數(shù)的參數(shù)凡是指針都經(jīng)過了映射才傳遞給驅(qū)動程序,所以很多驅(qū)動程序開發(fā)者并不了解其中的奧秘就可以編程了。但是如果參數(shù)是一個指向一個結(jié)構(gòu)體的指針,而結(jié)構(gòu)體里包括一個或多個指針,那么WINCE內(nèi)核并不負(fù)責(zé)映射,所以就需要開發(fā)者在驅(qū)動程序接口函數(shù)中調(diào)用API函數(shù)MapPtrToProcess來映射地址。例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());

  關(guān)于MapPtrToProcess 用法 WINCE驅(qū)動分析的學(xué)習(xí)又要告一段落了。我們使用evc編譯應(yīng)用程序代碼測試driver。希望大家在學(xué)習(xí)中舉一反三學(xué)到更多的東西。當(dāng)然也許本文還不夠完善,在接下來的學(xué)習(xí)中我們會更加深入地學(xué)習(xí)MapPtrToProcess 用法 WINCE驅(qū)動分析。如果大家有更好的例子可以發(fā)出來。學(xué)無止境,我的并不一定是的,我只希望對需要這方面知識的人有所幫助,我就滿足了。接下來我們要說的就是對一個真正的driver還缺少的東西——訪問硬件的方法。希望感興趣的人多多關(guān)注。



  
關(guān)鍵詞:驅(qū)動

版權(quán)與免責(zé)聲明

凡本網(wǎng)注明“出處:維庫電子市場網(wǎng)”的所有作品,版權(quán)均屬于維庫電子市場網(wǎng),轉(zhuǎn)載請必須注明維庫電子市場網(wǎng),http://m.58mhw.cn,違反者本網(wǎng)將追究相關(guān)法律責(zé)任。

本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點或證實其內(nèi)容的真實性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個人從本網(wǎng)轉(zhuǎn)載時,必須保留本網(wǎng)注明的作品出處,并自負(fù)版權(quán)等法律責(zé)任。

如涉及作品內(nèi)容、版權(quán)等問題,請在作品發(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。

廣告
OEM清單文件: OEM清單文件
*公司名:
*聯(lián)系人:
*手機號碼:
QQ:
有效期:

掃碼下載APP,
一鍵連接廣大的電子世界。

在線人工客服

買家服務(wù):
賣家服務(wù):
技術(shù)客服:

0571-85317607

網(wǎng)站技術(shù)支持

13606545031

客服在線時間周一至周五
9:00-17:30

關(guān)注官方微信號,
第一時間獲取資訊。

建議反饋

聯(lián)系人:

聯(lián)系方式:

按住滑塊,拖拽到最右邊
>>
感謝您向阿庫提出的寶貴意見,您的參與是維庫提升服務(wù)的動力!意見一經(jīng)采納,將有感恩紅包奉上哦!