一、前言
為什么Linux內(nèi)核代碼60%都是驅動? 如果每支持新的設備就加入驅動,內(nèi)核會不會變得越來越臃腫?
要先搞明白這個問題,我們首先要明確(區(qū)分)兩個概念:內(nèi)核代碼和內(nèi)核,這是兩個完全不一樣的概念,我們通過 git clone 命令從網(wǎng)上拉取下來的代碼叫做內(nèi)核代碼,如果增加新的設備內(nèi)核代碼確實會變得越來越臃腫,這點是肯定的,但是內(nèi)核并不會變得臃腫,具體原因我們接下里會進行討論。說了那么多內(nèi)核代碼,那內(nèi)核是什么呢?為什么內(nèi)核代碼變多了內(nèi)核卻不會變大?
內(nèi)核 是我們通過交叉編譯之后真正燒錄到板子里跑起來的代碼,而交叉編譯的時候,是有選擇的進行編譯,這里面有頂尖的大神們的智慧結晶,與你硬件相關的才編譯,不相關的代碼則不會被編譯到內(nèi)核里,所以不是說內(nèi)核里提交了一個設備的驅動你的內(nèi)核就會變大,這要看你的硬件有沒有用到這個驅動。
二、Linux中避免內(nèi)核臃腫的措施
我們上面知道了內(nèi)核是經(jīng)過我們交叉編譯裁剪之后的代碼,會有選擇性的將對我們有用的代碼編譯進內(nèi)核中,不需要的將被舍棄,這是Linux內(nèi)核開發(fā)者智慧的結晶,也是保證內(nèi)核不會變得臃腫的原因。那除了交叉編譯之外還有沒有其他的措施來保證內(nèi)核不會變的越來越大呢?下面就給大家分享幾個用來保證內(nèi)核不臃腫的措施。
2.1 交叉編譯及SDK包的裁剪
(這部分稍微有些啰嗦,主要為了讓初學者更好的理解,老工程師可以直接跳過啦!)交叉編譯是指在一種平臺上編譯生成在另一種不同平臺上運行的可執(zhí)行程序。在Linux中,常見的情況是在PC主機(Ubuntu系統(tǒng))上編譯生成適用于嵌入式設備或其他架構的目標程序。
通過上面的介紹我們已經(jīng)知道了內(nèi)核代碼是會通過交叉編譯來進行選擇性的將對我們有用的代碼編譯進內(nèi)核的,但是交叉編譯到底是如何工作的呢?我們應該怎么去配置交叉編譯以讓我們的內(nèi)核能過夠在穩(wěn)定運行的基礎上盡量小巧呢?
做過嵌入式Linux的應該都清楚,我這里的介紹也主要針對嵌入式Linux來講解,一般嵌入式Linux的交叉編譯工具鏈都是由SDK包提供商(一般是芯片廠)提供,所以一般不需要我們進行編寫和設計,只需要針對自己開發(fā)板的實際情況進行裁剪即可。
其實Linux代碼到你燒錄到板子中的內(nèi)核代碼是經(jīng)過了下面的過程:
上面的圖是我對于一套代碼從Linux開源代碼一步一步的被裁剪和適配后最終到達用戶手中過程的理解,當然不同的廠商這個過程可能有所不同。
所以回到我們的問題,看完上面圖片中的過程,你覺得Linux內(nèi)核中提交了新設備的驅動代碼會被燒錄到最終燒錄到板子中嗎?
這里分幾種情況來討論:
如果這個新設備在該款芯片上完全不會用到,那么芯片廠提供的SDK包中就不會包含這個驅動;
如果這個新設備芯片是支持的,但是我這款開發(fā)板不支持,那么板廠就不會同步這個設備的驅動;
如果這個新設備在開發(fā)板上也是支持的,但是作為用戶完全不會用到該設備,那么該設備的驅動也會被裁剪;
所以不是說Linux內(nèi)核代碼中新提交一個設備驅動,該設備驅動就會最終到開發(fā)板中,中間是會經(jīng)過很多篩選的,只有真正對用戶有用的代碼才會被同步編譯和燒錄。
這里用戶可能會有疑問,講了半天代碼包的裁剪,代碼裁剪和交叉編譯有什么關系呢?這里還要明確一點,代碼的裁剪并不是你想象的直接把代碼從代碼包中刪除了,更多時候是把代碼從編譯中刪除掉,即該設備的驅動并不會被編譯到內(nèi)核中,但是源代碼你還是可以看到的。
2.2 設備樹
設備樹的由來想必大家應該都有所耳聞:
“
ARM社區(qū)一貫充斥的大量垃圾代碼導致Linus盛怒,因此社區(qū)在2011年到2012年進行了大量的工作。ARM Linux開始圍繞Device Tree展開,Device Tree有自己的獨立的語法,它的源文件為.dts,編譯后得到.dtb,Bootloader在引導Linux內(nèi)核的時候會將.dtb地址告知內(nèi)核。之后內(nèi)核會展開Device Tree并創(chuàng)建和注冊相關的設備,因此arch/arm/mach-xxx和arch/arm/plat-xxx中大量的用于注冊platform、I2C、SPI板級信息的代碼被刪除,而驅動也以新的方式和.dts中定義的設備結點進行匹配。
”
在設備樹出現(xiàn)之前,內(nèi)核代碼中包含了大量與硬件設備相關的配置信息和初始化操作。隨著硬件數(shù)量和多樣性的增加,內(nèi)核代碼變得越來越復雜,難以管理和維護。設備樹將硬件描述從內(nèi)核代碼中分離出來,使得內(nèi)核代碼更加清晰簡潔,并且與具體硬件解耦。
使用設備樹可以在運行時動態(tài)地配置硬件設備,而無需修改內(nèi)核源代碼。這點對于代碼的調(diào)試非常方便,我們自需要重新編譯設備樹文件放到開發(fā)板中即可,而不用重新燒錄整個內(nèi)核。設備樹中的硬件描述信息可以根據(jù)實際硬件配置進行自由組合和調(diào)整,從而達到更好的兼容性和靈活性。
2.3 模塊化
Linux內(nèi)核采用的是模塊化設計,通過將功能劃分為獨立的模塊,可以提高代碼的可復用性和靈活性。內(nèi)核模塊是一段可以被動態(tài)加載到內(nèi)核中并擴展其功能的代碼。它相對獨立于內(nèi)核的其他部分,在需要時可以加載或卸載。
除了動態(tài)的加載將通用的功能封裝成獨立的模塊,可以被多個子系統(tǒng)或驅動程序共享和復用,避免了重復編寫相同的代碼,提高了開發(fā)效率。如果看過I2C驅動的話大家應該清楚I2C驅動分為設備驅動和核心驅動,Linux內(nèi)核已經(jīng)將I2C驅動的公用代碼封裝到核心代碼中了,其實I2C設備驅動代碼只需要簡單的調(diào)用I2C核心驅動中的接口即可,而不用從0開始完成一個I2C的驅動代碼,這樣代碼的復用率會變高,內(nèi)核驅動的代碼量和代碼復雜度也會變小。
2.4 硬件抽象層
硬件抽象層(Hardware Abstraction Layer,HAL)是一種軟件層,用于將底層硬件設備的詳細實現(xiàn)細節(jié)與上層應用程序隔離開來,提供一組統(tǒng)一的接口和功能,以簡化對硬件的訪問和操作。
硬件抽象層起到了在不同硬件平臺之間建立標準化接口的作用,使得應用程序可以以相似的方式進行硬件訪問和控制,而無需關心具體硬件的細節(jié)。通過使用硬件抽象層,開發(fā)人員可以更加方便地編寫跨平臺或可移植的應用程序,而不需要針對每個具體硬件設備進行獨立的編程。
總的來說硬件抽象層提供了一種中間層的軟件抽象,將底層硬件設備的具體實現(xiàn)細節(jié)與上層應用程序解耦,為開發(fā)人員提供簡化的硬件訪問接口和功能,以提高應用程序的可移植性和跨平臺性。
三、嵌入式Linux的裁剪
其實本文默認說的Linux內(nèi)核都是說的嵌入式Linux,因為對于像Ubuntu這種系統(tǒng)我也不太清楚。對于嵌入式Linux的裁剪我們上面已經(jīng)介紹了整個代碼包的流程,想必大家已經(jīng)明白了我們燒錄進去的內(nèi)核是已經(jīng)通過交叉編譯精簡過的,所以理論上來說燒錄進去的已經(jīng)是最精簡的了。
其實內(nèi)核裁剪不是我們想象的那么簡單,只有道行深的工程師才敢進行內(nèi)核的裁剪。Linux內(nèi)核裁剪我也沒有做過,所以這部分我留給大佬來補充吧!
四、總結
所以回歸最開始的問題,Linux內(nèi)核代碼60%都是驅動?驅動代碼不會造成內(nèi)核臃腫嗎?我認為答案是不會,如果你認為會變得越來越臃,可以一起交流一下哦!
審核編輯:劉清
-
Linux系統(tǒng)
+關注
關注
4文章
593瀏覽量
27392 -
LINUX內(nèi)核
+關注
關注
1文章
316瀏覽量
21644
原文標題:Linux內(nèi)核代碼60%都是驅動?驅動代碼不會造成內(nèi)核臃腫嗎?
文章出處:【微信號:嵌入式悅翔園,微信公眾號:嵌入式悅翔園】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論