久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

【轉(zhuǎn)】驅(qū)動(dòng)和應(yīng)用層的三種通信方式

 山峰云繞 2023-06-01 發(fā)布于貴州
https://blog.csdn.net/qinlicang/article/details/4465514?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-11-4465514-blog-106835990.235%5Ev36%5Epc_relevant_anti_vip&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-11-4465514-blog-106835990.235%5Ev36%5Epc_relevant_anti_vip&utm_relevant_index=14


原文:sislcb(http://bbs./showthread.php?p=446641),表示感謝,! 驅(qū)動(dòng)程序和客戶應(yīng)用程序經(jīng)常需要進(jìn)行數(shù)據(jù)交換,,但我們知道驅(qū)動(dòng)程序和客戶應(yīng)用程序可能不在同一個(gè)地址空間,因此操作系統(tǒng)必須解決兩者之間的數(shù)據(jù)交換,。 驅(qū)動(dòng)層和應(yīng)用層通信,,主要是靠DeviceIoControl函數(shù),下面是該函數(shù)的原型: BOOL DeviceIoControl ( HANDLE hDevice, // 設(shè)備句柄 DWORD dwIoControlCode, // IOCTL請求操作代碼 LPVOID lpInBuffer, // 輸入緩沖區(qū)地址 DWORD nInBufferSize, // 輸入緩沖區(qū)大小 LPVOID lpOutBuffer, // 輸出緩沖區(qū)地址 DWORD nOutBufferSize, // 輸出緩沖區(qū)大小 LPDWORD lpBytesReturned, // 存放返回字節(jié)數(shù)的指針 LPOVERLAPPED lpOverlapped // 用于同步操作的Overlapped結(jié)構(gòu)體指針 ); dwIoControlCode 要進(jìn)行操作的控制碼,。驅(qū)動(dòng)程序可以通過CTL_CODE宏來組合定義一個(gè)控制碼,,并在IRP_MJ_DEVICE_CONTROL的實(shí)現(xiàn)中進(jìn)行控制碼的操作。在驅(qū)動(dòng)層,,irpStack->Parameters.DeviceIoControl.IoControlCode表示了這個(gè)控制碼,。 IOCTL請求有四種緩沖策略,下面一一介紹,。 1,、 輸入輸出緩沖I/O(METHOD_BUFFERED) 2、 直接輸入緩沖輸出I/O(METHOD_IN_DIRECT) 3,、 緩沖輸入直接輸出I/O(METHOD_OUT_DIRECT) 4,、 上面三種方法都不是(METHOD_NEITHER) 為了對這些類型更詳細(xì)的描述,請看msdn上的解釋,,我抄錄如下: "緩沖"方法(METHOD_BUFFERED) 備注:在下面的討論中,,"輸入"表示數(shù)據(jù)從用戶模式的應(yīng)用程序到驅(qū)動(dòng)程序,,"輸出"表示數(shù)據(jù)從驅(qū)動(dòng)程序到應(yīng)用程序。 對于讀取請求,,I/O 管理器分配一個(gè)與用戶模式的緩沖區(qū)大小相同的系統(tǒng)緩沖區(qū),。IRP 中的 SystemBuffer 字段包含系統(tǒng)地址。 UserBuffer 字段包含初始的用戶緩沖區(qū)地址,。當(dāng)完成請求時(shí),,I/O 管理器將驅(qū)動(dòng)程序已經(jīng)提供的數(shù)據(jù)從系統(tǒng)緩沖區(qū)復(fù)制到用戶緩沖區(qū)。對于寫入請求,,會(huì)分配一個(gè)系統(tǒng)緩沖區(qū)并將 SystemBuffer 設(shè)置為地址,。用戶緩沖區(qū)的內(nèi)容會(huì)被復(fù)制到系統(tǒng)緩沖區(qū),但是不設(shè)置 UserBuffer,。對于 IOCTL 請求,,會(huì)分配一個(gè)容量大小足以包含輸入緩沖區(qū)或輸出緩沖區(qū)的系統(tǒng)緩沖區(qū),并將 SystemBuffer 設(shè)置為分配的緩沖區(qū)地址,。輸入緩沖區(qū)中的數(shù)據(jù)復(fù)制到系統(tǒng)緩沖區(qū),。UserBuffer 字段設(shè)置為用戶模式輸出緩沖區(qū)地址。內(nèi)核模式驅(qū)動(dòng)程序應(yīng)當(dāng)只使用系統(tǒng)緩沖區(qū),,且不應(yīng)使用 UserBuffer 中存儲(chǔ)的地址,。 對于 IOCTL,驅(qū)動(dòng)程序應(yīng)當(dāng)從系統(tǒng)緩沖區(qū)獲取輸入并將輸出寫入到系統(tǒng)緩沖區(qū),。當(dāng)完成請求時(shí),,I/O 系統(tǒng)將輸出數(shù)據(jù)從系統(tǒng)緩沖區(qū)復(fù)制到用戶緩沖區(qū)。 "直接"方法(METHOD_IN/OUT_DIRECT) 對于讀取和寫入請求,,用戶模式緩沖區(qū)會(huì)被鎖定,,并且會(huì)創(chuàng)建一個(gè)內(nèi)存描述符列表 (MDL)。MDL 地址會(huì)存儲(chǔ)在 IRP 的 MdlAddress 字段中,。SystemBuffer 和 UserBuffer 均沒有任何含義,。但是,驅(qū)動(dòng)程序不應(yīng)當(dāng)更改這些字段的值,。 對于 IOCTL 請求,,如果在 METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT 中同時(shí)有一個(gè)輸出緩沖區(qū),則分配一個(gè)系統(tǒng)緩沖區(qū)(SystemBuffer 又有了地址)并將輸入數(shù)據(jù)復(fù)制到其中,。如果有一個(gè)輸出緩沖區(qū),,且它被鎖定,則會(huì)創(chuàng)建 MDL 并設(shè)置 MdlAddress,。UserBuffer 字段沒有任何含義,。 "兩者都不"方法(METHOD_NEITHER) 對于讀取和寫入請求,UserBuffer 字段被設(shè)置為指向初始的用戶緩沖區(qū),。不執(zhí)行任何其他操作,。 SystemAddress 和 MdlAddress 沒有任何含義,。對于 IOCTL 請求,I/O 管理器將 UserBuffer 設(shè)置為初始的用戶輸出緩沖區(qū),,而且,,它將當(dāng)前 I/O 棧位置的 Parameters.DeviceIoControl.Type3InputBuffer 設(shè)置為用戶輸入緩沖區(qū)。利用該 I/O 方法,,由驅(qū)動(dòng)程序來確定如何處理緩沖區(qū):分配系統(tǒng)緩沖區(qū)或創(chuàng)建 MDL,。 通常,驅(qū)動(dòng)程序在訪問用戶數(shù)據(jù)時(shí)不應(yīng)當(dāng)將 UserBuffer 字段用作地址,,即使當(dāng)用戶緩沖區(qū)被鎖定時(shí)也是如此,。這是由于在調(diào)用驅(qū)動(dòng)程序時(shí),,在系統(tǒng)中可能看不到調(diào)用用戶的地址空間,。(對于該規(guī)則的一個(gè)例外是,在最高層驅(qū)動(dòng)程序?qū)?IRP 向下傳遞到較低層的驅(qū)動(dòng)程序之前,,它可能需要使用 UserBuffer 來復(fù)制數(shù)據(jù),。)如果使用"直接"或"兩者都不"方法,在創(chuàng)建 MDL 之后,,驅(qū)動(dòng)程序可以使用 MmGetSystemAddressForMdl 函數(shù)來獲取有效的系統(tǒng)地址以訪問用戶緩沖區(qū),。 在驅(qū)動(dòng)層,依傳輸類型的不同,,輸入緩沖區(qū)的位置亦不同,,見下表。 傳輸類型 位置 METHOD_IN_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_OUT_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer METHOD_NEITHER irpStack->Parameters.DeviceIoControl.Type3InputBuffer 在驅(qū)動(dòng)層,,依傳輸類型的不同,,輸出緩沖區(qū)的位置亦不同,見下表,。 傳輸類型 位置 METHOD_IN_DIRECT irp->MdlAddress METHOD_OUT_DIRECT irp->MdlAddress METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer METHOD_NEITHER irp->UserBuffer 所以只要確定了傳輸方式后,,就可以根據(jù)各自的位置來讀取和寫入數(shù)據(jù),從而實(shí)現(xiàn)應(yīng)用層和驅(qū)動(dòng)的通信,。 下面看驅(qū)動(dòng)層對ioctl控制碼的處理代碼: 代碼: //METHOD_OUT_DIREC方式 NTSTATUS COMM_DirectOutIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_DirectOutIo/r/n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = Irp->AssociatedIrp.SystemBuffer; pOutputBuffer = NULL; if(Irp->MdlAddress) pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_DirectOutIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } // METHOD_IN_DIRECT NTSTATUS COMM_DirectInIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_DirectInIo/r/n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = Irp->AssociatedIrp.SystemBuffer; pOutputBuffer = NULL; if(Irp->MdlAddress) pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_DirectInIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } // METHOD_BUFFERED NTSTATUS COMM_BufferedIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_BufferedIo/r/n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = Irp->AssociatedIrp.SystemBuffer; pOutputBuffer = Irp->AssociatedIrp.SystemBuffer; if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_BufferedIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } // METHOD_NEITHER NTSTATUS COMM_NeitherIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite) { NTSTATUS status = STATUS_UNSUCCESSFUL; PVOID pInputBuffer, pOutputBuffer; ULONG outputLength, inputLength; DbgPrint("COMM_NeitherIo/r/n"); outputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; inputLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; pInputBuffer = pIoStackIrp->Parameters.DeviceIoControl.Type3InputBuffer; pOutputBuffer = Irp->UserBuffer; if(pInputBuffer && pOutputBuffer) { DbgPrint("COMM_NeitherIo UserModeMessage = '%s'", pInputBuffer); RtlCopyMemory(pOutputBuffer, pInputBuffer, outputLength); *sizeofWrite = outputLength; status = STATUS_SUCCESS; } return status; } 代碼比較簡單,,都是取得輸入的數(shù)據(jù),然后把數(shù)據(jù)直接拷貝到輸出,,傳輸給應(yīng)用層,。 應(yīng)用層的代碼: procedure TfrmMain.Send_Recv_Data(AInData: String; var AOutData:String; IoctlCode: DWORD); var dwReturn: DWORD; inData:array[0..1023] of char; outData:array[0..1023] of char; begin StrPCopy(inData, AInData); if m_hCommDevice <> 0 then begin DeviceIoControl(m_hCommDevice, IoctlCode, @inData, Length(inData), @outData, Length(outData), dwReturn, nil); AOutData := StrPas(@outData); end; end; 上面是進(jìn)行發(fā)送和接受的過程。 需要通信,,只要如下做: 代碼: procedure TfrmMain. btnDirect_IN_IOClick (Sender: TObject); var outData:String; begin Send_Recv_Data(Trim(edtDirect_in_in.Text), outData, IOCTL_COMM_DIRECT_IN_IO); edtDirect_in_out.Text := outData; end; 這是 direct_in方式通信,,其他通信方式類似,大家可以參考代碼了,,這里就不列舉了,,由于代碼比較簡單,,我就不多說了,大家還是看代碼吧,,很好明白,。最后,給個(gè)測試圖: 應(yīng)用層: 名稱: 1.jpg 查看次數(shù): 1449 文件大小: 27.9 KB 驅(qū)動(dòng)層: 名稱: 2.jpg 查看次數(shù): 1443 文件大小: 34.9 KB 代碼: 驅(qū)動(dòng)和應(yīng)用層通信.rar/Files/aurain/ioctl.rar

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多