內(nèi)核開發(fā)與用戶空間應用程序開發(fā)的差異

寫在前面:

本文是我學習《Linux內(nèi)核設計與實現(xiàn)》 一書的學習筆記柿冲,以書的章節(jié)目錄為框架较性,同時加入一定的網(wǎng)上搜索的資料以及自己的理解瘩欺。供自己學習外,也希望能分享出去沫屡,幫助其他學習者饵隙。

差異一? 內(nèi)核編程時既不能訪問C庫也不能訪問標準 C 頭文件

由于大小和速度的限制,無論是完整的C庫還是它的子集沮脖,都太大太低效金矛。 所以內(nèi)核不能鏈接使用標準C函數(shù)庫。

大部分常用的C庫函數(shù)在內(nèi)核中得到了實現(xiàn)倘潜,Linux下的庫文件分為共享庫和靜態(tài)庫兩大類绷柒,它們兩者的差別僅在程序執(zhí)行時所需的代碼是在運行時動態(tài)加載的,還是在編譯時靜態(tài)加載的涮因。?Linux的庫一般在/lib?或/usr/lib?目錄下废睦,例如操作字符串的函數(shù)組就位于lib/string.c 文件中,想要使用它們的話养泡,只要包含 <linux/string.h> 嗜湃。

在所以沒有實現(xiàn)的函數(shù)中,最著名的就是printf函數(shù)澜掩,但是內(nèi)核代碼提供了幾乎相同的printk函數(shù)购披。printk相對于printf的一個顯著區(qū)別在于printk允許通過制定log level來設置優(yōu)先級。具體的優(yōu)先級如下表所示肩榕。

printk prototype: int printk(const char *fmt,...);

內(nèi)核基本的頭文件位于內(nèi)核源代碼書頂級目錄下的include目錄下刚陡, 例如 include/linux/inotify.h , 內(nèi)核代碼通過形如 <linux/inotify.h>的方式包含內(nèi)核基本頭文件株汉。 (inotify是一種在Linux 2.6新添加的特性筐乳,它可以實現(xiàn)對文件系統(tǒng)進行監(jiān)控,通過觸發(fā)的方式告訴你文件的變化)乔妈。

體系結(jié)構(gòu)相關(guān)的頭文件集位于內(nèi)核源代碼樹的 arch/<architecture>/include/asm 目錄下蝙云, architecture 表示所用的體系結(jié)構(gòu),例如x86體系結(jié)構(gòu)的相關(guān)頭文件就在?arch/x86/include/asm 目錄下路召。 內(nèi)核代碼通過形如<asm/ioctrl.h>的方式包含體系結(jié)構(gòu)相關(guān)的頭文件勃刨。(ioctl是設備驅(qū)動程序中對設備的I/O通道進行管理的函數(shù)波材。所謂對I/O通道進行管理,就是對設備的一些特性進行控制身隐,例如串口的傳輸波特率廷区、馬達的轉(zhuǎn)速等等。)?

差異二? 內(nèi)核編程必須使用 GNU C

Linux庫的命名比較簡單抡医,第一個特點是所有的庫以lib開頭躲因,GCC命令在在-l?選項所指定的文件名前會自動加入lib。第二個特點文件名以.a結(jié)尾的庫是靜態(tài)庫?忌傻。第三個特點文件名是.so的庫為共享庫(共享庫是在運行的時候動態(tài)加載的?)?大脉。默認情況下,GCC在鏈接時優(yōu)先使用共享庫水孩,只有當共享庫不存在時才考慮使用靜態(tài)庫镰矿。?

內(nèi)聯(lián)函數(shù) - inline關(guān)鍵字定義,一般定義在頭文件中(若是內(nèi)聯(lián)函數(shù)僅僅在某個源文件中使用俘种,也可以把它定義在文件開始的地方秤标。),形如下面的例子宙刘。

static inline void wolf (unsigned long tail_size)

它會在調(diào)用它的地方展開苍姜,因此內(nèi)聯(lián)函數(shù)在使用前必須定義好,否則編譯器沒法展開悬包。這樣可以消除函數(shù)調(diào)用和返回所帶來的開銷衙猪,包括寄存器的存儲和恢復。并且編譯器會將調(diào)用函數(shù)的代碼以及函數(shù)本身放在一起優(yōu)化布近。這樣做的代價就是占用更多的內(nèi)存空間或者占用更多的指令緩存垫释。內(nèi)核開發(fā)這通常會把那些對時間要求較高,而本身長度比較短的函數(shù)定義成內(nèi)聯(lián)函數(shù)撑瞧。

很自然的棵譬,人們會把內(nèi)聯(lián)函數(shù)與宏定義做比較,一個顯著的區(qū)別在于预伺,宏定義在預處理是展開订咸,因此不檢查函數(shù)參數(shù),返回值什么的酬诀,只是展開脏嚷,相對來說,內(nèi)聯(lián)函數(shù)在編譯時展開料滥,因此會檢查參數(shù)類型然眼,所以更安全艾船。此外葵腹,內(nèi)聯(lián)函數(shù)能有效避免使用宏定義可能產(chǎn)生的由優(yōu)先級引起的錯誤以及有宏定義中有多個相同操作數(shù)且有自增操作時高每,回到導致展開的代碼不符合預期。因此內(nèi)聯(lián)函數(shù)更被推薦使用践宴。

