亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

蟲蟲首頁(yè)| 資源下載| 資源專輯| 精品軟件
登錄| 注冊(cè)

您現(xiàn)在的位置是:蟲蟲下載站 > 資源下載 > 單片機(jī)編程 > 驅(qū)動(dòng)程序與應(yīng)用程序的接口

驅(qū)動(dòng)程序與應(yīng)用程序的接口

資 源 簡(jiǎn) 介

有兩種方式可以讓設(shè)備和應(yīng)用程序之間聯(lián)系:
1. 通過(guò)為設(shè)備創(chuàng)建的一個(gè)符號(hào)鏈;
2. 通過(guò)輸出到一個(gè)接口
WDM驅(qū)動(dòng)程序建議使用輸出到一個(gè)接口而不推薦使用創(chuàng)建符號(hào)鏈的方法。這個(gè)接口保證PDO的安全,也保證安全地創(chuàng)建一個(gè)惟一的、獨(dú)立于語(yǔ)言的訪問(wèn)設(shè)備的方法。
一個(gè)應(yīng)用程序使用Win32APIs來(lái)調(diào)用設(shè)備。在某個(gè)Win32 APIs和設(shè)備對(duì)象的分發(fā)函數(shù)之間存在一個(gè)映射關(guān)系。
獲得對(duì)設(shè)備對(duì)象訪問(wèn)的第一步就是打開一個(gè)設(shè)備對(duì)象的句柄。

用符號(hào)鏈打開一個(gè)設(shè)備的句柄
為了打開一個(gè)設(shè)備,應(yīng)用程序需要使用CreateFile。如果該設(shè)備有一個(gè)符號(hào)鏈出口,應(yīng)用程序可以用下面這個(gè)例子的形式打開句柄:
hDevice = CreateFile("\\\\.\\OMNIPORT3",
  GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,
  NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL ,NULL
);
文件路徑名的前綴“\\.\”告訴系統(tǒng)本調(diào)用希望打開一個(gè)設(shè)備。這個(gè)設(shè)備必須有一個(gè)符號(hào)鏈,以便應(yīng)用程序能夠打開它。有關(guān)細(xì)節(jié)查看有關(guān)Kdevice和CreateLink的內(nèi)容。在上述調(diào)用中第一個(gè)參數(shù)中前綴后的部分就是這個(gè)符號(hào)鏈的名字。
注意:CreatFile中的第一個(gè)參數(shù)不是Windows 98/2000中驅(qū)動(dòng)程序(.sys文件)的路徑。是到設(shè)備對(duì)象的符號(hào)鏈。
如果使用DriverWizard產(chǎn)生驅(qū)動(dòng)程序,它通常使用類KunitizedName來(lái)構(gòu)成設(shè)備的符號(hào)鏈。這意味著符號(hào)鏈名有一個(gè)附加的數(shù)字,通常是0。例如:如果鏈接名稱的主干是L“TestDevice”那么在CreateFile中的串就該是“\\\\.\\TestDevice0”。
如果應(yīng)用程序需要被覆蓋的I/O,第六個(gè)參數(shù)(Flags)必須或上FILE_FLAG_OVERLAPPED。

使用一個(gè)輸出接口打開句柄
用這種方式打開一個(gè)句柄會(huì)稍微麻煩一些。DriverWorks庫(kù)提供兩個(gè)助手類來(lái)使獲得對(duì)該接口的訪問(wèn)容易一些,這兩個(gè)類是CDeviceInterface, 和 CdeviceInterfaceClass。
CdeviceInterfaceClass類封裝了一個(gè)設(shè)備信息集,該信息集包含了特殊類中的所有設(shè)備接口信息。
應(yīng)用程序能有用CdeviceInterfaceClass類的一個(gè)實(shí)例來(lái)獲得一個(gè)或更多的CdeviceInterface類的實(shí)例。CdeviceInterface類是一個(gè)單一設(shè)備接口的抽象。它的成員函數(shù)DevicePath()返回一個(gè)路徑名的指針,該指針可以在CreateFile中使用來(lái)打開設(shè)備。
下面用一個(gè)小例子來(lái)顯示這些類最基本的使用方法:
extern GUID TestGuid;
HANDLE OpenByInterface(
  GUID* pClassGuid,
  DWORD instance,
  PDWORD pError
)
{
  CDeviceInterfaceClass DevClass(pClassGuid, pError);
  if (*pError != ERROR_SUCCESS)
    return INVALID_HANDLE_VALUE;
  CDeviceInterface DevInterface(&DevClass, instance, pError);
  if (*pError != ERROR_SUCCESS)
    return INVALID_HANDLE_VALUE;
  cout << "The device path is "
    << DevInterface.DevicePath()
    << endl;

  HANDLE hDev;
  hDev = CreateFile(
   DevInterface.DevicePath(),
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
  );
  if (hDev == INVALID_HANDLE_VALUE)
    *pError = GetLastError();
  return hDev;
}

