关于WOSA/XFS中SP程序报无效地址的错误

关于 WOSA/XFS SP 程序报无效地址的错误
 
刘永胜      2006 年于广州
 
如果深入接触过符合WOSA/XFS规范的软件,会有幸看到有时候软件报以下错误:“invalid virtual base addr., GetLastError: 487”。
 
当定位错误时,会发现是XFS_SUPP.DLL程序报出来的错。
 
如果不知道原因,解决这个问题将会花费一些时间,甚至即使解决了也不知道具体原因。因为有很多人问过该问题,所以将其写下来,以有利于需要的人,节省他们的时间。
 
用regedit程序打开Windows注册表,如果是2.0版本的XFS ,在路径HKEY_CLASSES_ROOT/WOSA/XFS_ROOT/XFS_MANAGER下面,如果是3.0版本的XFS ,在路径HKEY_LOCAL_MACHINE/SOFTWARE/XFS/XFS_MANAGER下面,有几项注册表内容和这个有关,分别是:
ShareMapAddr=6BC00000
ShareFileName=c:/xfs_supp.sys
ShareFileSize=5242880
 
解决上面提到的错误有以下方法(改完后可能要重启机器才生效):
一、将ShareMapAddr的值改变,默认一般该值是6BC00000,把值改大点或改小点,比如改成7BC00000。
二、将ShareMapAddr项删除,让其自动定位地址。
三、修改软件中关于装载DLL的基地址信息,如果是调用LoadLibrary动态装载,则考虑下各个DLL的装载顺序问题。
四、编译时将静态链接的DLL基地址进行修改,避免操作系统加载程序时的重定位基地址,导致使用到了ShareMapAddr以上的地址空间。
 
下面详细讲一下为什么会出现这个错误,这样可以做到知其所以然。
 
因为SP是基于DLL导出接口的形式,所以存在一个多进程共享内存的问题。两个EXE调用同一个设备的SP,因为SP的DLL会被加载到每个EXE进程中,导致它们之间的内存并不能共享,从而导致信息不同步。
 
为了处理这个问题,在WOSA/XFS的内存分配函数WFMAllocateBuffer中的第二个参数ulFlags是比较重要的,如果在程序中使用WFMAllocateBuffer,则XFS Manager会根据ulFlags标志进行不同的处理。
 
如果ulFlags标志设置为0,则使用进程内部的堆内存。此时XFS Manager只是简单的调用HeapAlloc、HeapFree系列Heap处理函数来分配内存,我们都知道这种内存只存在本EXE进程的内部,另外一个进程正常是看不到该内存的,从而内存是私有的,无法共享。
 
如果设置值为WFS_MEM_SHARE,则会使用XFS Manager里面的共享内存。在Windows平台下面,本质上的进程之间共享内存,大多是基于内存映射文件的方式来实现的。XFS Manager在启动的时候,会创建一个内存映射文件,名字就是上面注册表提到的ShareFileName=c:/xfs_supp.sys,该文件会在XFS Manager第一次被调用的时候创建,被映射到ShareMapAddr=6BC00000项所定的基地址,并且向高位地址端保留ShareFileSize=5242880字节的内存范围,是给内存共享使用的,以后访问该块内存,在所有调用该SP DLL的EXE进程里面的该地址段内容将都是一样的,都被映射到ShareFileName=c:/xfs_supp.sys内存映射文件中。如果不存在ShareMapAddr=6BC00000项,则由操作系统来自动分配一个可用的空间,但这个空间的基地址每次装载是可能发生变化的。
 
对于内存映射文件的原理请参考相关资料,这里不多讲。我们显然会想到一个问题就是存在XFS Manager会在ShareMapAddr的基地址处将ShareFileName映射到进程内存空间失败的情况。最大的可能是该地址中的某一段被其他模块占用了。如果这样,XFS Manager则就会报“invalid virtual base addr., GetLastError: 487”,因为XFS Manager不能够将内存映射文件映射到规定的地址空间。
 
好了,知道原因了,就可以理解上面提到的几种解决方法,以后就不会因为这种问题而烦恼了。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1425764 

你可能感兴趣的:(WOSA/XFS,manager,dll,exe,windows,平台,c)