實時性迷思(2)——“時間片輪轉”的沙子

【說在前面的話】


在前面文章中,我們介紹了實時性的基本模型、並分析了實時性窗口內不同位置的時間對整個系統的價值,得出了一個結論——實時性窗口中越靠前的時間對系統中的其它任務越有價值;當一個有實時性要求的事件發生時,如果“不顧其它任務、自私自利”——只“單純”考慮以越快越好的速度儘快完成當前的事件處理,會給整個系統的實時性帶來毀滅性的結果——事實上,當所有任務都採取這一策略時,系統中沒有任何一個任務的實時性是可以確定得到保證的。關於以上的結論,如果你還沒有閱讀過前一篇文章、或是對上述結論仍然抱有疑惑,可以單擊《實時性迷思(1)——”快是優點麼“?》進行閱讀。

其實,在上一篇文章的留言區,很多朋友除了熱烈討論以外,還針對原文中的例子提出了“將任務拆分成小塊進行時間片輪轉”的解決方案,認爲這樣就可以解決文中提出的實時性矛盾。究竟時間片輪轉能不能確保實時性?相信在閱讀完本文以後,你一定可以做出自己的判斷。也歡迎將你的想法在評論區留言。

【正文】


在討論系統實時性的問題時,我們常常會跳過一個非常重要的步驟——證明當前系統在理論上是否有解——而直接進入討論“如何確保具體任務實時性的方法”中來。這就好比看到一個渾濁的池塘,首先不調查是否可能有魚,而直接開始着手釣魚一樣——也許大概率有魚而你又運氣不錯,皆大歡喜;又或者根本污染嚴重魚早就缺氧死光了,你卻以爲是自己運氣不好,或者是技術不佳,悻悻而歸——這實在是太可笑了。

那麼,讓我們明確一下這裏首先需要面對和解決的問題吧:

  • 在一個多任務系統中,有一部分(或者全部)任務擁有實時性要求;

  • 對於這些有實時性要求的任務來說任何一個任務在任何一種情形、哪怕是極小的概率下、存在無法滿足實時性的可能整個系統就判定爲無法滿足實時性要求

  • 由於上述判定條件過於苛刻,所以工程實踐中,我們一般退而求其次,轉而尋找一定無法滿足實時性的情況,即:

    • 如果在極其理想的條件下,可以通過數學方法證明這些任務的實時性一定無法得到滿足,則需要調整硬件環境,或者對任務進行重新規劃、降低實時性要求

    • 如果在極其理想的條件下,證明系統的實時性可以得到保證,則我們只能假設可能存在一種方式讓當前系統的實時性得到保證——此時我們可以進入下一階段的討論——也就是如何設計系統、將理論上證明可能做的事情變成既成事實。

如果上面的描述讓你摸不着北,其實也可以換一種簡單的說法:

  • 如果數學上都已經能證明實時性得不到保證了,咱們就別折騰了

  • 如果數學上證明有希望,咱們再繼續討論實施方法——究竟最終能不能做到——事在人爲,結果另說

那麼這是個怎樣的數學模型呢?請大家翻出小學課本,學過除法和百分數的那個年級就行:

先說結論:

  • 我們就是要計算每個實時性任務可能佔用的最大CPU資源,並用百分比表示

  • 計算所有實時性任務所佔用CPU資源的總和(將百分比累加起來)

    • 如果超過100%,則整個實時性必然得不到保證

    • 如果沒有超過100%,則可以判定在理想狀況下,系統的實時性是有可能得到保證的

  • 實踐中,距離100%越遠,則可能性越大。如果卡着100%或者99%則相當危險,甚至可以穩妥的判定爲不滿足。

怎麼樣?道理是不是很簡單?那麼具體怎麼計算呢?

  • 觀察此前介紹的實時性模型可以發現,無論是“實時性窗口”,還是“處理事件所需的時間” 都是表示時間長短的量

  • 其中,“實時性窗口” 是根據具體應用需要,由自於客觀物理世界的時間要求所決定的,翻譯成人話就是:“如果不在某一時間內完成任務,就會受到牛頓的毒打!”

  • 實時性窗口還隱含了另外一個重要的假設,即,最差情況下,這個事件可能會以實時性窗口所代表的時間間(Interval, Period)隔週期性的發生——正可謂一波剛平一波又起(紳士們,我就不配圖了)。

  • 事件處理所需時間”,故名思意,就是CPU執行事件處理程序所需的時間。這裏其實涉及到另外一個非常關鍵的問題——確定性(Deterministic):說白了,就是“最起碼”要你能夠拍胸脯打包票——執行這個任務所花的時間存在一個最大值(上界),並且這個上界是穩定可靠的——這只是確定性的最低標準;有時候某些應用對確定性的要求高的乍舌,比如,系統會強硬的規定:執行時間只允許在某一個非常小的範圍內微弱的波動,做不到就直接判定爲不滿足“確定性”要求(例如很多車載系統中所使用的ECU就是這樣),從而整個系統的實時性也成了空中樓閣。


