Linux內核頭文件


Linux內核頭文件

概述:在進行有關系統軟件的安裝的時候(編譯一個新的驅動,或者安裝一個系統級別的測試工具,例如systemtap),經常需要重新編譯內核,相應的問題往往與內核頭文件有關。那么,什么是內核頭文件,為什么需要更新內核頭文件?內核頭文件作用是什么,如何更新?本文主要為你解答這些疑問。

1.內核頭文件的發展歷史

​ 在 Linux 2.2/2.4 的純真年代,內核頭文件一直保持着 Unix 世界的"KISS"傳統,只需將內核源碼樹中的頭文件直接復制到 /usr/include 中即可使用,一切都是那么 Simple and Stupid ...

​ 但是隨着 2.6 系列內核的發布,事情開始變得混亂和復雜起來。首先是內核開發者宣布強烈反對直接使用"未凈化"的"原始"內核頭文件,他們建議使用發行版提供的"經過凈化的"內核頭文件。於是各種發行版開始"八仙過海,各顯神通",由於"凈化"方法各不相同,結果就是每個發行版都有着自己與眾不同的內核頭文件。更為嚴重的是,內核開發者甚至推薦編譯 Glibc 的頭文件也要使用發行版提供的"經過凈化的"內核頭文件。由於 Glibc 和 Kernel 是整個系統的根基,這樣一來 Linux 便像傳統的 Unix 那樣開始走向分裂。
​ 另一件哭笑不得的事情是,雖然內核開發者強烈推薦使用發行版提供的"經過凈化的"內核頭文件,但是 Glibc 的開發者卻不買賬,他們推薦使用"未凈化"的"原始"內核頭文件來編譯 Glibc ,兩個開發組一直堅持各自的見解,互不妥協!另外,兩個開發組在應當由誰提供內核頭文件的問題上意見也不一致:內核開發組認為應當由發行版的制作者提供,而 Glibc 開發組認為應當由內核開發組提供。結果就是"神仙打架,凡人遭殃",雖然對 Debian 這種大型發行版來說,提供自己獨有的"經過凈化的"內核頭文件不會成為多大的負擔,但是對於那些沒有能力或精力的小心發行版制作者和我們這些 DIY fans 來說卻是一場災難!要么直接使用其他發行版的成果,要么自力更生;前者讓人心有不甘(沒有了 DIY 的原汁原味),后者讓人望而生畏(有幾個人知道啥叫"凈化"?怎么凈化?)。
​ 危機時刻總會有英雄的出現,就在一片恐慌之際,一個叫"linux-libc-headers"項目組誕生了!他們向我們這些"凡人"們提供了安全的、普遍適用的、"經過凈化的"內核頭文件,真是及時雨啊!天空重新晴空萬里……然而好景不長,由於精力和人力有限,該項目在發布了 2.6.12.0 版本之后,遺憾的離開了這個世界。這樣一來,2.6.12 以上版本的內核新特性(比如新的系統調用)和 ABI/API 的變化就無法反映出來,對於我們這些 DIY fans 來說,世界重回混沌……
​ 俗話說,"合久必分,分久必合",大概是內核開發組意識到了如果繼續固執己見將不可避免的導致混亂以及重蹈 Unix 逐漸走向分裂的覆轍,於是從 2.6.18 版本開始,內核開發組擔負起了維護一份統一的、"經過凈化的"內核頭文件的職責(竊以為這原本就是他們的責任)。現在獲取"經過凈化的"內核頭文件又變得簡單起來,只要在內核源碼樹中使用 make headers_install 即可,而且不用再擔心更新問題。對於我們這些 DIY fans 來說,又可以重新 Day Day Happy 了。

​ 不過,由於磨合需要時間。目前 Glibc-2.4 以下的版本都無法配合這種新式頭文件編譯成功。

2內核頭文件的作用

​ 說了這么多,那么什么時候會用到內核頭文件呢?內核頭文件又有哪些與用戶有關的作用呢?

​ 概括來說,內核頭文件的作用主要有兩個:1)定義內核組件間的接口2)定義內核與用戶空間的接口

​ 內部模塊:模塊間的內部接口在linux/include/ 或 linux/arch/*/include/ 下都有定義。一個單獨模塊的源文件間的接口應該同模塊源碼置於同一目錄下,避免污染全局頭文件空間。

​ 外部模塊:傳統的內核源碼安裝在/usr/src/linux下,這不再支持外部模塊的編譯。相反,你的Makefile應該指向/lib/modules/${kver}/build,其中${kver}是內核確切的版本字符串,例如:對於當前正在運行的內核,就是“uname -r”的輸出。

​ 用戶空間程序:一般來說,用戶空間程序是針對發行版提供的頭文件編譯的,通常源於glibc-devel、glibc-kernheaders 或 linux-libc-dev。這些頭文件通常來源於舊版內核,並不能安全地在不重新編譯glibc的情況下被替換。特別地,作為一個到/usr/src/linux/include或/lib/modules/*/build/include/linux的符號鏈接/usr/include/linux,是極不推薦使用的。因為它經常使重新編譯的應用程序損壞。例如,舊內核使用include/asm-${arch}存放架構特定的頭文件,而不是現在的arch/${arch}/include/asm ,且沒有符號鏈接到架構特定的目錄。

3.如何打包頭文件

​ 為發行版打包頭文件:為一個發行版打包頭文件正確的方法是在內核源碼目錄下運行 'make headers_install'來安裝頭文件到/usr/include,並依賴這個剛剛安裝的特定版本的內核頭文件重新編譯C庫包。如果你正在發布一個依賴某個特定版本內核頭文件的用戶空間程序,比如因為你的程序只運行在打過補丁或者最新的內核上,你不能依賴/usr/include中的頭文件。你也不能使用來自/usr/src/linux/include 或/lib/modules/*/build/include/的頭文件,因為他們還沒有為用戶空間的包含做好准備。若你嘗試這么做了,內核會警告你並指引你到這個Wiki頁。解決這個問題的正確方法是獨立出你需要的特定接口,比如一個打過補丁的新內核並為你的應用程序提供字符設備ioctl號的獨立頭文件。在你自己的程序中添加一份這個源文件的拷貝,並說明這個應該和新內核版本保持一致。如果你的程序不遵循GPLv2證書,請保證你得到了這個文件作者的許可:可在你自己程序的證書下發布它。因為你的程序現在依賴的內核接口並不在常規內核中。在這種情況下,一個推薦的做法是通過運行時檢測來保證內核知道這個接口並在無法向下兼容舊接口的時候給出有用的錯誤信息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM