1. 程式人生 > >要認識嵌入式Linux,看這一篇就夠了

要認識嵌入式Linux,看這一篇就夠了

對於剛接觸嵌入式Linux,還沒有整明白什麼是“嵌入式”的朋友們,下面的一篇文章關於什麼是嵌入式Linux,內容總結的非常透徹,分享給大家。


嵌入式Linux跟桌面Linux一樣,是一個作業系統。從微控制器走過來的童鞋往往習慣於直接控制暫存器,事必躬親,從零開始實現想要的功能。而在嵌入式Linux的世界裡,我們首先要拋棄這個思想,應把它作為最後沒辦法的辦法。

就像我們想要在windows系統中編寫一個程式,首先想到的不是操作CPU晶片的暫存器,而是學習Windows API一樣。我們在嵌入式linux程式設計時,首先想到的應該是使用現成的驅動或軟體或Linux API。沒有的話看看能不能修改一下現成的資源為己所用。還是不行的話才考慮自己從頭開始寫。

嵌入式Linux大廈是由很多層組成的,當我們想找一個人時,首先要明確他在那一層樓。同樣的,我們遇到問題時,首先要知道是哪個方面的問題,然後才有可能知道到哪裡尋找答案。下面我們把這座大廈進行一下拆解。

我們平時使用Linux系統的話,最常用的工具就是Shell(或者用windows中常見的說法:命令列),初學者接觸Linux的第一個東西往往也是shell。也許你已經知道,把shell命令組合起來寫成一個檔案,亦即shell程式設計,也是一門大學問,它能做的事很多很強大,但僅限於對Linux系統的操作。

我們一定不會用shell命令去編寫一個顯示屏程式,或者一個GPS導航程式。而且作為嵌入式Linux開發來說,shell不可能作為最終產品工作的平臺,因為我們不能要求使用者在螢幕中輸入程式碼來實現功能。因此我認為對

嵌入式開發來說,shell命令無需深究,掌握基本操作就夠了。

shell基本操作主要包括:獲取命令幫助,到達指定目錄,檢視目錄內容,許可權修改,檔案的複製貼上等基本操作,檔案搜尋,檔案內容檢視和編輯,系統關機重啟……(這些只是最基本的,後面再慢慢學別的命令,比如學習程序程式設計時,再學習程序相關的命令;學習C語言程式設計時,再學各種編譯和除錯命令也不遲)

學習嵌入式Linux,我們的最終目的是製作一套嵌入式系統來實現功能。往往需要用C/C++或Python等其他語言來編寫程式,但是程式設計之前我們要先明確一些基本概念。

最基本的,當我們編寫程式時,首先要明確嵌入式Linux分為使用者空間

核心空間。使用者空間是應用程式執行的空間,核心空間就是作業系統和驅動程式執行的空間。這是從軟體的角度來說的,對應於ARM晶片來說,就是晶片的不同“工作模式”。這兩個空間是通過“地理隔離”實現互相完全獨立的,它們各自的程式使用不同的記憶體地址區間,各自使用自己的標頭檔案(有些標頭檔案在兩個空間內甚至是重名的,要注意區分)、各自呼叫屬於自己空間的函式(哪怕實現的功能相同,比如printf()和printk()),而且不能互相直接訪問(用指標也不行)。(意味著學習這兩部分的程式設計時要學習兩套獨立的知識體系)

核心空間相關的東西有:Linux核心原始碼、核心編譯和配置、核心移植、檔案系統、Busybox、裝置驅動程式編寫、中斷程式設計……

使用者空間相關的東西有:Shell、應用程式編譯和除錯、程序、執行緒、檔案IO程式設計、網路通訊相關、Qt圖形介面程式設計……

如果你僅僅要開發應用程式,那你就可以遠離核心空間那些東西了。對你來說,驅動程式、底層硬體、作業系統的工作方式等都是透明的,你寫的程式在別的晶片上也能跑得很好。

但如果你想要開發驅動程式,或者定製自己的作業系統,或者你想向一片“全裸”晶片中寫入作業系統,並使它正常執行起來,那就得學習核心空間的知識了。

