linux核心開發的特點
相對於使用者空間內的應用程式開發,核心開發存在很多的不同,最重要的差異包括以下幾種:
1)核心程式設計時不能訪問c庫。
2)核心程式設計時必須使用gnu c。
3)核心程式設計時缺乏像使用者空間那樣的記憶體保護機制。
4)核心程式設計時浮點數很難使用。
5)核心只有乙個很小的定長堆疊。
6)由於核心支援非同步中斷,搶占和smp,因此必須時刻注意同步和併發。
7)要考慮可移植性的重要性。
1.沒有libc庫
與使用者空間的應用程式不同,核心不能鏈結使用標準c函式庫(其他的那些庫也不行)。最主要的原因在於速度和大小。雖然不能使用,但大部分常用的c庫函式在核心中都已經得到實現。比如說操作字串的函式組就位於lib/string.c檔案中,只要包含標頭檔案,就可以使用它們。
核心並沒有實現printf(),但可以使用printk(),printk()負責把格式化好的字串拷貝到核心日誌緩衝區上,這樣,syslog程式就可以通過讀取該緩衝區來獲取核心資訊。printk()的用法很像printf():
printk("hello world! a string: %s and an integer: %d.\n", a_string, an_integer);
printk()和printf()之間的乙個顯著區別在於printk()允許通過指定乙個標誌來設定優先順序。syslog會根據這個優先順序標誌來決定在什麼地方顯示這條系統訊息。
printk(kern_err "this is a error!\n");
2.gnu c
linux核心是用c語言編寫的,但它並不完全符合ansi c標準,而使用到gcc提供的許多語言擴充套件部分。
1)內聯(inline)函式
inline使函式在它被呼叫的位置上展開,這樣做可以消除函式呼叫和返回所帶來的開銷(暫存器儲存和恢復)。而且,由於編譯器會把呼叫函式的**和函式本身放在一起進行優化,所以也有進一步優化**的可能。不過,這樣做是有代價的,**會變長,意味著占用更多的記憶體空間或者占用更多的指令快取。通常把那些對時間要求比較高,而本身長度又比較短的函式定義成內聯函式。
static inline void dog(unsinged long tail_size);
在核心中,為了型別安全的原因,優先使用內聯函式而不是複雜的巨集。
2)內聯彙編
gcc編譯器支援在c函式中嵌入彙編指令。當然,在核心程式設計的時候,只有知道對應的體系結構,才能使用這個功能。
3)分支宣告
對於條件選擇語句,gcc內建了一條指令用於優化,在乙個條件經常出現,或者該條件很少出現的時候,編譯器可以根據這條指令對條件分支選擇進行優化,核心把這條指令封裝成了巨集,比如likely()和unlikely()。
例如,下面是乙個條件選擇語句:
if (foo) {
如果想要把這個選擇標記成絕少發生的分支:
/* 我們認為foo絕大多數時間都會為 0 */
if (unlikely(foo)) {
相反,如果我們想把乙個分支標記為通常為真的選擇
/* 我們認為foo通常都不會為 0 */
if (likely(foo)) {
在想要對某個條件選擇語句進行優化之間,一定要搞清楚其中是不是存在這麼乙個條件,在絕大多數情況下都會成立,這點十分重要:如果你的判斷正確,確定是這個條件佔壓倒性的地位,那麼效能會得到提公升,如果你搞錯了,效能反而會下降。在對一些錯誤條件進行判斷的時候,常常用到unlikely()和likely()。可以猜到,unlikely()在核心中得到廣泛使用,因為if語句往往判斷一種特殊情況。
3.沒有記憶體保護機制
如果乙個使用者程式試圖進行一次非法的記憶體訪問,核心會發現這個錯誤,傳送sigsegv,並結束整個程序。然而,如果是核心自己非法訪問了記憶體,那後果就很難控制了,核心中發生的記憶體錯誤會導致oops,這是核心中出現的最常見的一類錯誤。在核心中,不應該去做訪問非法的記憶體位址,引用空指標之類的事情,否則它可能會死掉,卻根本不知會你一聲——在核心裡,風險常常會比外面大一些。
此外,核心中的記憶體都不分頁,也就是說,用掉乙個位元組,物理記憶體就減少乙個位元組。所以,在你想往核心裡加入什麼新功能的時候,要記住這一點。
4.不要輕易在核心中使用浮點數
使用者空間的程序內進行浮點操作的時候,核心會完成從整數操作到浮點數操作的模式轉換。在執行浮點指令時到底會做些什麼,因體系結構不同,核心的選擇也不同,但是,核心通常捕獲陷阱並做相應處理。
和使用者空間程序不同,核心並不能完美地支援浮點操作,因為它本身不能陷入。在核心中使用浮點數時,除了要人工儲存和恢復浮點暫存器,還有其他一些瑣碎的事情要做。如果要直截了當的回答,那就是:別這麼做,不要在核心中使用浮點數。
5.容積小而固定的棧
使用者空間的程式可以從棧上分配大量的空間來存放變數,甚至巨大的結構體或者是包含許多資料項的陣列都沒有問題。因為使用者空間的棧本身比較大,而且還能動態的增長。
核心棧的準確大小隨體系結構而變。在x86上,棧的大小在編譯時配置,可以是4kb或8kb。核心棧的大小是兩頁,所以32位機的核心棧是8kb,而64位機是16kb,這是固定不變的。每個處理器都有自己的棧。
6.同步和併發
核心很容易產生競爭條件,因核心的許多特性都要求能夠併發的訪問共享資料,這就要求有同步機制保證不出現競爭條件,尤其是:
1)linux是搶占多工作業系統。核心的程序排程程式即興對程序進行排程和重新排程。核心必須對這些任務同步。
2)linux核心支援多處理器系統。如果沒有適當的保護,在兩個或兩個以上的處理器上執行的**很可能會訪問共享的同乙個資源。
3)中斷是非同步到來的,完全不顧及當前正在執行的**。如果不加以適當的保護,中斷完全有可能在**訪問共享資源的當中到來,這樣中斷處理程式就有可能訪問同一資源。
4)linux核心可以搶占,如果不加以適當的保護,核心中的一段正在執行的**可能會被另外一段**搶占,從而有可能導致幾段**同時訪問相同的資源。
7.可移植性的重要性
linux是乙個可移植的作業系統,大部分c**應該與體系結構無關,在許多不同體系結構的計算機上都可以編譯和執行。因此,必須把體系結構相關的**從核心**樹的特定目錄中適當地分享出來。
諸如保持位元組序,64位對齊,不假定字長和頁面長度等一系列準則都有助於移植性。
第二章從核心出發之Linux核心開發特點
2.4 核心開發的特點 相對於使用者空間內應用程式的開發,核心開發有一些獨特之處。儘管這些差異並不會使開發核心的難點超過開發使用者 但依然有很大不同。核心程式設計時既不能訪問c庫也不能訪問標準的c標頭檔案。核心程式設計時必須使用gnu c。核心程式設計時缺乏像使用者空間那樣的記憶體保護機制。核心程式...
Qt 核心特點
本文主要對qt中一些核心的特點進行簡單的介紹。元物件系統 元物件系統 meta object system 提供了物件之間通訊的訊號與槽 執行時型別資訊和動態屬性系統。主要有三部分組成 對於qobject及其子類,可以使用qobject cast 函式進行型別轉換,類似c 中的 dynamic st...
Linux核心開發 核心模組引數
目錄 使用引數載入模組 module param巨集 讀取和更改引數值 驗證引數值 宣告模組引數陣列 有關模組引數的一些說明 在本文中,我們將向模組新增引數。使用引數,您可以在載入模組時訪問模組全域性變數,並在執行時已載入模組時訪問模組全域性變數。使用insmod命令載入模組時,可以提供引數作為ke...