XiaoQJ
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2003-06-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1835回复:7

请问IM Driver和Application同步的问题

楼主#
更多 发布于:2003-06-04 19:11
IM Driver的Sample-passthru里的能够截获数据包的例程都是运行
在Deferred Procedure Call的背景里的,比如MpSendPacket、
PtReceive等。所以利用passthru截包的代码都发生在DISPATCH_LEVEL
.我想把截获的数据包通过共享nonpaged memory送给用户态PASSIVE_LEVEL的程序。所以共享内存的访问互斥问题十分麻烦。用户态不能使用spin lock,DISPATCH_LEVEL又不能使用一般的Dispatcher object而发生阻塞。
   我现在挺急,那位大侠能给我些建议。如何作好上面的同步工作。

最新喜欢:

chilichili
XiaoQJ
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2003-06-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-06-04 20:06
我们可以使用shared event或者让用户态线程死锁在DeviceIoControl
的方法来通知Application,驱动代码捕获了合适的数据包。
但是如何使Shared Memory的读和写两种操作,保持原子性,不会发生
所谓的interfere呢?
XiaoQJ
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2003-06-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-06-04 20:52
这种驱动和用户程序共享内存块的方法实际上变相实现了Direct I/O.
但是Microsoft实现Direct I/O的方法是通过将用户态提供的内存块
锁定,再使用Irp->MdlAddress来描述这块已锁定的分页内存。
若此时IoDispatcher发现要回送的数据已经准备好了,就立即将数据
填入Irp->MdlAddress。否则,就有必要作IRP排队。
  我觉得Microsoft的实现方案是没有问题的。因为尽管IoDispatcher
也是工作在PASSIVE_LEVEL,但是它是属于内核代码的一部分。它的代码
存放的空间是不会交换到外存的。重要的结论是IoDispatcher代码有权利使用spin lock(因为是内核的一部分),也可以安全的使用spin lock(因为不会提出页中断)。
  所以Microsoft对于PASSIVE_LEVEL代码和DISPATCH_LEVE代码同步
问题的解决方案是将PASSIVE_LEVEL代码归并如内核并且锁定它的存储空间。这样就可以使用Spin lock来作同步,同时还能支持对称多处理。
   我妄言前面各位大侠提出的Application和IM Driver共享内存,但同时有不加访问互斥的方案是错误的。
   有没有那位大侠,能驳倒我的论点。我将非常感谢!!!
XiaoQJ
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2003-06-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-06-04 21:12
我看了一下,有人使用KeReadStateEvent,在内核态需要将数据包传递给用户态之前先检查Event状态,如果用户态将数据包取走了,再进行数据包传递。否则,这个数据包不予记录。
这种方案虽然变相的使得Shared Memory的读写操作不会互相干扰,但是它经常会丢失要记录的数据。因为内核态的驱动代码没有提供相应的缓冲机制。
XiaoQJ
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2003-06-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-06-04 21:27
如果要解决丢失统计数据的问题,有没有什么好方案?

使用Shared Semaphore同时统计数据在Shared Memory里排队吗?好像不行。

下面这方案,行不行?
让驱动代码在Shared Event还是signaled状态时不丢失数据,而是缓存在某个驱动代码维护的缓冲里面。再使用一个内核timer,定时检查Shared Event的状态。(似乎复杂了一些)

似乎直接使用微软的Direct I/O control是最简单和安全的。而且DeviceIoControl里面还有一个lpOverlapped 的回调函数可以使用。
baoyibao99
禁止发言
禁止发言
  • 注册日期2003-05-07
  • 最后登录2016-04-11
  • 粉丝0
  • 关注0
  • 积分894分
  • 威望8415点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-06-05 09:53
用户被禁言,该主题自动屏蔽!
XiaoQJ
驱动牛犊
驱动牛犊
  • 注册日期2003-05-03
  • 最后登录2003-06-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-06-07 11:24
总结,目前所有的Passthru和Application耦合方式中,方法有二:
方法一(简单)、使用Shared Event和Shared Memory
Application首先Register Shared Event和Get Shared Memory。这个Shared Event一般可以有Application生成。注意不要把Shared Event设置成Auto Reset,而是使用manual reset的Event。并且Event初始状态设为not signaled。
Shared Memory需要映射到用户态进程的虚拟地址空间。
Shared Event注册的时候,注意需要使用ObReferenceObjectByHandle将Event句柄转化成Event指针,因为Event句柄是由进程管理的。每个进程有个句柄表实现从指针到句柄的映射,所以在内核里不可使用事件句柄。
这样,可以开始交互过程:
   Worker thread in Application:
      WaitforSingleObject(pSharedEvent);
      ......
      <对Shared Memory的访问代码>
      ......
      ResetEvent(pSharedEvent);
   DPC 过程 in Passthru
      if(KeReadStateEvent(pSharedEvent))//这样就不会有阻塞
      {   ......
          <向Shared Memory里写数据>
          ......
          KeSetEvent(pSharedEvent,IO_NO_INCREMENT,FALSE)
      }
这种方法较为简单,但是如果DPC 过程两次调用这段代码作写数据工作期间,worker thread没有将Shared Memory的东西取走,那么就会发生数据丢失。
   我在这里抛砖引玉,请那位大侠提出改进意见。
方法二:使用Device I/O control的Direct I/O和IRP排队
   这需要对Passthru里的ADAPT结构体的精细的操作,请那位大侠补充描述一下这种方法。
  
cndustin
驱动牛犊
驱动牛犊
  • 注册日期2004-07-23
  • 最后登录2006-03-03
  • 粉丝0
  • 关注0
  • 积分12分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2005-06-03 21:40
好帖子,在刚入门时挺受益。
游客

返回顶部