阅读:14245回复:23
c从kernel里映射出来的地址在applicatinon里为什么不好使?(付有代码,50分)
PVOID pBee;
PVOID userAddress; 在DispatchIOControl里的代码: ...... ...... pBee = ExAllocatePoolWithTag(NonPagedPool,PAGE_SIZE,'xjuw'); mdl = IoAllocateMdl(pBee,PAGE_SIZE,FALSE,FALSE,NULL); MmBuildMdlForNonPagedPool(mdl); outBeeAddress= MmMapLockedPagesSpecifyCachemdl,UserMode,MmCached, NULL,FALSE,NormalPagePriority); RtlCopyMemory(pSmartcardExtension->IoRequest.ReplyBuffer,&outBeeAddress,sizeof(PVOID)); *pSmartcardExtension->IoRequest.Information = sizeof(PVOID); return STATUS_SUCCESS; 我省去了一些检查分配的代码,outBeeAddress de的值是0x630000. z在application端的代码: PVOID pBeeAddress; unsigned char abc[10] = {0x01,0x02...0x0A}; 通过DeviceIOControl得到kernel里传出的outBeeAddress的值, 然后我发现pBeeAddress的是确实也是0x630000. 但是当我做: memcpy(pBeeAddress,abc,10); 的时候application程序就崩掉了,请问为深么啊?0x630000不是从kernel里映射到user地址空间的地址吗? |
|
最新喜欢:imlym |
沙发#
发布于:2005-01-23 23:56
我是这样造的. |
|
板凳#
发布于:2005-01-24 09:13
把outBeeAddress= MmMapLockedPagesSpecifyCachemdl,UserMode,MmCached,
改成MmBuildMdlForNonPagedPool(pMdl); 那个pBee应该就是返回的共享地址。 |
|
|
地板#
发布于:2005-01-24 09:15
PVOID pBee; 试一试在映射前加一句 MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess); |
|
|
地下室#
发布于:2005-01-24 09:30
你在应用层访问该地址前用SOFTICE看看该地址是否已经存在了?
还有建议你在DRIVERENTRY里分配内存,影射MDL等,而在DispatchIOControl里只需MmMapLockedPages即可. |
|
|
5楼#
发布于:2005-01-24 09:39
看看下面的代码
PVOID pBee; |
|
|
6楼#
发布于:2005-01-24 09:40
刚才附件没有发上去
|
|
|
7楼#
发布于:2005-01-24 11:46
[quote] 我是这样造的. [/quote] 这样不行,我试过了,在app里说access violation,我想也是这样,一个kernel的地址怎么可以直接拿来app里用 |
|
8楼#
发布于:2005-01-24 11:49
你在应用层访问该地址前用SOFTICE看看该地址是否已经存在了? 拿到的0x00630000确实在VC的debug里看到内容都是??????, 那么为什么映射出来的地址会没定义呢,我已经在driverEntry里声明内存和分配mdl了,在ioctrl里进行映射,可是还是没用啊 |
|
9楼#
发布于:2005-01-24 11:56
[quote] 我是这样造的. [/quote] 请给一些你的变量说明好吗? |
|
10楼#
发布于:2005-01-24 12:10
试过了,也没用。 |
|
11楼#
发布于:2005-01-24 12:11
救命啊,
有谁能看出问题在哪儿吗? |
|
12楼#
发布于:2005-01-25 16:02
从0x630000这个地址上看,小于2G,肯定是应用层地址,我估计是应用层地址在这段上尚未映射,是空洞。
|
|
|
13楼#
发布于:2005-01-25 22:57
救命啊, 看了我上面的哪个代码吗? 仔细参考看看,应该可以 |
|
|
14楼#
发布于:2005-01-26 09:17
把你完整的工程贴上来看看.......
|
|
|
15楼#
发布于:2005-01-26 17:02
[quote]救命啊, 看了我上面的哪个代码吗? 仔细参考看看,应该可以 [/quote] 我看了,可是那个是每次交换数据都要通过DeviceIOControl的,我的要求是映射一次就一直可以用啊,看看我发的新帖子好吗,里面有我的driver的具体需求和实现设想,谢谢 |
|
16楼#
发布于:2005-01-26 17:07
从0x630000这个地址上看,小于2G,肯定是应用层地址,我估计是应用层地址在这段上尚未映射,是空洞。 请问“用层地址在这段上尚未映射,是空洞”是什么意思? 我确实没有在应用层开出一个buffer, 只是声明了一个PVOID pFromKernel 指针, 并把0x630000附给这个指针,然后就直接写诸如: pFromKernel[0] = 0x01; 这时app就出问题了。 请问我是不是在app里少做了什么啊?多谢各位了 |
|
17楼#
发布于:2005-01-27 11:11
就是这个地址在应用程序页表中尚未映射,还未用到这块空间
|
|
|
18楼#
发布于:2005-01-27 12:24
就是这个地址在应用程序页表中尚未映射,还未用到这块空间 怎么映射呀,在app里有api可以调吗? |
|
19楼#
发布于:2005-01-27 15:59
[quote]就是这个地址在应用程序页表中尚未映射,还未用到这块空间 怎么映射呀,在app里有api可以调吗? [/quote] 看看这个 IoAllocateMdl 创建MDL IoBuildPartialMdl 创建一个已存在MDL的子MDL IoFreeMdl 销毁MDL MmBuildMdlForNonPagedPool 修改MDL以描述内核模式中一个非分页内存区域 MmGetMdlByteCount 取缓冲区字节大小 MmGetMdlByteOffset 取缓冲区在第一个内存页中的偏移 MmGetMdlVirtualAddress 取虚拟地址 MmGetSystemAddressForMdl 创建映射到同一内存位置的内核模式虚拟地址 MmGetSystemAddressForMdlSafe 与MmGetSystemAddressForMdl相同,但Windows 2000首选 MmInitializeMdl (再)初始化MDL以描述一个给定的虚拟缓冲区 MmPrepareMdlForReuse 再初始化MDL MmProbeAndLockPages 地址有效性校验后锁定内存页 MmSizeOfMdl 取为描述一个给定的虚拟缓冲区的MDL所占用的内存大小 MmUnlockPages 为该MDL解锁内存页 对于I/O管理器执行的Direct方式的读写操作,其过程可以想象为下面代码: KPROCESSOR_MODE mode; // either KernelMode or UserMode PMDL mdl = IoAllocateMdl(uva, length, FALSE, TRUE, Irp); MmProbeAndLockPages(mdl, mode, reading ? IoWriteAccess : IoReadAccess); <code to send and await IRP> MmUnlockPages(mdl); ExFreePool(mdl); I/O管理器首先创建一个描述用户缓冲区的MDL。IoAllocateMdl的第三个参数(FALSE)指出这是一个主数据缓冲区。第四个参数(TRUE)指出内存管理器应把该内存充入进程配额。最后一个参数(Irp)指定该MDL应附着的IRP。在内部,IoAllocateMdl把Irp->MdlAddress设置为新创建MDL的地址,以后你将用到这个成员,并且I/O管理器最后也使用该成员来清除MDL。 这段代码的关键地方是调用MmProbeAndLockPages(以粗体字显示)。该函数校验那个数据缓冲区是否有效,是否可以按适当模式访问。如果我们向设备写数据,我们必须能读缓冲区。如果我们从设备读数据,我们必须能写缓冲区。另外,该函数锁定了包含数据缓冲区的物理内存页,并在MDL的后面填写了页号数组。在效果上,一个锁定的内存页将成为非分页内存池的一部分,直到所有对该页内存加锁的调用者都对其解了锁。 在Direct方式的读写操作中,对MDL你最可能做的事是把它作为参数传递给其它函数。例如,DMA传输的MapTransfer步骤需要一个MDL。另外,在内部,USB读写操作总使用MDL。所以你应该把读写操作设置为DO_DIRECT_IO方式,并把结果MDL传递给USB总线驱动程序。 顺便提一下,I/O管理器确实在stack->Parameters联合中保存了读写请求的长度,但驱动程序应该直接从MDL中获得请求数据的长度。 ULONG length = MmGetMdlByteCount(mdl); 不行的话,自己从0开始做就复杂了 |
|
|
上一页
下一页