簡介
對於高性能的嵌入式應用程序所需要的對時間要求嚴格的響應來說
實時性能是不可缺少的
例如
電信交換設備
工業自動化和控制系統
醫學監視設備和空間導航和制導系統
這樣的應用程序必須在指定的時間參數以內實時地傳遞它們的響應
實時性能是什麼?對於 Microsoft Windows CE
NET OS
以下列表定義了實時性能
; 有關高優先級線程調度的擔保的上限 — 只針對所有已調度線程中的最高優先級線程
; 調度高優先級中斷服務例程 (ISR) 過程中有關延遲的擔保上限
搶占機制在一個短暫
有限的時間內關閉後內核有很少的空間
; 對計劃程序和它如何調度線程進行細致的控制
重要的是應當區分實時系統和實時 OS (RTOS)
實時系統由滿足系統要求所需的所有元素(硬件
OS 和應用程序)組成
RTOS 只是完整的實時系統的一個元素
它必須提供足夠的功能
才能使全部實時系統能夠滿足它的要求
盡管以前的 Windows CE 版本提供了某些 RTOS 功能
但自從 Windows CE
以後很多重要的內核更改極大地增強了實時性能
Windows CE
NET 內核包含了與 Windows CE
相同的實時增強功能
除此之外還有某些額外的功能
本文描述了作為 Windows CE
NET 及其以前版本的組成部分的以下更改
Windows CE
NET
對 x
平台添加了通過 OEM 定義的變量指定頁面池大小的功能
Windows CE
; 增加了線程優先級級別的數目(從
到
)
; 更多地控制時間和調度
應用程序可以控制提供給每個線程的時間
並操縱對它們有好處的計劃程序
現在
對於與休眠和等待相關的應用程序編程接口 (API)
計時器精確到一毫秒
; 處理優先級倒置的方法得到改進
; 全面支持嵌套中斷
; ISR 和中斷服務線程 (IST) 滯後時間得到減少
; 更細粒度的內存管理控制
此外
本文描述了用來測試內核實時性能的工具
並提供了在三種不同 CPU 上的實時性能測試結果
返回頁首
對內核的更改 內核是 Windows CE OS 的內部核心
它負責調度和同步線程
處理異常和中斷
加載應用程序和管理虛擬內存
在 Windows CE
中
為了提高性能和減少滯後時間
內核經歷了以下幾個更改
; 將所有內核數據結構移動到物理內存
從而當在內核中執行非搶占代碼時極大地避免了轉換後備緩沖區 (TLB) 損失
; 所有非搶占
但可中斷的內核部分(稱為 KCALL)被分割成更小的非搶占節
由於增加了節數
這就引入了某些復雜性
但現在搶占機制能夠在更短的時間內關閉
這一節描述為了增強 Windows CE
的實時性能對內核的進一步更改
更多優先級級別 內核的計劃程序首先使用較高的優先級級別運行某個線程
然後使用相同的優先級以循環方式運行多個線程
為線程指派優先級級別是管理執行速度的一種方式
Windows CE
將可用於線程的優先級級別數從
增加到
是最高的優先級
是最低的優先級
Windows CE 的前一版本的優先級級別
到
對應於 Windows CE
中級別
到
更多的優先級級別允許開發人員更靈活地控制嵌入式系統的調度
並防止由於限制優先級級別數使隨機應用程序降低系統性能
要指派這些新的優先級
Windows CE
引入了兩個新函數
CeSetThreadPriority 和 CeGetThreadPriority
新函數與 Windows CE
中的 SetThreadPriority 和 GetThreadPriority 函數看起來完全相同
不過新函數接受的數字范圍是
到
更多地控制時間和調度 Windows CE
已經改進了計時器性能
計時器和休眠函數調用的精度達到了一毫秒
並且應用程序可以為每個線程設置時間片
計時器(或系統時鐘)是一種速率
由 OS 以此速率生成計時器中斷並對其提供服務
以前
計時器也是線程時間片
是線程沒有被搶占的情況下可以在系統中運行的最長時間
在 Windows CE
中
計時器不再直接與線程時間片相關
以前
OEM 將計時器和時間片作為 OEM 適配層 (OAL) 中的常量設置為大約
毫秒
計時器觸發時
如果一個線程已做好准備
內核會調度此新的線程
在 Windows CE
中
計時器總是設置為一毫秒
並且可以對每個線程設置時間片
通過將計時器從 OEM 定義的數字更改為一毫秒
可以讓應用程序執行 Sleep(
) 函數
並預計得到大約一毫秒的精度
當然
這取決於線程的優先級
其他線程的優先級以及是否正在運行 ISR
以前
Sleep(
) 經過一個系統周期後返回
這意味著如果計時器被設置為
毫秒
則 Sleep(
) 實際上是 Sleep(
)
計時器中斷 現在
內核有幾個新的變量
開發人員可以使用它們確定系統時鐘是否需要重新調度
通過在適當的時候返回 SYSINTR_NOP 標志而不是 SYSINTR_RESCHED 標志
完整實現的系統時鐘 ISR 可以防止內核被重新調度
Nk
lib 導出在 Timer ISR 中使用的以下變量
; dwPreempt 是線程被搶占之前的毫秒數
; dwSleepMin 是第一次超時(如果有)到期之前的毫秒數
需要重新調度
; ticksleft 是已經過去
但尚未被計劃程序的休眠隊列處理的系統時鐘數
因而
非零值將導致重新調度
在 Timer ISR 中
其他邏輯將優化計劃程序
並防止內核執行不必要的工作
如以下代碼示例所示
if (ticksleft || (dwSleepMin && (DiffMSec >= dwSleepMin)) || (dwPreempt &&
(DiffMSec >= dwPreempt))) return SYSINTR_RESCHED; return SYSINTR_NOP;
OEMIdle 函數 OEM 實現 OEMIdle 函數
在沒有要調度的線程時內核將調用該函數
在以前的版本中
計時器時鐘會強制 OS 脫離空閒狀態
並返回到內核以確定是否線程已做好調度准備
如果沒有線程做好准備
內核再次調用 OEMIdle
該操作將導致內核每隔
毫秒(或 OEM 指定的其他時間片長度)被激活一次
以確定是否仍然沒有要調度的線程
在電池供電的設備上
這樣的操作會耗盡寶貴的電池電量
在 Windows CE
中
為了在時鐘頻率較高的情況下減少耗電量
OEMIdle 函數可以讓 CPU 進入待機模式一毫秒以上
OEM 通過使用 dwSleepMin 和 DiffMSec 變量來編程設置系統時鐘計時器
以便在第一個可用的超時後喚醒
DiffMSec 是自從通過 TimerCallBack 函數檢索到最後一次間隔時間以來的當前毫秒值
硬件計時器的最大超時值可能小於 MAX_DWORD 毫秒值
所以可以編程設置計時器的最大等待時間
在所有情況下
系統從空閒狀態返回時
OEMIdle 函數必須使用已經過去的實際毫秒數更新 CurMSec 和 DiffMSec
CurMSec 是間隔時間的當前值 £ 即自從啟動以來的毫秒數
線程時間片 在 Windows CE
中
線程時間片很靈活
足以使應用程序能夠逐個線程地設置時間片
這就讓開發人員可以改編計劃程序
以滿足應用程序的當前需要
為了調整時間片
已經添加了兩個新函數
CeGetThreadQuantum 和 CeSetThreadQuantum
這項更改使應用程序能夠基於線程完成任務所需要的時間量來設置線程的時間片
通過將任何線程的線程時間片設置為零
循環調度算法可以變為
運行到完成
算法
只有較高優先級的線程或硬件中斷才能先於設置為運行到完成的線程執行
默認時間片是
毫秒
但在 OEM 初始化階段
OEM 可以通過將內核變量 dwDefaultThreadQuantum 設置為大於零的任何值
從而重寫系統的默認值
更改處理優先級倒置的方法 為了有助於縮短響應時間
Windows CE
更改了它的優先級倒置方法
當低優先級線程擁有一個較高優先級線程所需要的內核對象時
就會發生優先級倒置
Windows CE 使用優先級繼承來處理優先級倒置
這時
被阻塞的
擁有較高優先級線程所需要的內核對象的線程將繼承更高的優先級
優先級倒置使較低優先級線程能夠運行
並釋放資源供較高優先級的線程使用
以前
內核處理整個倒置鏈
從 Windows CE
開始
內核保證只處理優先級倒置到一個級別的深度
優先級倒置有兩個基本示例
第一個是簡單的情況
這種情況下
對優先級倒置的處理從 Windows CE
到 Windows CE
沒有變化
例如
在有三個處於運行狀態的線程時
可以看見這種情況
線程 A 的優先級是
線程 B 和 C 優先級較低
如果線程 A 正在運行
並且因為線程 B 擁有線程 A 需要的內核對象而使 A 被阻塞
那麼線程 B 的優先級會提高到 A 的優先級級別
以便允許線程 B 運行
然後
如果因為線程 C 擁有線程 B 需要的內核對象而使線程 B 被阻塞
則線程 C 的優先級會提高到 A 的優先級級別
以便允許線程 C 也能運行
第二個並且是更有趣的情況是
線程 A 可以以比 B 和 C 更高的優先級運行
線程 B 擁有 A 需要的內核對象
線程 B 被阻塞
等待 C 釋放它需要的內核對象
而 C 正在運行
在 Windows CE
中
當 A 運行然後因為 B 而被阻塞時
B 和 C 的優先級都會提高到 A 的優先級
以便使它們能夠運行
在 Windows CE
中
當 A 因為 B 而被阻塞時
只有線程 B 的優先級被提高
通過減少復雜性和更改算法
極大地減少和限制了 Windows CE 中最大的 KCALL
中斷處理和嵌套中斷
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25643.html