阅读:1759回复:11
帮忙看一下内存操作的问题
我按照以下的办法实现应用程序与驱动之间的共享内存:
首先如下分配内存: SystemVirtualAddress = MmAllocateContiguousMemory(NumberOfBytes, HighestAcceptableAddress); 或 SystemVirtualAddress = ExAllocatePool(PoolType, NumberOfBytes); 如下分配一个 MDL: Mdl = IoAllocateMdl(SystemVirtualAddress, NumberOfBytes, FALSE, FALSE, NULL); 建立 MDL 以描述内存页。 MmBuildMdlForNonPagedPool(Mdl); 如下将锁定的页面映射至进程的用户地址空间中: UserVirtualAddress = MmMapLockedPages(Mdl, UserMode); 然后用IOCTL将UserVirtualAddress传递给应用程序如下pSystemBuffer = Irp->AssociatedIrp.SystemBuffer; *(PVOID*)pSystemBuffer=deviceExt->VirtualAddress; 在应用程序中接收该虚拟地址如下: PCHAR Buffer; DeviceIoControl(app->hDevice, (DWORD)hEventPass, NULL, 0, (PCHAR)&Buffer,sizeof(PVOID), &count, NULL) 之后我在驱动中对pSystemVirtualAddress的读写都没有问题,可是在应用程序中对接收了虚拟地址的Buffer读写都出错,请问错在哪里? |
|
最新喜欢:![]() |
沙发#
发布于:2003-09-30 11:10
*(PVOID*)pSystemBuffer=deviceExt->VirtualAddress;
修改为: *(ULONG*)pSystemBuffer=(ULONG)(UserVirtualAddress); |
|
|
板凳#
发布于:2003-09-30 11:45
在应用程序的IOCTL里该怎么做,我弄来弄去来是死机阿
|
|
地板#
发布于:2003-09-30 11:58
#include \"ntddk.h\" #include \"..\\common\\ShareMemory.h\" static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); static NTSTATUS MydrvDispatchIoctl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject); PVOID SystemVirtualAddress, UserVirtualAddress; PMDL Mdl; NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNICODE_STRING nameString, linkString; PDEVICE_OBJECT deviceObject; NTSTATUS status; WCHAR wBuffer[200]; nameString.Buffer = wBuffer; nameString.MaximumLength = 200; DriverObject->DriverUnload = DriverUnload; RtlInitUnicodeString(&nameString, L\"\\\\Device\\\\My_ShareMemory\" ); status = IoCreateDevice(DriverObject, 0, &nameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject ); if (!NT_SUCCESS(status)) return status; deviceObject->Flags |= DO_BUFFERED_IO; RtlInitUnicodeString(&linkString, L\"\\\\??\\\\My_ShareMemory\"); status = IoCreateSymbolicLink (&linkString, &nameString); if (!NT_SUCCESS(status)) { IoDeleteDevice (DriverObject->DeviceObject); return status; } DriverObject->MajorFunction[IRP_MJ_CREATE] = MydrvDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = MydrvDispatch; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MydrvDispatchIoctl; SystemVirtualAddress = ExAllocatePool(NonPagedPool, 1024); Mdl = IoAllocateMdl(SystemVirtualAddress, 1024, FALSE, FALSE, NULL); MmBuildMdlForNonPagedPool(Mdl); strcpy(SystemVirtualAddress, \"In Driver\"); DbgPrint((char *)SystemVirtualAddress ); DbgPrint(\"\\n\"); return STATUS_SUCCESS; } static NTSTATUS MydrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status; PIO_STACK_LOCATION irpSp; // UNREFERENCED_PARAMETER(DeviceObject); //得到当前IRP (I/O请求包) irpSp = IoGetCurrentIrpStackLocation(Irp); switch (irpSp->MajorFunction) { case IRP_MJ_CREATE: Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0L; break; case IRP_MJ_CLOSE: Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0L; break; case IRP_MJ_CLEANUP: MmUnmapLockedPages(UserVirtualAddress, Mdl); break; default: break; } IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } static NTSTATUS MydrvDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpStack; NTSTATUS status; ULONG ControlCode; ULONG InputLength, OutputLength; TCHAR wInputBuffer[200]; TCHAR OutMsg[] = \"Hello, Application!\"; //得到当前IRP (IO请求包) IrpStack = IoGetCurrentIrpStackLocation( Irp ); //得到DeviceIoControl传来的控制码 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; //得到DeviceIoControl传来的输入缓冲区长度 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; //得到DeviceIoControl的输出缓冲区长度 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (ControlCode) { case IOCTL_SHAREMEMORY_GETVADDR: try { UserVirtualAddress = MmMapLockedPages(Mdl, UserMode); *((PVOID *)(Irp->AssociatedIrp.SystemBuffer)) = UserVirtualAddress; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(PVOID); } except(EXCEPTION_EXECUTE_HANDLER){} break; case IOCTL_SHAREMEMORY_SHOWCONTENT: DbgPrint(\"Now the shared memory is : \"); DbgPrint((char *)SystemVirtualAddress ); DbgPrint(\"\\n\"); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0L; default: break; } status = Irp->IoStatus.Status; //完成IRP请求 IoCompleteRequest(Irp, 0); return status; } VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject) { UNICODE_STRING nameString; RtlInitUnicodeString(&nameString, L\"\\\\??\\\\My_ShareMemory\"); IoDeleteSymbolicLink(&nameString); IoDeleteDevice(pDriverObject->DeviceObject); ExFreePool(SystemVirtualAddress); IoFreeMdl(Mdl); return; } |
|
|
地下室#
发布于:2003-09-30 13:30
现在的问题是我已经可以在驱动中把UserVirtualAddress正确的传递给应用程序,当时应用程序却不能对这个地址读写,一操作就出错!
所以问题可能在两个方面:1。可能在驱动中没有正确地映射到用户地址空间2。是不是win2000不允许Win32程序访问不在一个任务的地址空间中的内存? |
|
5楼#
发布于:2003-09-30 13:37
另外对于内存的申请和用户进程地址的映射我都是在DriverEntry中实现的,会不会有问题?
|
|
6楼#
发布于:2003-09-30 14:14
问题已经解决了,原来映射用户地址空间那一步是不能在DriverEntry里头实现得,要在调度进程的上下文中映射
|
|
7楼#
发布于:2003-09-30 15:46
当然,不然是运行在ARBITRARY CONTEST中,所以对用户地址的访问需要加入SEH.
|
|
|
8楼#
发布于:2004-04-21 10:35
hoosyman:
我也遇到了这样的问题,我在驱动中分配的内存也是对的,我是在driverentry下分配的内存,在ioctl下映射得内存。可是我在应用程序却不能到正确的。我觉得我程序没有问题。不知道怎么回事,请帮帮忙。 应用程序: DWORD DataBuf[1024]; if(!DeviceIoControl(hAMCC5920, IOCTL_AMCC5920_MAP_MEMORY, NULL, 0,(PDWORD)&DataBuf, sizeof(1024), &dwReturnedLength, NULL)) { printf(\"Ioctl mapmemory failed x%\\n \",GetLastError()); } 驱动程序: SystemVirtualAddress = ExAllocatePool(NonPagedPool,1024*9); //allocate memory in driver Mdl = IoAllocateMdl(SystemVirtualAddress, 1024*9, FALSE, FALSE, NULL); if(!Mdl) { ExFreePool(SystemVirtualAddress); return(NULL); } MmBuildMdlForNonPagedPool(Mdl); case IOCTL_AMCC5920_MAP_MEMORY: try { UserVirtualAddress = MmMapLockedPagesSpecifyCache(Mdl, UserMode,NULL,NULL,FALSE,NULL); // Priority DbgPrint(\"IO_GETADD:pUserVirAdd=%d\\n\",UserVirtualAddress);// *((PVOID *)(pIrp->UserBuffer)) = UserVirtualAddress; if(UserVirtualAddress==0) { DbgPrint(\"UserVirtualAddress==0\\n\");// Status=(!STATUS_SUCCESS); break; } pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = sizeof(PVOID); |
|
9楼#
发布于:2004-04-27 08:54
/////////////////////////////////////////////////////////
现在的问题是我已经可以在驱动中把UserVirtualAddress正确的传递给应用程序,当时应用程序却不能对这个地址读写,一操作就出错! 所以问题可能在两个方面:1。可能在驱动中没有正确地映射到用户地址空间2。是不是win2000不允许Win32程序访问不在一个任务的地址空间中的内存? ////////////////////////////////////////////////////// 我现在遇到的问题和你上面的一模一样,我在应用程序中得了正确的地址,可是就是不能访问,请问你最后是怎么解决的亚?我的程序 已经贴出来了,请帮帮忙忙好么? |
|
10楼#
发布于:2004-04-27 11:01
////////////////////////////////////////////////////
DWORD DataBuf[1024]; if(!DeviceIoControl(hAMCC5920, IOCTL_AMCC5920_MAP_MEMORY, NULL, 0,(PDWORD)&DataBuf, sizeof(1024), &dwReturnedLength, NULL)) { printf(\"Ioctl mapmemory failed x%\\n \",GetLastError()); } ///////////////////////////////////////////////////// 改为: DWORD DataBuf[1024]; if(!DeviceIoControl(hAMCC5920, IOCTL_AMCC5920_MAP_MEMORY, NULL, 0,(PULONG)&DataBuf, sizeof(ULONG), &dwReturnedLength, NULL)) { printf(\"Ioctl mapmemory failed x%\\n \",GetLastError()); } |
|
11楼#
发布于:2004-04-29 09:19
谢谢,好了!可是又有新问题了。
|
|