借贷网站建设方案,云南昆明网站设计,企业自建平台有哪些,恺策网优 营销型网站建设品牌服务商以下是一个驱动层 用户态的交互示例#xff0c;覆盖“超时设置设备状态查询数据读写”全流程#xff0c;包含驱动代码、用户态头文件、用户态调用代码。
一、整体架构说明层级核心文件/功能驱动层实现 IRP_MJ_DEVICE_CONTROL 处理逻辑#xff0c;响应自定义IOCTL#xff0…以下是一个驱动层 用户态的交互示例覆盖“超时设置设备状态查询数据读写”全流程包含驱动代码、用户态头文件、用户态调用代码。一、整体架构说明层级核心文件/功能驱动层实现IRP_MJ_DEVICE_CONTROL处理逻辑响应自定义IOCTL设置超时、查状态、读写数据接口层ioapist.h封装IOCTL、结构体、用户态API声明用户态层调用ioapist.h封装的API完成设备打开、参数下发、数据交互、设备关闭二、步骤1定义公共接口头文件ioapist.hioapist.h 并非 Windows 系统原生公开的头文件不属于 MSDN/Windows SDK 标准头文件而是行业 / 厂商自定义的接口头文件核心用于封装设备 I/O 操作的 API 集合尤其是通过DeviceIoControl实现的设备控制、数据交互逻辑常见于硬件驱动开发、工业控制、嵌入式 Windows 设备通信等场景。该文件是驱动和用户态的“协议约定”需保证两端结构体、IOCTL完全一致。#ifndefIOAPIST_H#defineIOAPIST_H#ifdef__cplusplusexternC{#endif/************************ 1. 基础常量定义 ************************/// 自定义设备类型避开Windows系统预留值范围0x8000-0xFFFF#defineFILE_DEVICE_CUSTOM_DEV0x8000// 缓冲区方式驱动与用户态数据交互方式这里用缓冲式最通用#defineMETHOD_CUSTOMMETHOD_BUFFERED// 访问权限#defineFILE_CUSTOM_ACCESSFILE_ANY_ACCESS// 封装CTL_CODE宏生成唯一IOCTL控制码#defineCUSTOM_CTL_CODE(code)\CTL_CODE(FILE_DEVICE_CUSTOM_DEV,code,METHOD_CUSTOM,FILE_CUSTOM_ACCESS)/************************ 2. IOCTL控制码定义 ************************/#defineIOCTL_SET_TIMEOUTCUSTOM_CTL_CODE(0x0001)// 设置超时#defineIOCTL_GET_DEVICE_STATUSCUSTOM_CTL_CODE(0x0002)// 获取设备状态#defineIOCTL_WRITE_DATACUSTOM_CTL_CODE(0x0003)// 写数据到设备#defineIOCTL_READ_DATACUSTOM_CTL_CODE(0x0004)// 从设备读数据/************************ 3. 数据交互结构体驱动/用户态一致 ************************/// 超时设置结构体对应IOCTL_SET_TIMEOUTtypedefstruct_DEV_TIMEOUT{DWORD dwReadTimeout;// 读超时毫秒DWORD dwWriteTimeout;// 写超时毫秒DWORD dwCtrlTimeout;// 控制指令超时毫秒}DEV_TIMEOUT,*PDEV_TIMEOUT;// 设备状态结构体对应IOCTL_GET_DEVICE_STATUStypedefstruct_DEV_STATUS{BOOL bOnline;// 设备是否在线TRUE/FALSEDWORD dwErrorCount;// 累计错误数DWORD dwBufferSize;// 设备缓存区大小DWORD dwReserved;// 预留字段保证结构体对齐}DEV_STATUS,*PDEV_STATUS;// 数据读写结构体对应IOCTL_READ/WRITE_DATAtypedefstruct_DEV_DATA{BYTE szBuffer[1024];// 数据缓冲区DWORD dwDataLen;// 有效数据长度输入/输出DWORD dwErrorCode;// 操作错误码输出}DEV_DATA,*PDEV_DATA;/************************ 4. 辅助常量/枚举 ************************/// 默认设备路径用户态打开设备用#defineDEFAULT_DEVICE_PATHL\\\\.\\CustomDevice// 超时默认值#defineDEFAULT_READ_TIMEOUT5000// 5秒#defineDEFAULT_WRITE_TIMEOUT3000// 3秒#defineDEFAULT_CTRL_TIMEOUT2000// 2秒// 设备状态枚举辅助用户态判断typedefenum{DEV_STATUS_OFFLINE0,DEV_STATUS_ONLINE1,DEV_STATUS_ERROR2}DEV_STATUS_ENUM;/************************ 5. 用户态封装API声明 ************************/// 打开设备封装CreateFileWHANDLE __stdcallDevOpen(LPCWSTR lpDevicePath,// 设备路径如DEFAULT_DEVICE_PATHDWORD dwDesiredAccess// 访问权限GENERIC_READ | GENERIC_WRITE);// 关闭设备封装CloseHandleVOID __stdcallDevClose(HANDLE hDevice);// 设置设备超时封装DeviceIoControl IOCTL_SET_TIMEOUTBOOL __stdcallDevSetTimeout(HANDLE hDevice,PDEV_TIMEOUT pTimeout);// 获取设备状态封装DeviceIoControl IOCTL_GET_DEVICE_STATUSBOOL __stdcallDevGetStatus(HANDLE hDevice,PDEV_STATUS pStatus);// 写数据到设备封装DeviceIoControl IOCTL_WRITE_DATABOOL __stdcallDevWriteData(HANDLE hDevice,PDEV_DATA pData);// 从设备读数据封装DeviceIoControl IOCTL_READ_DATABOOL __stdcallDevReadData(HANDLE hDevice,PDEV_DATA pData);#ifdef__cplusplus}#endif#endif// IOAPIST_H三、步骤2驱动层实现内核态C语言驱动基于WDM框架开发核心实现IRP_MJ_DEVICE_CONTROL回调处理用户态下发的IOCTL指令。1. 驱动头文件CustomDev.h#ifndefCUSTOM_DEV_H#defineCUSTOM_DEV_H#includewdm.h#includeioapist.h// 引入公共接口头文件// 设备扩展结构体保存设备状态、超时配置等typedefstruct_DEVICE_EXTENSION{PDEVICE_OBJECT pDeviceObj;// 设备对象指针UNICODE_STRING ustrDeviceName;// 设备名UNICODE_STRING ustrSymLinkName;// 符号链接名// 设备运行状态DEV_TIMEOUT stTimeout;// 超时配置用户态下发DEV_STATUS stStatus;// 设备状态BYTE szDevBuffer[1024];// 设备内部缓存区DWORD dwDevBufferLen;// 缓存区有效数据长度}DEVICE_EXTENSION,*PDEVICE_EXTENSION;// 函数声明NTSTATUSDriverUnload(PDRIVER_OBJECT pDriverObj);NTSTATUSDispatchCreateClose(PDEVICE_OBJECT pDeviceObj,PIRP pIrp);NTSTATUSDispatchDeviceControl(PDEVICE_OBJECT pDeviceObj,PIRP pIrp);#endif// CUSTOM_DEV_H2. 驱动实现文件CustomDev.c#includeCustomDev.h/************************ 1. 驱动入口函数 ************************/NTSTATUSDriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegistryPath){NTSTATUS status;PDEVICE_OBJECT pDeviceObjNULL;PDEVICE_EXTENSION pDevExtNULL;UNICODE_STRING ustrDeviceName;UNICODE_STRING ustrSymLinkName;// 1. 设置驱动卸载例程pDriverObj-DriverUnloadDriverUnload;// 2. 设置分发例程处理Create/Close/DeviceControlpDriverObj-MajorFunction[IRP_MJ_CREATE]DispatchCreateClose;pDriverObj-MajorFunction[IRP_MJ_CLOSE]DispatchCreateClose;pDriverObj-MajorFunction[IRP_MJ_DEVICE_CONTROL]DispatchDeviceControl;// 3. 创建设备对象RtlInitUnicodeString(ustrDeviceName,L\\Device\\CustomDevice);statusIoCreateDevice(pDriverObj,// 驱动对象sizeof(DEVICE_EXTENSION),// 设备扩展大小ustrDeviceName,// 设备名FILE_DEVICE_CUSTOM_DEV,// 设备类型与ioapist.h一致0,// 设备特性FALSE,// 非独占pDeviceObj// 输出设备对象);if(!NT_SUCCESS(status)){DbgPrint(IoCreateDevice failed, status: 0x%X\n,status);returnstatus;}// 4. 初始化设备扩展pDevExt(PDEVICE_EXTENSION)pDeviceObj-DeviceExtension;pDevExt-pDeviceObjpDeviceObj;pDevExt-ustrDeviceNameustrDeviceName;// 初始化默认超时pDevExt-stTimeout.dwReadTimeoutDEFAULT_READ_TIMEOUT;pDevExt-stTimeout.dwWriteTimeoutDEFAULT_WRITE_TIMEOUT;pDevExt-stTimeout.dwCtrlTimeoutDEFAULT_CTRL_TIMEOUT;// 初始化设备状态pDevExt-stStatus.bOnlineTRUE;// 默认在线pDevExt-stStatus.dwErrorCount0;// 无错误pDevExt-stStatus.dwBufferSize1024;// 缓存区大小1024pDevExt-dwDevBufferLen0;// 初始无数据// 5. 创建符号链接用户态可通过\\.\CustomDevice访问RtlInitUnicodeString(ustrSymLinkName,L\\DosDevices\\CustomDevice);pDevExt-ustrSymLinkNameustrSymLinkName;statusIoCreateSymbolicLink(ustrSymLinkName,ustrDeviceName);if(!NT_SUCCESS(status)){DbgPrint(IoCreateSymbolicLink failed, status: 0x%X\n,status);IoDeleteDevice(pDeviceObj);returnstatus;}DbgPrint(CustomDev Driver Load Success!\n);returnSTATUS_SUCCESS;}/************************ 2. 驱动卸载例程 ************************/NTSTATUSDriverUnload(PDRIVER_OBJECT pDriverObj){PDEVICE_OBJECT pDeviceObjpDriverObj-DeviceObject;PDEVICE_EXTENSION pDevExt(PDEVICE_EXTENSION)pDeviceObj-DeviceExtension;// 删除符号链接IoDeleteSymbolicLink(pDevExt-ustrSymLinkName);// 删除设备对象IoDeleteDevice(pDeviceObj);DbgPrint(CustomDev Driver Unload Success!\n);returnSTATUS_SUCCESS;}/************************ 3. Create/Close分发例程 ************************/NTSTATUSDispatchCreateClose(PDEVICE_OBJECT pDeviceObj,PIRP pIrp){PDEVICE_EXTENSION pDevExt(PDEVICE_EXTENSION)pDeviceObj-DeviceExtension;NTSTATUS statusSTATUS_SUCCESS;// 模拟打开设备时标记在线状态if(pIrp-CurrentLocation1pIrp-MajorFunctionIRP_MJ_CREATE){pDevExt-stStatus.bOnlineTRUE;DbgPrint(Device Opened!\n);}// 关闭设备时标记离线elseif(pIrp-CurrentLocation1pIrp-MajorFunctionIRP_MJ_CLOSE){pDevExt-stStatus.bOnlineFALSE;DbgPrint(Device Closed!\n);}// 完成IRPpIrp-IoStatus.Statusstatus;pIrp-IoStatus.Information0;IoCompleteRequest(pIrp,IO_NO_INCREMENT);returnstatus;}/************************ 4. DeviceControl分发例程核心 ************************/NTSTATUSDispatchDeviceControl(PDEVICE_OBJECT pDeviceObj,PIRP pIrp){NTSTATUS statusSTATUS_SUCCESS;PIO_STACK_LOCATION pIoStackIoGetCurrentIrpStackLocation(pIrp);PDEVICE_EXTENSION pDevExt(PDEVICE_EXTENSION)pDeviceObj-DeviceExtension;ULONG ulIoControlCodepIoStack-Parameters.DeviceIoControl.IoControlCode;ULONG ulInputLenpIoStack-Parameters.DeviceIoControl.InputBufferLength;ULONG ulOutputLenpIoStack-Parameters.DeviceIoControl.OutputBufferLength;DbgPrint(DispatchDeviceControl: IOCTL0x%X\n,ulIoControlCode);/************************ 处理IOCTL_SET_TIMEOUT ************************/if(ulIoControlCodeIOCTL_SET_TIMEOUT){// 校验输入缓冲区大小if(ulInputLen!sizeof(DEV_TIMEOUT)){statusSTATUS_INVALID_PARAMETER;DbgPrint(IOCTL_SET_TIMEOUT: Input buffer size error!\n);gotoEnd;}// 读取用户态下发的超时参数PDEV_TIMEOUT pTimeout(PDEV_TIMEOUT)pIrp-AssociatedIrp.SystemBuffer;// 保存到设备扩展pDevExt-stTimeout*pTimeout;DbgPrint(Set Timeout: Read%dms, Write%dms, Ctrl%dms\n,pTimeout-dwReadTimeout,pTimeout-dwWriteTimeout,pTimeout-dwCtrlTimeout);}/************************ 处理IOCTL_GET_DEVICE_STATUS ************************/elseif(ulIoControlCodeIOCTL_GET_DEVICE_STATUS){// 校验输出缓冲区大小if(ulOutputLen!sizeof(DEV_STATUS)){statusSTATUS_INVALID_PARAMETER;DbgPrint(IOCTL_GET_DEVICE_STATUS: Output buffer size error!\n);gotoEnd;}// 将设备状态写入输出缓冲区返回给用户态PDEV_STATUS pStatus(PDEV_STATUS)pIrp-AssociatedIrp.SystemBuffer;*pStatuspDevExt-stStatus;// 设置返回数据长度pIrp-IoStatus.Informationsizeof(DEV_STATUS);DbgPrint(Get Status: Online%d, ErrorCount%d\n,pStatus-bOnline,pStatus-dwErrorCount);}/************************ 处理IOCTL_WRITE_DATA ************************/elseif(ulIoControlCodeIOCTL_WRITE_DATA){// 校验输入缓冲区大小if(ulInputLen!sizeof(DEV_DATA)){statusSTATUS_INVALID_PARAMETER;DbgPrint(IOCTL_WRITE_DATA: Input buffer size error!\n);gotoEnd;}// 读取用户态下发的数据PDEV_DATA pData(PDEV_DATA)pIrp-AssociatedIrp.SystemBuffer;if(pData-dwDataLen1024){// 校验数据长度statusSTATUS_BUFFER_OVERFLOW;pData-dwErrorCodeSTATUS_BUFFER_OVERFLOW;DbgPrint(IOCTL_WRITE_DATA: Data too long!\n);gotoEnd;}// 将数据拷贝到设备内部缓存RtlCopyMemory(pDevExt-szDevBuffer,pData-szBuffer,pData-dwDataLen);pDevExt-dwDevBufferLenpData-dwDataLen;pData-dwErrorCodeSTATUS_SUCCESS;// 写入成功pIrp-IoStatus.Informationsizeof(DEV_DATA);DbgPrint(Write Data: Len%d, Data%s\n,pData-dwDataLen,pData-szBuffer);}/************************ 处理IOCTL_READ_DATA ************************/elseif(ulIoControlCodeIOCTL_READ_DATA){// 校验输出缓冲区大小if(ulOutputLen!sizeof(DEV_DATA)){statusSTATUS_INVALID_PARAMETER;DbgPrint(IOCTL_READ_DATA: Output buffer size error!\n);gotoEnd;}// 读取设备内部缓存数据返回给用户态PDEV_DATA pData(PDEV_DATA)pIrp-AssociatedIrp.SystemBuffer;RtlCopyMemory(pData-szBuffer,pDevExt-szDevBuffer,pDevExt-dwDevBufferLen);pData-dwDataLenpDevExt-dwDevBufferLen;pData-dwErrorCodeSTATUS_SUCCESS;pIrp-IoStatus.Informationsizeof(DEV_DATA);DbgPrint(Read Data: Len%d, Data%s\n,pData-dwDataLen,pData-szBuffer);}/************************ 未知IOCTL ************************/else{statusSTATUS_NOT_SUPPORTED;DbgPrint(Unsupported IOCTL: 0x%X\n,ulIoControlCode);gotoEnd;}End:// 完成IRPpIrp-IoStatus.Statusstatus;IoCompleteRequest(pIrp,IO_NO_INCREMENT);returnstatus;}四、步骤3用户态实现ioapist.c 测试程序1. 封装API实现ioapist.c#includewindows.h#includestdio.h#includeioapist.h/************************ 1. 打开设备 ************************/HANDLE __stdcallDevOpen(LPCWSTR lpDevicePath,DWORD dwDesiredAccess){if(lpDevicePathNULL){lpDevicePathDEFAULT_DEVICE_PATH;}// 打开设备需管理员权限HANDLE hDeviceCreateFileW(lpDevicePath,dwDesiredAccess,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(hDeviceINVALID_HANDLE_VALUE){DWORD dwErrGetLastError();printf(DevOpen failed! ErrCode0x%X\n,dwErr);returnNULL;}returnhDevice;}/************************ 2. 关闭设备 ************************/VOID __stdcallDevClose(HANDLE hDevice){if(hDevice!NULLhDevice!INVALID_HANDLE_VALUE){CloseHandle(hDevice);printf(DevClose success!\n);}}/************************ 3. 设置超时 ************************/BOOL __stdcallDevSetTimeout(HANDLE hDevice,PDEV_TIMEOUT pTimeout){if(hDeviceNULL||pTimeoutNULL){SetLastError(ERROR_INVALID_PARAMETER);returnFALSE;}DWORD dwBytesReturned0;BOOL bResultDeviceIoControl(hDevice,IOCTL_SET_TIMEOUT,pTimeout,sizeof(DEV_TIMEOUT),NULL,0,dwBytesReturned,NULL);if(!bResult){DWORD dwErrGetLastError();printf(DevSetTimeout failed! ErrCode0x%X\n,dwErr);}else{printf(DevSetTimeout success! Read%dms, Write%dms, Ctrl%dms\n,pTimeout-dwReadTimeout,pTimeout-dwWriteTimeout,pTimeout-dwCtrlTimeout);}returnbResult;}/************************ 4. 获取设备状态 ************************/BOOL __stdcallDevGetStatus(HANDLE hDevice,PDEV_STATUS pStatus){if(hDeviceNULL||pStatusNULL){SetLastError(ERROR_INVALID_PARAMETER);returnFALSE;}DWORD dwBytesReturned0;BOOL bResultDeviceIoControl(hDevice,IOCTL_GET_DEVICE_STATUS,NULL,0,pStatus,sizeof(DEV_STATUS),dwBytesReturned,NULL);if(!bResult){DWORD dwErrGetLastError();printf(DevGetStatus failed! ErrCode0x%X\n,dwErr);}else{printf(DevGetStatus success! Online%d, ErrorCount%d, BufferSize%d\n,pStatus-bOnline,pStatus-dwErrorCount,pStatus-dwBufferSize);}returnbResult;}/************************ 5. 写数据 ************************/BOOL __stdcallDevWriteData(HANDLE hDevice,PDEV_DATA pData){if(hDeviceNULL||pDataNULL){SetLastError(ERROR_INVALID_PARAMETER);returnFALSE;}DWORD dwBytesReturned0;BOOL bResultDeviceIoControl(hDevice,IOCTL_WRITE_DATA,pData,sizeof(DEV_DATA),pData,// 输出错误码到同一个结构体sizeof(DEV_DATA),dwBytesReturned,NULL);if(!bResult){DWORD dwErrGetLastError();printf(DevWriteData failed! ErrCode0x%X\n,dwErr);}else{printf(DevWriteData success! Len%d, Data%s, ErrCode0x%X\n,pData-dwDataLen,pData-szBuffer,pData-dwErrorCode);}returnbResult;}/************************ 6. 读数据 ************************/BOOL __stdcallDevReadData(HANDLE hDevice,PDEV_DATA pData){if(hDeviceNULL||pDataNULL){SetLastError(ERROR_INVALID_PARAMETER);returnFALSE;}DWORD dwBytesReturned0;BOOL bResultDeviceIoControl(hDevice,IOCTL_READ_DATA,NULL,0,pData,sizeof(DEV_DATA),dwBytesReturned,NULL);if(!bResult){DWORD dwErrGetLastError();printf(DevReadData failed! ErrCode0x%X\n,dwErr);}else{printf(DevReadData success! Len%d, Data%s, ErrCode0x%X\n,pData-dwDataLen,pData-szBuffer,pData-dwErrorCode);}returnbResult;}2. 用户态测试程序TestApp.c#includewindows.h#includestdio.h#includeioapist.hintmain(){HANDLE hDeviceNULL;DEV_TIMEOUT stTimeout{0};DEV_STATUS stStatus{0};DEV_DATA stWriteData{0};DEV_DATA stReadData{0};/************************ 1. 打开设备 ************************/hDeviceDevOpen(DEFAULT_DEVICE_PATH,GENERIC_READ|GENERIC_WRITE);if(hDeviceNULL){printf(Open Device Failed!\n);return-1;}printf(Open Device Success!\n);/************************ 2. 设置超时 ************************/stTimeout.dwReadTimeout6000;// 6秒stTimeout.dwWriteTimeout4000;// 4秒stTimeout.dwCtrlTimeout3000;// 3秒if(!DevSetTimeout(hDevice,stTimeout)){gotoCleanup;}/************************ 3. 获取设备状态 ************************/if(!DevGetStatus(hDevice,stStatus)){gotoCleanup;}/************************ 4. 写数据到设备 ************************/charszWriteBuf[]Hello Custom Device!;RtlCopyMemory(stWriteData.szBuffer,szWriteBuf,strlen(szWriteBuf));stWriteData.dwDataLenstrlen(szWriteBuf);if(!DevWriteData(hDevice,stWriteData)){gotoCleanup;}/************************ 5. 从设备读数据 ************************/RtlZeroMemory(stReadData,sizeof(DEV_DATA));if(!DevReadData(hDevice,stReadData)){gotoCleanup;}/************************ 6. 清理资源 ************************/Cleanup:DevClose(hDevice);printf(Test App Exit!\n);return0;}五、编译与运行说明1. 驱动编译WDK环境依赖Windows Driver KitWDK 10配置驱动项目属性中选择“Kernel Mode Driver”平台选择x64/x86输出生成CustomDev.sys驱动文件。2. 用户态编译VS环境依赖Visual Studio 2019Windows SDK配置控制台项目将ioapist.h、ioapist.c、TestApp.c加入项目编译选项启用Unicode平台选择与驱动一致x64/x86输出生成TestApp.exe可执行文件。3. 运行步骤安装驱动通过sc create CustomDev type kernel binPath C:\CustomDev.sys创建服务sc start CustomDev启动驱动以管理员权限运行TestApp.exe查看输出控制台会打印各步骤结果驱动侧可通过DebugView查看DbgPrint日志卸载驱动sc stop CustomDevsc delete CustomDev。六、关键细节与注意事项权限要求用户态程序需管理员权限否则CreateFile打开设备失败结构体对齐驱动和用户态的结构体必须保证内存对齐避免数据解析错误错误处理驱动侧通过DbgPrint打印调试信息用NT_SUCCESS判断状态用户态通过GetLastError获取错误码常见错误ERROR_INVALID_HANDLE设备句柄无效ERROR_NOT_SUPPORTED驱动不支持该IOCTLERROR_ACCESS_DENIED无管理员权限缓冲区方式示例中用METHOD_BUFFERED最通用驱动侧通过pIrp-AssociatedIrp.SystemBuffer访问数据符号链接驱动创建的符号链接\\DosDevices\\CustomDevice对应用户态的\\\\.\\CustomDevice需保证名称一致。七、运行预期输出用户态控制台Open Device Success! DevSetTimeout success! Read6000ms, Write4000ms, Ctrl3000ms DevGetStatus success! Online1, ErrorCount0, BufferSize1024 DevWriteData success! Len19, DataHello Custom Device!, ErrCode0x0 DevReadData success! Len19, DataHello Custom Device!, ErrCode0x0 DevClose success! Test App Exit!该示例完整覆盖了“驱动初始化→用户态打开设备→下发参数→数据交互→关闭设备→驱动卸载”全流程可直接基于此扩展更多功能如设备错误处理、超时触发逻辑等。