技術文章
介紹一種基于PC端Windows中內核態(tài)和用戶態(tài)之間交互數據的用法
閱讀:291 發(fā)布時間:2020-8-12問題的提出
數控機床重要的工作是自動加工 在開放式數控系統(tǒng)中 執(zhí)行自動加工功能時 數據處理的流程一般如圖 1一個編制好的加工文件 首先經過 PC 用戶態(tài)程序的處理 完成所謂粗插補的工作 然后控制系統(tǒng)再把粗插補的結果通過 CNC 內核 俗稱驅動 傳遞給運動控制卡 讓控制卡完成精插補的工作 實際中 在 CNC 內核層會完成更多的 實時性相對高的工作 比如端口掃描 為了討論方便 忽略這些內容
所謂的粗插補 是指對文件的一系列操作 包括對文件描述的刀路的語義理解 速度規(guī)劃軌跡處理 插補等等 人們之所以選擇在 PC 上完成粗插補 是看中了計算機強大的運算能力 但一般人們不會采用在 CNC 內核層完成粗插補的工作 有如下原因 1 Windows 系統(tǒng)在調度內核模式的線程時不會自動保存和恢復浮點寄存器中的內容 如要做需要手工完成 2 CNC 內核中的程序不方便調試 俗稱驅動程序不方便調試 3 為了保證控制卡處理數據的完整性 一般的控制系統(tǒng)都會設計成驅動程序由控制卡發(fā)出的中斷來驅動運行 在中斷服務程序中一般不宜做特別復雜的事情 有時 對于復雜的插補算法和刀路情形 可能需要較長的計算時間 這在性能上是不允許的 因此 人們一般把粗插補工作放在應用程序層 然后把插補結果傳遞給驅動程序
這里有一個問題 當用戶應用程序完成粗插補后 插補結果的數據量一般都是巨大的 而用戶程序和內核程序之間的數據傳遞一般情況下是不方便的 這就要求人們找到一種高效的方法來完成數據交換
從 Intel80386 開始 出于安全性和穩(wěn)定性的考慮 該系列的 CPU 可以運行于 ring0~ring3 從高到低四個不同的權限級 對數據也提供相應的四個保護級別 運行于較低級別的代碼不能隨意調用高級別的代碼和訪問較高級別的數據 而且也只有運行在 ring0 層的代碼可以直接對物理硬件進行訪問 由于 WindowsNT 是一個支持多平臺的操作系統(tǒng) 為了與其他平臺兼容 它只利用了 CPU 的兩個運行級別 一個被稱為內核模式 對應 80 86 的 ring0 層 是操作系統(tǒng)的核心部分 設備驅動程序就是運行在該模式下 另一個被稱為用戶模式 對應 80 86 的 ring3 層 操作系統(tǒng)的用戶接口部分 就是我們通常所說的 Win32 API 以及所有的用戶應用程序都運行在該級別
運行在這兩個模式下的程序 一般都是通過專門的 API 應用程序接口 函數 DeviceIOControl 進行數據交換的 用戶模式程序通過該函數向內核程序申請服務 同時把需要傳遞的數據一并告知 內核程序在接收到該服務申請信息以后 將傳遞的數據拷貝到內核的緩沖區(qū)中 這就造成在傳遞數據之前和傳遞到內核程序以后 都需要進行數據的拷貝 并且 DeviceIOControl 函數在執(zhí)行時也有較大的開銷 因此造成用這種方法進行數據傳遞效率不高 為了解決上述方案的不足 本文給出另一種使用內存映射的方式來完成數據交換的方法
2.內存映射方式傳遞數據
我們知道 32 位 Windows 操作系統(tǒng)會為每個應用程序分配 4G 的內存地址空間 這些在邏輯上連續(xù)的內存地址所對應的物理地址其實并不一定連續(xù) 既有可能把不相鄰的存儲空間映射成相鄰的 也可能把相鄰的物理塊映射成不相鄰的邏輯地址 同時 它還具有把同一塊物理存儲設備分別映射到不同的地址的能力 本方案使用的就是操作系統(tǒng)的后一種能力
方案思路 將某一塊內存空間 分別映射到內核地址空間和用戶模式地址空間 這樣 兩種模式下的程序就可以直接對該內存區(qū)域進行讀寫 從而達到數據交換的目的
圖 2 中 物理內存 C 被分別映射成用戶地址空間的 A 和內核地址空間的 B內核模式程序從 B 處開始讀取數據 用戶程序從 A 處開始寫入數據
Windows 提供了相應的 API 函數和數據結構 整個過程敘述如下
首先申請一個 MDL 內存描述表 memory descriptor list 用來映射我們需要大小的內存地址 然后從已獲得的 MDL 分配一塊物理內存 獲得其起始地址 后把這塊內存地址映射到用戶地址空間中 上述過程依次使用 IoAllocateMdl MmBuildMdlForNonPagedPool 和 MmMapLockedPages 三個 API 函數
下面是一個例子 假設 CNccmdFifo 為描述緩沖區(qū)的數據結構
CNccmdFifo NccmdFifo;
PMDL pMdlNccmdFifo = IoAllocateMdl(&NccmdFifo, sizeof(NccmdFifo), false, false, NULL);
MmBuildMdlForNonPagedPool(pMdlNccmdFifo);
void* pNccmdFifoUserSpace = (CNccmdFifo*)MmMapLockedPages(pMdlNccmdFifo, UserMode);
現在 pNccmdFifoUserSpace 即為用戶在用戶模式中也能訪問的地址 從這以后 用戶可以直接在用戶模式中向該地址寫入數據 也可以直接從內核模式讀取該緩沖區(qū)中的數據
3.效率比較
作者所從事的工作是開發(fā)開放式數控系統(tǒng) 為了對比如上兩種方案的效率 在公司一款已經成熟的產品上做測試 結果表明 使用內存直接映射的方式 在效率上有較大的優(yōu)勢 表 1 是一些測試數據
表 1 所測試的文件約 500 行 從數據可以看出 使用緩沖區(qū)映射方式 所花費的時間只有使用普通方式 用 DeviceIOControl 交換 的 78.85% 效率明顯提高
表 2 是更多的實驗數據
從表 2 能看出 內存映射方式有較大優(yōu)勢
4.優(yōu)缺點和一些問題
因為對讀寫信息存儲時為了避免因為線程的調度而產生問題 需要讓記錄在一個指令中完成 這意味著從理論上講 該映射空間不能太大不能大于 2^32 4G 實際上這是遠遠夠用的
內存映射要求使用物理內存進行映射 不能將這些內存用作交換區(qū) 減少了交換區(qū)內存的使用量實現比較復雜 要求對 Windows 操作系統(tǒng)有較深的了解
因為對緩沖區(qū)的訪問是在不同的線程中進行的 一個讀 另一個可能會同時寫 需要處理訪問沖突的情況
在對比兩種數據交換方式的效率時 筆者發(fā)現 如果遇到一些的加工文件 它們在粗插補階段需要花費較多的時間的話整體的效率差別就會比較小 這是本方案在實際應用時需要考慮到的一點
本文由 伯特利技術文章 整理發(fā)表,文章來自網絡僅參考學習,本站不承擔任何法律責任。
伯特利數控一直以盡心、盡力、盡意的態(tài)度把握每一臺 加工中心、鉆攻中心的質量
相關文章可查閱本站:技術文章 或本文下方 標簽 分類
相關產品可查閱本站:產品中心