在設(shè)備中執(zhí)行I/O操作
一旦應(yīng)用程序獲得一個(gè)有效的設(shè)備句柄,它就能使用Win32 APIs來(lái)產(chǎn)生到設(shè)備對(duì)象的IRPs。下面的表顯示了這種對(duì)應(yīng)關(guān)系。
Win32 API  DRIVER_FUNCTION_xxx
IRP_MJ_xxx  KDevice subclass member function
CreateFile  CREATE  Create
ReadFile  READ  Read
WriteFile  WRITE  Write
DeviceIoControl  DEVICE_CONTROL  DeviceControl
CloseHandle  CLOSE
CLEANUP  Close
CleanUp
需要解釋一下設(shè)備類成員的Close和CleanUp:CreateFile使內(nèi)核為設(shè)備創(chuàng)建一個(gè)新的文件對(duì)象。這使得多個(gè)句柄可以映射同一個(gè)文件對(duì)象。當(dāng)這個(gè)文件對(duì)象的最后一個(gè)用戶級(jí)句柄被撤銷后,I/O管理器調(diào)用CleanUp。當(dāng)沒(méi)有任何用戶級(jí)和核心級(jí)的對(duì)文件對(duì)象的訪問(wèn)的時(shí)候,I/O管理器調(diào)用Close。
如果被打開的設(shè)備不支持指定的功能,則調(diào)用相應(yīng)的Win32將引起錯(cuò)誤(無(wú)效功能)。
以前為Windows95編寫的VxD的應(yīng)用程序代碼中可能會(huì)在打開設(shè)備的時(shí)候使用FILE_FLAG_DELETE_ON_CLOSE屬性。在Windows NT/2000中,建議不要使用這個(gè)屬性,因?yàn)樗鼘?dǎo)致沒(méi)有特權(quán)的用戶企圖打開這個(gè)設(shè)備,這是不可能成功的。
I/O管理器將ReadFile和WriteFile的buff參數(shù)轉(zhuǎn)換成IRP域的方法依賴于設(shè)備對(duì)象的屬性。當(dāng)設(shè)備設(shè)置DO_DIRECT_IO標(biāo)志,I/O管理器將buff鎖住在存儲(chǔ)器中,并且創(chuàng)建了一個(gè)存儲(chǔ)在IRP中的MDL域。一個(gè)設(shè)備可以通過(guò)調(diào)用Kirp::Mdl來(lái)存取MDL。
當(dāng)設(shè)備設(shè)置DO_BUFFERED_IO標(biāo)志,設(shè)備對(duì)象分別通過(guò)KIrp::BufferedReadDest或 KIrp::BufferedWriteSource為讀或?qū)懖僮鳙@得buff地址。
當(dāng)設(shè)備不設(shè)置DO_BUFFERED_IO標(biāo)志也不設(shè)置DO_DIRECT_IO,內(nèi)核設(shè)置IRP 的UserBuffer域來(lái)對(duì)應(yīng)ReadFile或WriteFile中的buff參數(shù)。然而,存儲(chǔ)區(qū)并沒(méi)有被鎖住而且地址只對(duì)調(diào)用進(jìn)程有效。驅(qū)動(dòng)程序可以使用KIrp::UserBuffer來(lái)存取IRP域。
對(duì)于DeviceIoControl調(diào)用,buffer參數(shù)的轉(zhuǎn)換依賴于特殊的I/O控制代碼,它不在設(shè)備對(duì)象的特性中。宏CTL_CODE(在winioctl.h中定義)用來(lái)構(gòu)造控制代碼。這個(gè)宏的其中一個(gè)參數(shù)指明緩沖方法是METHOD_BUFFERED, METHOD_IN_DIRECT, METHOD_OUT_DIRECT, 或METHOD_NEITHER。下面的表顯示了這些方法和與之對(duì)應(yīng)的能獲得輸入緩沖與輸出緩沖的KIrp中的成員函數(shù):
Method  Input Buffer Parameter  Output Buffer Parameter
METHOD_BUFFERED  KIrp::IoctlBuffer
KIrp::IoctlBuffer

METHOD_IN_DIRECT  KIrp::IoctlBuffer
KIrp::Mdl

