明天的嵌入式系統編程語言仍然是C語言嗎?
摘要:本文介紹了嵌入式系統編程語言的發展,并將C語言和時下其他較為流行的編程語言比較,分析了各自的優缺點和未來發展趨勢。
本文引用地址:http://www.104case.com/article/201606/293251.htm您在下一項目編程時所使用的最佳語言是什么? 如果您是一名嵌入式系統設計人員,可能認為這一問題實在可笑。您會使用C語言,如果希望加強管理,則會使用C衍生的C++。可能會有一些關鍵代碼片段是以匯編語言編寫的,但是,據Barr集團最近的一項研究表明,目前95%的嵌入式系統代碼是采用C或者C++編寫的。
然而,世界是在變化的。新的程序員、新挑戰以及新體系結構讓C松開了在嵌入式軟件上的“抓手”。據最近的一項研究表明,嵌入式計算語言發展最快的是Python,當然還有很多其他參與競爭的語言,只是這些語言仍然占少數。但是逐漸地,一直堅持使用C/C++的程序員像20年前匯編語言專家那樣開始冒險——采用更快、更緊湊和更可靠的程序。 圖1提出了新語言能夠提高嵌入式計算機領域的效能。
C語言在嵌入式領域中的地位受到沖擊
嵌入式算法變革的一個主要推動力量是其他工作環境的程序員進入了嵌入式領域。這方面最明顯的是剛畢業的學生進入職場。以前,剛畢業的學生在C課程中學會了編程,會用C或者C++完成他們的大部分項目。而現在,已經不再如此了。Intel軟件工程經理David Stewart注意到,“現在,大部分計算機科學課程使用Python作為他們的入門語言。”計算機科學專業畢業的學生很有可能在Python、Ruby以及幾種腳本語言上有豐富的經驗,但是他們可能從未認真地使用過C語言。同時,其他影響也越來越多。使用Android作為平臺進行相關的或者用戶友好的嵌入式設計,為Android的自然語言——Java,帶來了機會。在這一復雜景象的另一端,機器人、無人機或者相似的小項目業余愛好開發人員通常都有Arduino或者Raspberry-Pi背景。他們的經驗會體現在非常緊湊和簡單的程序發生器或者B#等小型語言環境里。
這一現象對物聯網(IoT)的廣泛研究也產生了影響,網絡開發人員也參與到討論中。他們認為,如果嵌入式系統的外部接口是RESTful Web,編程語言應該是JavaScript或者其服務器側相關的Node.js。熱衷于使用C語言進行開發的人員應該觀察一下node.js——貝寶和沃爾瑪等公司在企業規模的開發中大量使用了這一可擴展平臺,據跟蹤調查網站modulecounts.com,在任何編程語言中,該平臺的輔助支持系統增長是最快的。
選擇Node.js的動機部分是源自文化,但是也有體系結構方面的因素。IoT會在客戶側、互聯網以及服務器側之間分配其嵌入式系統任務。其中,客戶側連接實際環境,通常要求盡可能少地采用硬件。客戶側很自然地采用硬件專用庫支持的Web應用程序,而服務器側則是服務器應用程序。這樣,對于Web程序員,在IoT系統編程中很顯然會使用JavaScript和Node.js。
日益復雜的嵌入式算法是變革的另一推動力量。簡單的控制環路被卡爾曼濾波器、神經網絡以及基于模型的控制功能所替代,高性能計算語言——Python,開放計算語言(例如OpenCL?)以及MATLAB等基于模型的環境逐漸發展起來。
強烈的動機
那么這些新人們為什么不靜下心來學習C語言呢? Stewart說:“真正的原因在于開發人員的效能。”反對C語言的人一直認為這種語言編寫慢,容易出錯,會帶來意想不到的硬件相關問題,并且除了最初的程序員,其他人很難讀懂它。這些因素會對提高設計效能產生不利影響。而很多最近出現的語言逐步轉向快速學習和高效的代碼重用。雖然目前幾乎所有語言都受益于C語言高度簡潔的語法,但現在的重點已經轉回可讀性,而不是最少字符數。不但在現代語言中鼓勵實現協調一致的文檔,而且結構化約定也通常會這樣定義文檔。C程序員一直把這類文檔看成是自由表述的例子,因為作者自己不會牽連其中。例如,這些約定使得實用工具程序能夠從Python組件的結構化注釋中生成用戶手冊。
現代語言還采用了高級數據結構,可以在C++環境中建立任何對象,并重用它。基于指針,Python還提供自然List和Dictionary數據類型。而Ruby等其他語言,基本上是面向對象的,支持結構和重用,這使其可以融入到程序員的習慣中。
影響了現代語言是否易于重用的另外兩個重要因素是動態輸入和模塊化。動態輸入是一個很有爭議的因素。當程序員在使用變量時,解釋程序確定程序員傳送給表達式的數值的當前數據類型——幾乎所有這些服務器側語言都是解釋性的,而不是編譯的。然后,解釋程序會選擇相應的操作,評估含有該數據類型的表達式。這樣,程序員不用太過擔心他要調用的函數需要的是整數變量還是實數變量。但是,嵌入式程序和代碼可靠性專家很快指出,動態輸入在運行時實際上效率不高。另一個因素是部分程序員對模塊化的偏見。有時候會有人說,Python編程實際上不是編程,而是腳本,是把別人用C語言編寫的函數調用或串起來。
可讀性、協調一致的文檔、動態輸入以及函數大量的重用等,催化了開源領域中輔助支持系統的爆發。程序員本能地會在巨大的開源庫中找到他們能夠使用的函數,例如,npm (用于Node.js)、PyPI (用于Python)或者Rubygems.org (用于Ruby)。如果他們不用修改組件或者編寫新的組件,他們會回到庫中工作。結果,庫會越來越大(npm目前大概有25萬個組件)。這些大規模的輔助支持系統也相應地大幅度提高了程序員的效能。
嵌入式的新編程語言的不足之處及解決方法
這些編程語言盡管有這么多的優點,但也有缺點。要想在嵌入式計算領域占據一席之地還有很多不足。
大部分這些語言最明顯的問題是,它們是解釋性的,而不是編譯的。這意味著它們需要可觀的運行時程序包,包括解釋程序本身、工作存儲、動態輸入開銷和運行時庫等,都要適配到嵌入式系統中。基本上,所有這些會非常緊湊,某些Java虛擬機可以裝入到幾十K字節中,但是Node.js、Python以及來自服務器側相似的語言需要自己的空間。一個兼容性還可以的Python虛擬機在加入程序員自己的代碼之前可能已經占用了幾兆字節。
在性能問題方面,解釋程序讀取每一行代碼(源程序或者預處理過的中間級代碼)需要解析它、進行運行時檢查以及調用執行所需操作的例程。在C語言中,這會導致一行代碼有很多操作,編譯成很多機器語言指令。執行時間和能耗的成本都會增加。
在運行時效率方面,可以使用即時(JiT)編譯器進行改進。一個JiT編譯器可以與解釋程序并行工作,為循環中的代碼生成編譯后的機器指令,因此,后續的代碼能夠更快地執行。Stewart說:“JiT技術非常有趣,PyPy JiT編譯器把Python執行速度提高了兩倍。”對于效率方面,還研究了其他方法。例如,如果函數是無阻塞的,或者使用了信令機制,有很多函數調用的程序即使是在采用循環展開等方法來建立更多的線程之前,也可以含有很多線程。因此,可以在一個組件上應用很多多線程內核——這是高性能計算已經研究應用的方向。更進一步,Ruby語言本身支持多線程,因此,即使底層操作系統不支持線程,它也能夠產生線程代碼。某些團隊則尋求在硬件加速器中實現庫或者組件,例如,圖形處理單元(GPU)、Xeon Phi和FPGA。實際上,解釋程序本身就會有適合加速的任務。
服務器側語言遇到的其他困難是缺少處理實際環境的結構。在服務器環境中,除了網絡和存儲,沒有實時限制,也沒有I/O。可以通過幾種方式來解決這一問題。
最簡單的是,Android環境以硬件幾乎無關的抽象方式包封Java代碼:具有圖形、觸摸屏、音頻、視頻、多個網絡以及物理傳感器的虛擬機。對于更強調物理I/O,甚至能夠在微控制器上運行的輕型平臺,提供嵌入式Java。
Python等語言需要不同的方法。由于CPython解釋程序運行在Linux上,因此,原理上能夠運行在有足夠速度和物理存儲器的任何嵌入式Linux系統中。在這方面已經有了工作基礎,通過減小裝入時間開銷,為物理I/O訪問提供功能,使用硬件加速器,進一步適應CPython,運行時系統適應實時約束。最新的一個實例是STM32微控制器的裸金屬Micro Python環境。雖然這看起來幾乎不可能,但是已經在Node.js下面的JavaScript引擎上有了類似的工作。
安全呈現出更多的問題。很多安全和可靠性標準不鼓勵甚至禁止使用未經正式認證或者全面測試的開源代碼。這些限制使得不可能重用組件,或者重用組件過于復雜,對效能的提高不大。同樣等級的詳細檢查也延伸到虛擬機等開源環境中。在可靠和安全大環境下,CPython等開源平臺很容易受到攻擊。
未來的編程語言發展方向
最后,考慮到有眾多的推動力量促使新語言進入嵌入式世界中,可以預見到會有多語系統,這種系統含有的組件來自多種源語言,每一種選擇要使用的關鍵庫,或者方便某類開發人員使用。當然,您可以在不同的CPU內核上放置幾種虛擬機,在一個內核管理程序下相統一,然后,通過函數調用,為任務間消息的傳送提供約定。但是,這樣的系統最終會非常大。
另一種可能是一組語言相關解釋程序,為JiT編譯器生成公共中間代碼(圖2)。當然,還能列出其他問題,例如,不同的任務間具有不同的通信模型、存儲器模型和調試環境,但這些問題總是能夠解決的。
小結
如果這些最終會到來,那么,一名經驗豐富的嵌入式程序員該如何應對? 您可以從Web編程、服務器甚至業余愛好者使用的開發環境中研究這些語言。您可以在下一項目中,嘗試在C++和解析語言中開發組件。這需要時間學習,但是獨立并行開發是值得的。
本文來源于中國科技期刊《電子產品世界》2016年第6期第18頁,歡迎您寫論文時引用,并注明出處。
評論