GCC 編譯器支持 在C函數(shù)中嵌入會變指令(這樣做的前提是知道對應的體系結(jié)構(gòu))鲸匿。我們通常使用asm()指令嵌入?yún)R編代碼,直接對寄存器進行操作阻肩。

asm(

"mov? ? r0, r0\n\t"

"mov? ? r0, r0\n\t"

"mov? ? r0, r0\n\t"

"mov? ? r0, r0"

);

對于條件選擇語句带欢,gcc內(nèi)建了一條指令用于優(yōu)化,當一個條件經(jīng)常出現(xiàn)/很好出現(xiàn)的時候烤惊,編譯器可以根據(jù)這條指令對條件分之選擇進行優(yōu)化乔煞,這條指令被內(nèi)核封裝成了 likely 與 unlikely 宏。?

例如當error錯誤分支很少發(fā)生柒室,我們可以定義:

if(unlikely(error)){

}

相反如果我們想把一個分支標記為通常為真的選擇渡贾,可以定義:

if(likely(success)){

}。

使用likely一定要非常小心雄右,如果某個條件不是占壓倒性的低位時空骚,使用likely反而會降低性能。而unlikely則被廣泛使用去標記異常分支擂仍。

差異三 內(nèi)核沒有內(nèi)存保護機制

當用戶進程試圖非法訪問時囤屹,內(nèi)核會發(fā)現(xiàn)這個錯誤,發(fā)送SIGSEGV信號逢渔,并結(jié)束整個進程肋坚,而內(nèi)核自己非法訪問內(nèi)存時,會導致oops錯誤。因此木缝,在內(nèi)核中不應該去訪問非法的內(nèi)存地址拦焚,引用空指針之類的事情,否則它可能死掉去根本不通知你一聲峦剔。

此外,內(nèi)核中的內(nèi)存不分頁角钩,也就是說吝沫,內(nèi)核中用掉每一字節(jié),物理內(nèi)存就會少掉一個字節(jié)递礼。

差異四 不要輕易在內(nèi)核中使用浮點數(shù)

差異五 內(nèi)核有容積小且固定的棧

用戶空間的棧比較大惨险,且可以動態(tài)增長,所以用戶進程可以從棧上分配大量的空間存放變量脊髓,甚至包含巨大的結(jié)構(gòu)體和數(shù)組辫愉。而內(nèi)核的棧隨體系結(jié)構(gòu)而變化,到那時固定而小将硝,每個處理器都有自己的棧恭朗。

差異六 同步和并發(fā)

Linux內(nèi)核支持SMP屏镊,兩個或多個處理器上執(zhí)行的中斷代碼可能會同時訪問共享的資源。

Linux內(nèi)核可以搶占痰腮,內(nèi)核中一段正在執(zhí)行的代碼可能被另一段代碼搶占而芥,從而導致幾段代碼訪問相同資源。

中斷是異步到來的膀值,不會顧及到正在執(zhí)行的代碼棍丐。如果不加以適當?shù)谋Wo,中斷完全可能會在代碼訪問資源時到來沧踏,這樣中斷處理函數(shù)就可能訪問同一資源歌逢。

為防止上述的問題,自旋鎖以及信號量是常用的解決并發(fā)中的資源競爭問題的方法翘狱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趋翻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子盒蟆,更是在濱河造成了極大的恐慌踏烙,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件历等,死亡現(xiàn)場離奇詭異讨惩,居然都是意外死亡,警方通過查閱死者的電腦和手機寒屯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門荐捻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寡夹,你說我怎么就攤上這事处面。” “怎么了菩掏?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵魂角,是天一觀的道長。 經(jīng)常有香客問我智绸,道長野揪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任瞧栗,我火速辦了婚禮斯稳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迹恐。我一直安慰自己挣惰,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著憎茂,像睡著了一般唆涝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唇辨,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音能耻,去河邊找鬼赏枚。 笑死,一個胖子當著我的面吹牛晓猛,可吹牛的內(nèi)容都是我干的饿幅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戒职,長吁一口氣:“原來是場噩夢啊……” “哼栗恩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洪燥,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤磕秤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捧韵,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體市咆,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年再来,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒙兰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡芒篷,死狀恐怖搜变,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情针炉,我是刑警寧澤挠他,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站篡帕,受9級特大地震影響绩社,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赂苗,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一愉耙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拌滋,春花似錦朴沿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽魏铅。三九已至,卻和暖如春坚芜,著一層夾襖步出監(jiān)牢的瞬間览芳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工鸿竖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沧竟,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓缚忧,卻偏偏與公主長得像悟泵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子闪水,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容