METHOD_OUT_DIRECT  KIrp::IoctlBuffer
KIrp::Mdl

METHOD_NEITHER  KIrp::IoctlType3InputBuffer
KIrp::UserBuffer

如果控制代碼指明METHOD_BUFFERED,系統(tǒng)分配一個(gè)單一的緩沖來(lái)作為輸入與輸出。驅(qū)動(dòng)程序必須在向輸出緩沖放數(shù)據(jù)之前拷貝輸入數(shù)據(jù)。驅(qū)動(dòng)程序通過(guò)調(diào)用KIrp::IoctlBuffer獲得緩沖地址。在完成時(shí),I/O管理器從系統(tǒng)緩沖拷貝數(shù)據(jù)到提供給Ring 3級(jí)調(diào)用者使用的緩沖中。驅(qū)動(dòng)程序必須在結(jié)束前存儲(chǔ)拷貝到IRP的Information成員中的數(shù)據(jù)個(gè)數(shù)。
如果控制代碼不指明METHOD_IN_DIRECT或METHOD_OUT_DIRECT,則DeviceIoControl的參數(shù)呈現(xiàn)不同的含義。參數(shù)InputBuffer被拷貝到一個(gè)系統(tǒng)緩沖,這個(gè)緩沖驅(qū)動(dòng)程序可以通過(guò)調(diào)用KIrp::IoctlBuffer。參數(shù)OutputBuffer被映射到KMemory對(duì)象,驅(qū)動(dòng)程序?qū)@個(gè)對(duì)象的訪問(wèn)通過(guò)調(diào)用KIrp::Mdl來(lái)實(shí)現(xiàn)。對(duì)于METHOD_OUT_DIRECT,調(diào)用者必須有對(duì)緩沖的寫訪問(wèn)權(quán)限。
注意,對(duì)METHOD_NEITHER,內(nèi)核只提供虛擬地址;它不會(huì)做映射來(lái)配置緩沖。虛擬地址只對(duì)調(diào)用進(jìn)程有效。
這里是一個(gè)用METHOD_BUFFERED的例子:
首先,使用宏CTL_CODE來(lái)定義一個(gè)IOCTL代碼:
#define IOCTL_MYDEV_GET_FIRMWARE_REV \
CTL_CODE (FILE_DEVICE_UNKNOWN,0,METHOD_BUFFERED,FILE_ANY_ACCESS)
現(xiàn)在使用一個(gè)DeviceIoControl調(diào)用:
BOOLEAN b;
CHAR FirmwareRev[60];
ULONG FirmwareRevSize;
b = DeviceIoControl(hDevice, IOCTL_MYDEV_GET_VERSION_STRING,
  NULL, // no input  注意,這里放的是包含有執(zhí)行操作命令的字符串指針
  0,
FirmwareRev,      //這里是output串指針,存放從驅(qū)動(dòng)程序中返回的字符串。
sizeof(FirmwareRev),& FirmwareRevSize,
  NULL // not overlapped I/O
 );
如果輸出緩沖足夠大,設(shè)備拷貝串到里面并將拷貝的資結(jié)束設(shè)置到FirmwareRevSize中。
在驅(qū)動(dòng)程序中,代碼看起來(lái)如下所示:
const char* FIRMWARE_REV = "FW 16.33 v5";
NTSTATUS MyDevice::DeviceControl( KIrp I )
{
  ULONG fwLength=0;
  switch ( I.IoctlCode() )
  {
    case IOCTL_MYDEV_GET_FIRMWARE_REV:
      fwLength = strlen(FIRMWARE_REV)+1;
      if (I.IoctlOutputBufferSize() >= fwLength)
      {
        strcpy((PCHAR)I.IoctlBuffer(),FIRMWARE_REV);
        I.Information() = fwLength; 
        return I.Complete(STATUS_SUCCESS);
      }
      else
      {
       
      }
    case . . .
   }
 }

相 關(guān) 資 源

主站蜘蛛池模板: 津市市| 舟山市| 肇州县| 石狮市| 休宁县| 上虞市| 贵阳市| 富蕴县| 定日县| 汕尾市| 洪湖市| 全椒县| 无锡市| 饶平县| 桃园市| 五莲县| 双桥区| 鞍山市| 荥阳市| 商南县| 阜新| 绩溪县| 长宁区| 剑川县| 色达县| 尖扎县| 永平县| 兴宁市| 团风县| 浦城县| 崇礼县| 长武县| 长岛县| 巨野县| 鲜城| 沙坪坝区| 辛集市| 宁乡县| 宁蒗| 伊春市| 泰兴市|