Programming 版 (精华区)

发信人: Sun (大灯泡), 信区: Programming
标  题: [转载] 讨论]关于数据采集卡驱动的内存分配问题 k
发信站: 紫 丁 香 (Thu Sep  9 10:41:47 1999), 转信

【 以下文字转载自 VisualProgram 讨论区 】
【 原文由 xiaojun 所发表 】


主题: [讨论]关于数据采集卡驱动的内存分配问题 kingchurch (转寄)
日期: 1998年9月19日 07:30:54
发件人: lyj.bbs@bbs.net.tsinghua.edu.cn
收件人: lyj@hs1.hit.edu.cn

发信人: gmouse (大大灰狼), 信区: Programming

各位VXD编程高手:
    小弟这相有礼了!近日碰到难题,此番提出,还望多多指教!
    
     我对自行开发的数据采集卡编一驱动.VXD,实现采集卡的buffer
满后,中断处理过程中将此buffer中的数据(32K)用memcpy()方式拷贝
到应用程序的全局堆块中(用GlobalAlloc(GPTR,0x8000)分配得到)。
如此即可由应用程序处理此数据块的内容。我在应用程序中分配好全局
堆之后,调用VXD的PM_API接口将此内存指针传给我的VXD,VXD接到之后,
将此指针值转换为VXD的FLAT地址,并启动采集过程。
我遇到的问题是,如何将全局内存指针--》VXD的可操作地址值?此方案
是否有漏洞?

1。我用到的结构:
   typedef struct _PostMsgRequest
{
        WORD    ServiceID;      // supplied by caller
        WORD    PostMsghWnd;
        WORD    PostMsgSeg;
        WORD    PostMsgOff;
        WORD    BufferSeg;
        WORD    BufferOff;
        WORD    BufferSize; 
        WORD    Status;                         
} POSTMSGREQUEST, *PPOSTMSGREQUEST;

2。VXD中部分过程:

   VOID PM_Api_Handler(VMHANDLE hVM, PCLIENT_STRUCT pRegs)
{
        PPOSTMSGREQUEST pReq;
        DWORD temp;
        
        
        pReq = Map_Flat(CLIENT_ES, CLIENT_DI);
        if (pReq == NULL)       // validate
                return;

        // branch on requested service

        switch (pReq->ServiceID)
        {

        case PMVXD_REGISTER:

             pMemory = Map_Flat(PostMsgSeg,PostMsgOff);
             if(pMemory == NULL)
                return;
             PostMsghWnd       = pReq->PostMsghWnd;
             if(PostMsghWnd==0)
                return;
             PostMsgSelector   = pReq->PostMsgSeg;
             PostMsgOffset     = pReq->PostMsgOff;
             if(PostMsgOffset==0)
                return;  
             bClientRegistered = TRUE;
             pReq->Status      = STATUS_SUCCESS;
             
             break;

        case PMVXD_DEREGISTER:
             pReq->Status = STATUS_FAULT;
             bClientRegistered = FALSE;
             break;

        default:
                pReq->Status = STATUS_FAULT;
        }
        
}

3。应用程序的关键部分:
  BOOL RegisterCallback(HWND hWnd)
      {
        POSTMSGREQUEST req;


        hglb = GlobalAlloc(GPTR, 0x8000L);
        Buffer = GlobalLock(hglb);

        req.ServiceID  = PMVXD_REGISTER;
        req.PostMsghWnd = hWnd;
        req.PostMsgSeg = FP_SEG((FARPROC)PostMessage);
        req.PostMsgOff = FP_OFF((FARPROC)PostMessage);
        req.BufferSeg =  FP_SEG(Buffer);    //Buffer为全局指针
        req.BufferOff =  FP_OFF(Buffer);
        req.BufferSize = 0x8000L;

        _asm lea        di, [req]
        _asm mov        ax, ss
        _asm mov        es, ax

        VxDAddr();   //为VXD的入口API;

        return (req.Status);

    }   




发信人: suxm (笨笨), 信区: Programming

如果你用VXD的WIN32服务接口的话,问题就简单了。
你可以用DeviceIoControl函数。
应用程序可以利用这个函数中向VXD传递参数,如果你传递的参数是一地址
指针,VXD是可以直接用的。

还有一个建议,可以免去中断调用。
解决方案如下, 在VXD和应用程序之间建立一个同步信号灯。
然后开始VXD采集数据,当数据采集满了的时候,使信号灯亮。
这时应用程序去取VXD中的数据。

