驅動開發之 裝置讀寫方式:緩衝區方式

來源:互聯網
上載者:User

標籤:驅動開發

1.

裝置對象一共有三種讀寫方式:緩衝區方式讀寫(Buffered方式);直接方式讀寫(Direct方式);Neither方式。這三種方式的Flags分別對應DO_BUFFERED_IO,DO_DIRECT_IO,0

在buffered方式中,I/O管理器先建立一個與使用者模式資料緩衝區大小相等的系統緩衝區。而你的驅動程式將使用這個系統緩衝區工作。I/O管理器負責在系統緩衝區和使用者模式緩衝區之間複製資料。 
在direct方式中,I/O管理器鎖定了包含使用者模式緩衝區的實體記憶體頁,並建立一個稱為MDL(記憶體描述符表)的輔助資料結構來描述鎖定頁。因此你的驅動程式將使用MDL工作。 
在neither方式中,I/O管理器僅簡單地把使用者模式的虛擬位址傳遞給你。而使用使用者模式地址的驅動程式應十分小心。

2.

下面介紹緩衝區方式讀寫。其優點是比較簡單的解決了將使用者地址傳入驅動的問題,缺點是需要使用者模式和核心模式之間資料複製,可想而知,運行效率會受到影響。適合少量記憶體操作時使用的一種方法。

現在以readfile為例,首先應用程式中需要提供一段緩衝區並把緩衝區大小作為參數傳入,例如

UCHAR OutputBuffer[10];
DWORD RetLen = 0;
readfile(hDevice,OutputBuffer,sizeof(OutputBuffer),&RetLen,NULL);

OutputBuffer是提供的輸出緩衝區,是使用者模式的記憶體位址,作業系統將此緩衝區的資料複製到核心模式下的地址中,sizeof(OutputBuffer)是緩衝區的大小,而RetLen是真正的輸出的位元組數。


那麼核心模式怎麼得到此核心模式地址呢?怎麼得到writefile或readfile的位元組數呢?答案在下面。

此核心模式下的地址可以通過此readfile建立的IRP的AssociatedIrp.SystemBuffer得到。

假如請求的IRP為PIRP pIrp(一般是派遣函數的參數),那麼UCHAR* OutputBuffer= (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;

而readfile請求的位元組數為IO_STACK_LOCATION中的Parameters.Read.Length,writefilew為IO_STACK_LOCATION中的Parameters.Write.Length

//得到當前堆棧
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//得到readfile緩衝區大小
ULONG cbread = stack->Parameters..Read.Length;
//得到writefile緩衝區大小
ULONG cbwrite = stack->Parameters.Write.Length;


得到了核心模式下的緩衝區地址了就可以對此緩衝區操作了。比如:

UCHAR* OutputBuffer= (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;

ULONG cbread = stack->Parameters..Read.Length;

memcpy(OutputBuffer,0xBB,cbread);

這樣使用者模式下的緩衝區內得到的資料是0xBB。


另外還要設定實際操作的位元組數,pIrp->IoStatus.Information = cbread;(實際操作的位元組數不一定要設定為緩衝區的大小,但也不應該大於緩衝區的大小)

那麼使用者模式下readfile的RetLen被設定為cbread。

3.

附加說明:如果使用者模式調用DeviceIoControl的話,緩衝區的資訊獲得方式如下:

//得到當前堆棧
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//得到輸入緩衝區大小
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//得到輸出緩衝區大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;

//輸入緩衝區資料
 UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;
//操作輸出緩衝區
UCHAR* OutputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;    

pIrp->IoStatus.Information = 實際操作位元組數。



驅動開發之 裝置讀寫方式:緩衝區方式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.