深解WOSA/XFS中的内存分配函数

微软制定WOSA/XFS规范,并不是一件简单的事情。如果对Windows操作系统本身理解的足够深入的话,会理解WOSA架构里面的很多内容,远不是想象的那么简单。首先我们要清楚WOSA架构并不是只存在于XFS规范中,微软还有很多地方在使用WOSA架构,比较常见的如WinSock套接字、ODBC数据库等。所有的这些都用到同样的软件架构,差别的只是具体的扩展有些许不同而已。

      我们的话题谈不了太大,今天只是来看看WOSA/XFS中有关内存管理策略的几个函数,这几个函数只要了解的人都会知道,它们分别是WFMAllocateBuffer、WFMAllocateMore、WFMFreeBuffer、WFSFreeResult。我也在以前的文章中提到了WOSA/XFS中的内存管理策略,不过我觉得还是换一个角度来详细深入的讲讲它们,因为只要是做ATM行业的,无论你是完全自己写ATMC和SP,还是利用其他公司的平台(比如KAL公司的Kalignite平台、Diebold的Agilis Power平台、NCR的APTRA平台等)来开发整个ATM程序,最终都会涉及到内存部分。如果你有使用其他公司开发平台的经历,一定会遇到不知原因的ATM程序异常等情况,其中很多时候都是因为对WOSA/XFS内存处理不当而引起的。

      对于上面的四个函数来讲,WFMFreeBuffer和WFSFreeResult可以合为一个来看,因为WFSFreeResult主要是提供给上层应用程序释放SP返回的WFSResult结构的,其内部实现与WFMFreeBuffer一样,所以我们可以认为WOSA/XFS中只有三个内存管理函数WFMAllocateBuffer、WFMAllocateMore、WFMFreeBuffer。这三个函数与C语言里面的库函数malloc、realloc、free的功能是一一对应的。WFMAllocateBuffer用来分配一块内存,WFMAllocateMore是在WFMAllocateBuffer分配的基础上再多分配一块内存,WFMFreeBuffer是用来释放前两者分配的内存的。

      既然是这样,我们显而易见的一个问题是为什么WOSA/XFS架构中另外提供三个函数来管理内存,而不是直接使用C语言的库函数呢?

      (以下为了便于理解,称XFS Manager层上面叫做ATMC应用,XFS Manager层下面的叫做SP,请做好区分)

      考虑一下WOSA/XFS规范提到什么情况下应该用这几个内存管理函数?是ATMC应用需要将内存数据通过XFS Manager传到SP里面,或者相反,SP需要将内存数据通过XFS Manager传到ATMC应用里面,也就是只有在ATMC应用和SP之间需要传送数据时才用WOSA/XFS提供的内存管理函数。比如最常见的情况,ATMC应用调用WFSExecute命令时传入的参数 LPVOID lpCmdData,它是要用WFMAllocateBuffer来分配的,最后在SP里面调用WFMFreeBuffer来释放。

      如果你认为ATMC在调用WFSExecute可以直接使用malloc或者new来分配内存,代替WFMAllocateBuffer,这种看法是错误的。可能根据你的经验,发现直接用malloc或者new,整个ATMC应用也可以正常运行,但不表示它可以在其他厂家的SP上面运行。因为调用WFSExecute的地方,你可能是用VC编译器来写的ATMC应用,而调用的SP恰恰也是用VC写的,那么你们的malloc或者new的分配策略是一样的,没有问题。但是很多时候并不是都用VC来编写的ATMC应用和SP,可能你用VC编写ATMC应用,但是厂家的SP是用C++ Builder来编译,或者用不出名的C/C++编译器来编译,每个编译器对于C/C++规范中的malloc或者new实现不同,不能保证malloc或者new的通用性(一般是通用的)。更进一步考虑,如果厂家用非C/C++的语言来写SP,那它的SP根本不会理解ATMC传下了的内存。

      同样,ATMC应用也可以用不同的语言来调用API,甚至整个ATM软件中用多种编程语言写各个模块,它们之间的交互也就更加复杂。

      正因为存在上面提到的问题,WOSA/XFS需要统一内存的分配管理,只要通过XFS Manager交互数据,就需要使用其提供的内存管理函数,这样就会保证ATMC应用和SP之间对内存解释的是完全一致的。一样的情况在软件行业并不鲜见,如果熟悉微软的COM技术,就会知道为了统一COM领域的内存分配策略,微软提供了CoTaskMemAlloc系列函数来避免COM组件之间对内存分配的差异。

      现在我们应该明白了在WOSA/XFS中要尽量使用其提供的内存管理函数,而不要使用其他的内存分配函数。但是如果你的内存地址不通过XFS Manager层来传送,比如在你的SP内部,是可以用malloc、new来分配内存的。因为是在SP内部使用这些内存,你的SP都是用同一个编译器来编译,所以不存在对内存分配解释差异的问题;但是,如果你的SP各个模块都会用不同的编译器来写,那也要使用WOSA/XFS提供的函数为好。

      总之,只要两个模块可能存在用不同语言或者编译器的情况,就要考虑使用WOSA/XFS提供的内存管理函数。

      WOSA/XFS提供的内存管理函数还有个很好的功能,就是它的WFMFreeBuffer是可以释放内存链的。如果对WFMAllocateBuffer、WFMAllocateMore比较熟悉,就会知道当用WFMAllocateMore分配时,其与最开始分配的内存头是连接在一起的,形成一个链表结构。释放时不需要将链表中每个节点都释放,只需调用WFMFreeBuffer将链表头释放,则该链表中所有的节点都会被释放了。WOSA/XFS里面有很多结构,有了这个特性,那就太好了,我们省了很多事。但是要小心使用这个特性,如果用不好链式分配的功能,很容易导致ATM软件崩溃,尤其是使用象KAL平台的测试工具时,很容易就看到网页异常了。

      WOSA/XFS提供的内存管理函数存在一个问题就是它是基于内存映射文件的,分配的效率和速度比malloc等差了很多,不过对于ATM软件来说,这些效率的降低也不需要多加在意,毕竟不是操作系统内核处理程序,况且用内存映射机制还有利于内存共享,至于WOSA/XFS中利用内存映射机制进行跨进程内存共享在这里就不多说了。

      好了,我们已经看完了WOSA/XFS的内存管理策略,对其也算是掌握了,以后遇到相关的问题应该就可以轻松解决。

猜你喜欢

转载自blog.csdn.net/qq_26422355/article/details/52980156