爲什麼確定性如此重要呢?你想一想,如果一個滿口跑火車的人跟你做了個保證:“明天股市一定暴漲,你趕快滿倉”,你真敢根據這樣的信息來做決策麼?

在實時性系統中,任務執行時間是一個非常關鍵的指標,它直接關係到任務實際佔用系統資源的百分比,如果這個數據不是“確定的”,我們又如何“確定的說”:系統一定能滿足實時性要求呢?

這裏有一個很重要的結論,大家可以拿小本本記下來:

實時性不一定要求系統跑的越快越好,但一定要求系統是具有高度確定性的。

這就是爲什麼,低頻率低性能的Cortex-M和高頻率高性能的Cortex-R都能用於實時系統;而高頻率高性能的Cortex-A卻無法滿足“硬實時”的要求(因爲Cortex-A使用MMU,理論上由實現虛擬地址空間導致的存儲器訪問時間是不確定的,因此建立在MMU基礎上的任務執行就是無法滿足確定性要求的)。


  • 值得強調的是,假設事件處理程序的代碼是一樣的,那麼很容易理解:當CPU頻率升高的時候(CPU單位時間內可以執行的指令增加的時候),事件處理所需的時間就越短

基於以上事實,我們可以設想一個嚴格的理想狀況:

  • 某個事件已“實時性窗口”所表示的時間間隔(Tw)週期性的發生

  • 在這個週期內,要消耗時間(Th)來處理這個事件

則當前實時性任務所消耗的CPU資源百分比爲:

這裏的

就是“事件n”的CPU資源佔用。

【反覆橫跳的代價】


  不知道你還記不記得本文一開始我們試圖討論的那個問題:即,時間片輪轉是否對實時性的保證有意義?經過前面的理論準備,我們現在就有了明確而清晰回答這個問題所需的所有條件:

已知的事實如下:

  • CPU頻率不變的情況下,CPU的可用資源是固定的

  • 實現時間片輪轉的方法有多種多樣:比如,純粹的合作式輪轉(諸如裸機中的switch狀態機,或者是基於函數指針的合作式調度器);又或是操作系統下,擁有相同優先級任務間所使用的可搶佔式時間片輪詢,即Round-roubin模式(詳情請參考《【解惑】到底是“時間片”還是“分時輪詢”?》)。

  • 無論採用哪種時間片輪轉方式,任務的切換都是有代價的。比如,裸機中,進出函數所需的跳轉代價、局部變量在棧中重建的代價(詳情參考《漫談C變量——夏蟲不可語冰》);操作系統中任務調度的代價等等。

  • 在存量是固定不變的前提下,任務切換越頻繁,則切換所消耗的CPU時間就越多,因此實際用於實時性任務處理的CPU資源就越少

結論:頻繁任務切換對系統實時性是有害的;由於頻繁時間片輪轉會導致大量不必要的任務切換,因此對實時性總體上來說是有害的

推論:任務切換對實時性系統來說是必要的,但一定要越少越好——拒絕花拳繡腿的反覆橫跳,只做真正有必要的任務切換。

很不客氣的說,很多人一直把併發、甚至(僅僅只是併發其中一種實現方式的)“時間片輪轉”當成“確保實時性的沙子”——不僅一頭扎進去而不自知,還對周圍的人傳授自己的成功經驗——實在是讓人扼腕嘆息。

【結語】


本文的結論實際上從本質上傳達了一個信息:無論是裸機還是操作系統環境,多任務都是可以實現的——這是併發技術的本質所決定的。時間片輪轉只是裸機和操作系統環境下常見的、“無腦”實現併發的一種方式——或者說,時間片輪轉的作用只是實現併發而已,它不僅與實時性的保證無關,甚至是有害的。

  

那麼,假設,在通過數學方式證明了:“可能存在一種解來滿足系統的實時性要求”,那麼具體有什麼方法能夠實現它呢?欲知詳情,請聽下回分解。


1.嵌入式工程師心目中的微內核架構~

2.do{}while(0)只執行一次無意義?你可能真的沒理解!

3.BUG 終結者,現場抓獲!|顛覆認知

4.MATLAB 只是冰山一角!海外資深程序員聊被卡脖子……

5.“STM32CubeMonitor” 拍了拍你

6.如何把C++的源代碼改寫成C代碼?

免責聲明:本文系網絡轉載,版權歸原作者所有。如涉及作品版權問題,請與我們聯繫,我們將根據您提供的版權證明材料確認版權並支付稿酬或者刪除內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章