再补充一点,最好不要用中断调用,因为有很多需要注意的
地方,比如说有很多的VMM服务不能调用。

:    VOID PM_Api_Handler(VMHANDLE hVM, PCLIENT_STRUCT pRegs)
: {
:         PPOSTMSGREQUEST pReq;
:         DWORD temp;
:         pReq = Map_Flat(CLIENT_ES, CLIENT_DI);
:         if (pReq == NULL)       // validate
:                 return;
:         // branch on requested service
:         switch (pReq->ServiceID)
:         {
:         case PMVXD_REGISTER:
:              pMemory = Map_Flat(PostMsgSeg,PostMsgOff);
:              if(pMemory == NULL)
:    :         }
: }
: 3。应用程序的关键部分:
:   BOOL RegisterCallback(HWND hWnd)
:       {
:         POSTMSGREQUEST req;
:         hglb = GlobalAlloc(GPTR, 0x8000L);
:         Buffer = GlobalLock(hglb);
:         req.ServiceID  = PMVXD_REGISTER;
:         req.PostMsghWnd = hWnd;
:         req.PostMsgSeg = FP_SEG((FARPROC)PostMessage);
:         req.PostMsgOff = FP_OFF((FARPROC)PostMessage);
:         req.BufferSeg =  FP_SEG(Buffer);    //Buffer为全局指针
:         req.BufferOff =  FP_OFF(Buffer);
:         req.BufferSize = 0x8000L;
:         _asm lea        di, [req]
:         _asm mov        ax, ss
:         _asm mov        es, ax
:         VxDAddr();   //为VXD的入口API;
:         return (req.Status);
:     }   




发信人: gmouse (大大灰狼), 信区: Programming

  我的VXD最终要为Win31服务,只是没有找到VtoolsD for win 3.1
只好用for win95的做实验,最终的应用程序也是16位的。所以
还望在这些条件内帮我解决,我将不胜感激!
对于win95的VXD设计,我也很感兴趣,希望进一步解释一下你的
设计思想,我的基础太差,刚刚起步,还望耐心指点!
在此先多谢了!


【 在 suxm (笨笨) 的大作中提到: 】
: 如果你用VXD的WIN32服务接口的话,问题就简单了。
: 你可以用DeviceIoControl函数。
: 应用程序可以利用这个函数中向VXD传递参数,如果你传递的参数是一地址
: 指针,VXD是可以直接用的。
: 还有一个建议,可以免去中断调用。
: 解决方案如下, 在VXD和应用程序之间建立一个同步信号灯。
: 然后开始VXD采集数据,当数据采集满了的时候,使信号灯亮。
: 这时应用程序去取VXD中的数据。




发信人: fingertip (自由自在), 信区: Programming

这种方法是将应用程序的数据传递给VXD,如果VXD在中断中使用这些地址,
是否会有问题?据说应使用PageLock或Thread Event?我不太明白。
换过来说,如果在VxD中申请内存,将其转换为Selector和Offset,是否就没有问题乐?

BTW,如果在VC++的App里获得了VxD传来的Selector和Offset,如何将它组装?
不好意思,这个问题有点不入门



发信人: xxhd (侠客), 信区: Programming

【 在 suxm (笨笨) 的大作中提到: 】
: 如果你用VXD的WIN32服务接口的话,问题就简单了。
: 你可以用DeviceIoControl函数。
: 应用程序可以利用这个函数中向VXD传递参数,如果你传递的参数是一地址
: 指针,VXD是可以直接用的。
: 还有一个建议,可以免去中断调用。
: 解决方案如下, 在VXD和应用程序之间建立一个同步信号灯。
: 然后开始VXD采集数据,当数据采集满了的时候,使信号灯亮。
: 这时应用程序去取VXD中的数据。
: 再补充一点,最好不要用中断调用,因为有很多需要注意的
: 地方,比如说有很多的VMM服务不能调用。


Suxm大侠:

从一些资料中看到,用GlobalAlloc 分配的内纯不是shared memory, 必须先使其共享,
另外传到Vxd以后,还要使这快内存pagelocked, Vxd才能在中断处理程序中使用。

但我不知如何先共享内纯, 请问如何做? 在Vxd中Linpagelock
以后,返回的是这片内纯的指针吗?



发信人: suxm (笨笨@迷茫中), 信区: Programming

