首页 > 范文大全 > 正文

一种Windows中内核态和用户态之间交互数据的方法在基于PC的开放式数控系统中的应用

开篇:润墨网以专业的文秘视角,为您筛选了一篇一种Windows中内核态和用户态之间交互数据的方法在基于PC的开放式数控系统中的应用范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!

摘要:在基于Windows平台的开放式的数控系统中,内核态程序和用户态程序之间的数据交互非常大,而且效率往往不高,该文提出一种使用windows的内存映射技术实现高速数据交互的技术,能有效地解决数据交互慢的问题。

关键词:数据交换;双向缓冲区;内核态;用户态;开放式数控系统;Windows平台

中图分类号:TP393文献标识码:A文章编号:1009-3044(2011)16-3766-02

1 问题的提出

数控机床最重要的工作是自动加工,在开放式数控系统中,执行自动加工功能时,数据处理的流程一般如图1。

一个编制好的加工文件,首先经过pc用户态程序的处理,完成所谓粗插补的工作,然后控制系统再把粗插补的结果通过CNC内核(俗称驱动)传递给运动控制卡,让控制卡完成精插补的工作。实际中,在CNC内核层会完成更多的、实时性相对高的工作,比如端口扫描,为了讨论方便,忽略这些内容。

所谓的粗插补,是指对文件的一系列操作,包括对文件描述的刀路的语义理解、速度规划、轨迹处理、插补等等。人们之所以选择在PC上完成粗插补,是看中了计算机强大的运算能力。但一般人们不会采用在CNC内核层完成粗插补的工作,有如下原因:1)Windows系统在调度内核模式的线程时不会自动保存和恢复浮点寄存器中的内容,如要做需要手工完成;2)CNC内核中的程序不方便调试(俗称驱动程序不方便调试);3)为了保证控制卡处理数据的完整性,一般的控制系统都会设计成驱动程序由控制卡发出的中断来驱动运行,在中断服务程序中一般不宜做特别复杂的事情;有时,对于复杂的插补算法和刀路情形,可能需要较长的计算时间,这在性能上是不允许的。因此,人们一般把粗插补工作放在应用程序层,然后把插补结果传递给驱动程序。

这里有一个问题:当用户应用程序完成粗插补后,插补结果的数据量一般都是巨大的,而用户程序和内核程序之间的数据传递一般情况下是不方便的,这就要求人们找到一种高效的方法来完成数据交换。

从Intel80386开始,出于安全性和稳定性的考虑,该系列的CPU可以运行于ring0~ring3从高到低四个不同的权限级,对数据也提供相应的四个保护级别。运行于较低级别的代码不能随意调用高级别的代码和访问较高级别的数据,而且也只有运行在ring0层的代码可以直接对物理硬件进行访问。由于WindowsNT是一个支持多平台的操作系统,为了与其他平台兼容,它只利用了CPU的两个运行级别。一个被称为内核模式,对应80×86的ring0层,是操作系统的核心部分,设备驱动程序就是运行在该模式下;另一个被称为用户模式,对应80×86的ring3层,操作系统的用户接口部分(就是我们通常所说的Win32 API)以及所有的用户应用程序都运行在该级别。

运行在这两个模式下的程序,一般都是通过专门的API(应用程序接口)函数DeviceIOControl进行数据交换的,用户模式程序通过该函数向内核程序申请服务,同时把需要传递的数据一并告知;内核程序在接收到该服务申请信息以后,将传递的数据拷贝到内核的缓冲区中。这就造成在传递数据之前和传递到内核程序以后,都需要进行数据的拷贝,并且,DeviceIOControl函数在执行时也有较大的开销,因此造成用这种方法进行数据传递效率不高。为了解决上述方案的不足,本文给出另一种使用内存映射的方式来完成数据交换的方法。

2 内存映射方式传递数据

我们知道,32位Windows操作系统会为每个应用程序分配4G的内存地址空间,这些在逻辑上连续的内存地址所对应的物理地址其实并不一定连续。既有可能把不相邻的存储空间映射成相邻的,也可能把相邻的物理块映射成不相邻的逻辑地址。同时,它还具有把同一块物理存储设备分别映射到不同的地址的能力。本方案使用的就是操作系统的后一种能力。

方案思路:将某一块内存空间,分别映射到内核地址空间和用户模式地址空间,这样,两种模式下的程序就可以直接对该内存区域进行读写,从而达到数据交换的目的。

图2中,物理内存C被分别映射成用户地址空间的A和内核地址空间的B,内核模式程序从B处开始读取数据,用户程序从A处开始写入数据。

Windows提供了相应的API函数和数据结构,整个过程叙述如下:

首先申请一个MDL(内存描述表,memory descriptor list),用来映射我们需要大小的内存地址;然后从已获得的MDL分配一块物理内存,获得其起始地址,最后把这块内存地址映射到用户地址空间中。上述过程依次使用IoAllocateMdl、MmBuildMdlForNonPagedPool和MmMapLockedPages三个API函数。

下面是一个例子(假设CNccmdFifo为描述缓冲区的数据结构):

CNccmdFifo NccmdFifo;

PMDL pMdlNccmdFifo = IoAllocateMdl(&NccmdFifo, sizeof(NccmdFifo), false, false, NULL);

MmBuildMdlForNonPagedPool(pMdlNccmdFifo);

void* pNccmdFifoUserSpace = (CNccmdFifo*)MmMapLockedPages(pMdlNccmdFifo, UserMode);

现在pNccmdFifoUserSpace即为用户在用户模式中也能访问的地址。从这以后,用户可以直接在用户模式中向该地址写入数据,也可以直接从内核模式读取该缓冲区中的数据。

3 效率比较

作者所从事的工作是开发开放式数控系统,为了对比如上两种方案的效率,在公司一款已经成熟的产品上做测试,结果表明,使用内存直接映射的方式,在效率上有较大的优势。表1是一些测试数据。

表1所测试的文件约500行,从数据可以看出,使用缓冲区映射方式,所花费的时间只有使用普通方式(用DeviceIOControl交换)的78.85%,效率明显提高。

表2是更多的实验数据。

从表2能看出,内存映射方式有较大优势。

4 优缺点和一些问题

因为对读写信息存储时为了避免因为线程的调度而产生问题,需要让记录在一个指令中完成,这意味着从理论上讲,该映射空间不能太大,不能大于2^32(4G),实际上这是远远够用的。

内存映射要求使用物理内存进行映射,不能将这些内存用作交换区,减少了交换区内存的使用量。

实现比较复杂,要求对Windows操作系统有较深的了解。

因为对缓冲区的访问是在不同的线程中进行的,一个读,另一个可能会同时写,需要处理访问冲突的情况。

在对比两种数据交换方式的效率时,笔者发现,如果遇到一些极端的加工文件,它们在粗插补阶段需要花费较多的时间的话,整体的效率差别就会比较小,这是本方案在实际应用时需要考虑到的一点。

参考文献:

[1] 张建生,赵燕伟.数控系统应用及开发[M].北京:科学出版社,2006.

[2](美)布赖恩特.深入理解计算机系统[M].北京:电子工业出版社,2006.

[3](美)Jeffrey Richter.Windows核心编程[M].北京:机械工业出版社,2008.

[4] 罗学科,赵玉侠.典型数控系统及其应用[M].北京:化学工业出版社,2006.

注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文