如果你想讓“全裸”晶片執行起來,還會遇到一塊比核心更底層的東西,Bootloader。它是在核心啟動前執行的一段程式,用來初始化硬體、建立記憶體空間對映等,與晶片的品牌、型號極其相關。我們通常對一些現成的Bootloader進行修改來滿足需求,常見的Bootloader有U-Boot、Vivi等。

再多說一句,如果想從零開始做一個嵌入式裝置,還有更底層的問題需要解決和學習:電路設計、PCB佈線等。

因此,我們看到的嵌入式Linux書籍就可以粗略分成兩個方向:一類講嵌入式Linux應用程式程式設計,另一類講如何搭建一個完整的嵌入式Linux平臺。分別對應的就是使用者空間和核心空間的事情。

雖然使用者空間和核心空間是獨立的,但就像Windows提供了API,允許我們對系統進行操作一樣,使用者空間的程式也可以通過系統呼叫來訪問核心(就是一些的C語言函式)。但由於系統呼叫非常基礎,所以有時使用起來很麻煩。比如說一個簡單的給變數分配記憶體空間的操作,就需要動用多個系統呼叫。

Linux定義一些庫函式(API)來將系統呼叫組合成某些常用的功能,以方便我們程式設計(同樣是C語言函式)。因此,我們在讀別人的程式時,就要區分其中的函式是系統呼叫,還是庫函式,還是C/C++標準庫中的函式,還是使用者自己定義的函式。如果是前三者,就可以到各個地方搜尋相應的資料,這樣學習起來就快很多。

那麼shell程式和我們用C/C++編寫的程式有什麼區別呢?事實上,我們在shell中寫的每一個命令,都對應了一個程式,在程式內部就是通過呼叫各種API來實現相應功能的。因此用shell能實現的功能,理論上都能用C語言實現。

作為嵌入式Linux開發初學者,簡單熟悉了shell以後,就可以開始進行一些C語言程式設計的嘗試了。

我們最早接觸程式設計一般都是在大學的程式設計課上,而且往往用的是Visual C++ 6.0。竊以為這是讓我對程式設計原理長期困惑不解的罪魁禍首!啥是環境變數?為啥要設定include路徑,lib路徑?為啥一點編譯按鈕就會出來那麼多字尾名不同的檔案?這些很基礎很重要的問題都被VC6.0這個外殼掩蓋了。但哪怕你在Linux中使用gcc編譯一個最簡單程式,一定就會像我一樣馬上明白把一個.c的原始檔變成一個可執行檔案,中間究竟發生了什麼事情。如果你再用gdb除錯一個程式,就會明白得更多一點。

關於C/C++程式設計的基本工具,我們需要學習的有:vim等程式碼編輯器、diff等檔案比較的shell命令、gcc等編譯器、gdb等除錯工具、交叉編譯等。這裡需要特別提到一個重要工具(網站):github,根據百度的解釋,它是一個“分散式的版本控制系統”,初學者還用不到版本控制,那就可以單純把它當成一個開放的原始碼庫。這個網站裡有大量優秀的原始碼供學習和使用。

學習了基本的程式設計方法,我們就該接觸Linux的API等內容了。畢竟,我們的嵌入式系統要與裝置進行互動,只用C/C++標準庫是不夠的。在此之前,需要建立一個Linux的重要概念:一切皆檔案。甚至硬體裝置對Linux系統來說,也是檔案。這樣對裝置的操作就等同於對檔案進行讀、寫,或讀寫以外的操作。這部分內容在各種書籍資料中通常以“檔案IO程式設計”命名,作為一個章節來寫。我覺得這是應當第一個來學的東西,因為看到自己能隨意操控檔案和外設是一件讓人很振奮的事情!成就感是繼續學習的一大動力!

另外一個重要內容是,理解程序和執行緒。通過學習這個部分,能管中窺豹地大致領略到Linux系統如何進行排程,你的程式是怎麼在Linux中執行的。這是作業系統原理的內容,但作為非軟體專業出身的人,沒辦法,只能自學了。

其他應用程式程式設計如網路程式設計、Qt圖形程式設計等就不一一說明了。

驅動程式可能是我們將來接觸核心空間遇到的第一個內容。不過暫時還沒什麼特別想說的。核心空間距離初學者還是有點遠的……以後再來學這部分內容。

轉自網路:微控制器愛好者