看来你是想在WINDLL中分配内存了。
用GlobalAlloc,GloballLock,GlobalFix,GlobalPageLock得到
的buffer是全局堆中的,其指针是32位的,高位为16位段选 
择器, 低位为Offset。 这样得到的内存不再需要你在VXD中PageLock
就可以用了 。
在前面的一篇文章里我给出了一个例子,关于如何使用这些API的组合。
查一下啦。

【 在 xxhd (侠客) 的大作中提到: 】
: Suxm大侠:
: 从一些资料中看到,用GlobalAlloc 分配的内纯不是shared memory, 必须先使其共享,
: 另外传到Vxd以后,还要使这快内存pagelocked, Vxd才能在中断处理程序中使用。
: 但我不知如何先共享内纯, 请问如何做? 在Vxd中Linpagelock
: 以后,返回的是这片内纯的指针吗?




发信人: xxhd (侠客), 信区: Programming

【 在 suxm (笨笨@迷茫中) 的大作中提到: 】
: 看来你是想在WINDLL中分配内存了。
: 用GlobalAlloc,GloballLock,GlobalFix,GlobalPageLock得到
: 的buffer是全局堆中的,其指针是32位的,高位为16位段选 
: 择器, 低位为Offset。 这样得到的内存不再需要你在VXD中PageLock
: 就可以用了 。
: 在前面的一篇文章里我给出了一个例子,关于如何使用这些API的组合。
: 查一下啦。

您的这种方法是如何使Vxd共享Win16应用程序所分配的内纯。 那么怎样是Vxd

共享Win32程序分配的内纯呢?




发信人: suxm (笨笨@迷茫中), 信区: Programming

在WIN32APP中用MALLOC,然后在VXD中用PAGEMAPGLOBAL flag的
LinePageLock服务。

BTW:对于WIN16&VXD的内存共享问题,在WIN16中分配内存比较合
    合适。因为如果在VXD中分配内存,那定在2GB以上,而WIN16
    要想访问这块内存就不得不获得特殊的SELECTOR。
  
    对于WIN32&VXD的内存共享问题,还是在VXD中分配内存的好。

【 在 xxhd (侠客) 的大作中提到: 】
: 您的这种方法是如何使Vxd共享Win16应用程序所分配的内纯。 那么怎样是Vxd
: 共享Win32程序分配的内纯呢?




发信人: xxhd (侠客), 信区: Programming

【 在 suxm (笨笨@迷茫中) 的大作中提到: 】
: 在WIN32APP中用MALLOC,然后在VXD中用PAGEMAPGLOBAL flag的
: LinePageLock服务。
: BTW:对于WIN16&VXD的内存共享问题,在WIN16中分配内存比较合
:     合适。因为如果在VXD中分配内存,那定在2GB以上,而WIN16
:     要想访问这块内存就不得不获得特殊的SELECTOR。
:     对于WIN32&VXD的内存共享问题,还是在VXD中分配内存的好。

关键问题是我想分配4M的内纯。malloc 能分配这么大的块吗?还有LinPageLock的参数
需要page number, 而其返回值就是pagelock的指针吗?

要获得page number是否可以这样做: LinPageLock(((DWORD)pointer)>>12,....) ?

另外要想Win16&Vxd 的mem共享,Vc5.0好象不支持Win16的函数,比如GlobalPageLock,
请问那个VC版本可以支持Win16的编程?

谢谢。




发信人: suxm (笨笨@迷茫中), 信区: Programming

【 在 xxhd (侠客) 的大作中提到: 】
: 关键问题是我想分配4M的内纯。malloc 能分配这么大的块吗?还有LinPageLock的参数
: 需要page number, 而其返回值就是pagelock的指针吗?
: 要获得page number是否可以这样做: LinPageLock(((DWORD)pointer)>>12,....) ?

记不得linpagelock的具体用法了。建议你在VXD中用pageallocate分配内存,4M
没有问题。另:MALLOC应该可以分配4M的内存。

: 另外要想Win16&Vxd 的mem共享,Vc5.0好象不支持Win16的函数,比如GlobalPageLock,
: 请问那个VC版本可以支持Win16的编程?

VC1。5 OR VC1。0

: 谢谢。




发信人: xxhd (侠客), 信区: Programming

【 在 suxm (笨笨@迷茫中) 的大作中提到: 】
: 记不得linpagelock的具体用法了。建议你在VXD中用pageallocate分配内存,4M
: 没有问题。另:MALLOC应该可以分配4M的内存。
: VC1。5 OR VC1。0

我也想试试Win16和vxd的通信,VC1.5可能不好找,哪儿有?




--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: hs5.hit.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.118.239.237]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:208.152毫秒