问题的提出
数控机床重要的工作是自动加工 在开放式数控系统中 执行自动加工功能时 数据处理的流程一般如图 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 操作系统有较深的了解
因为对缓冲区的访问是在不同的线程中进行的 一个读 另一个可能会同时写 需要处理访问冲突的情况
在对比两种数据交换方式的效率时 笔者发现 如果遇到一些的加工文件 它们在粗插补阶段需要花费较多的时间的话整体的效率差别就会比较小 这是本方案在实际应用时需要考虑到的一点
本文由 伯特利技术文章 整理发表,文章来自网络仅参考学习,本站不承担任何法律责任。
伯特利数控一直以尽心、尽力、尽意的态度把握每一台 加工中心、钻攻中心的质量
相关文章可查阅本站:技术文章 或本文下方 标签 分类
相关产品可查阅本站:产品中心