歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> Linux技術

內核頭文件使用

原地址:http://blog.chinaunix.net/uid-20543672-id-3162485.html
昨天,同事在編譯應用層程序(V4L2相關)的時候出現了一個這樣的警告:
*/2.6.37/include/linux/types.h:13:2: warning: #warning "Attempt to use kernel headers from user space, seehttp://kernelnewbies.org/KernelHeaders"
然後問我這個怎麼消除。我也是第一次注意到這個警告(以前可能有出現,可能我沒有注意吧)。然後我根據後面提供的網址,研讀了一下這份英文資料,發現這個原來是頭文件的使用不當產生的。英文資料翻譯如下:
內核頭文件
Linux內核中的頭文件用於兩個目的:
1、定義內核組件間的接口,和
2、定義內核與用戶空間的接口
內部模塊
模塊間的內部接口在linux/include/ 或 linux/arch/*/include/ 下都有定義。一個單獨模塊的源文件間的接口應該同模塊源碼置於同一目錄下,避免污染全局頭文件空間。
外部模塊
為了編譯外部內核模塊,你需要來自該模塊所針對內核的頭文件。Driver porting: compiling external modules 解釋了如何編寫一個外置的Makefile來使用這些頭文件。照此做法,內核Makefile將為源碼和編譯目錄自動選擇正確的包含路徑,並從正確的構架中使用include/asm頭文件。
傳統的內核源碼安裝在/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
,且沒有符號鏈接到架構特定的目錄。
為一個發行版打包頭文件正確的方法是在內核源碼目錄下運行 'make headers_install'來安裝頭文件到/usr/include,並依賴這個剛剛安裝的特定版本的內核頭文件重新編譯C庫包。
如果你正在發布一個依賴某個特定版本內核頭文件的用戶空間程序,比如因為你的程序只運行在打過補丁或者最新的內核上,你不能依賴/usr/include中的頭文件。你也不能使用來自/usr/src/linux/include 或/lib/modules/*/build/include/的頭文件,因為他們還沒有為用戶空間的包含做好准備。若你嘗試這麼做了,內核會警告你並指引你到這個Wiki頁。解決這個問題的正確方法是獨立出你需要的特定接口,比如一個打過補丁的新內核並為你的應用程序提供字符設備ioctl號的獨立頭文件。在你自己的程序中添加一份這個源文件的拷貝,並說明這個應該和新內核版本保持一致。如果你的程序不遵循GPLv2證書,請保證你得到了這個文件作者的許可:可在你自己程序的證書下發布它。因為你的程序現在依賴的內核接口並不在常規內核中。在這種情況下,一個推薦的做法是通過運行時檢測來保證內核知道這個接口並在無法向下兼容舊接口的時候給出有用的錯誤信息。
看了這個說明,我就明白了,我同事直接使用了內核源碼中沒有處理過的頭文件。而我一般都是使用編譯器中自動包含的頭文件,那個是通過'make
headers_install'安裝的,所以一般不會出這樣的警告。
後來,我讓同事使用以下的方法解決了這個警告:
1、在內核源碼根目錄下運行: 'make headers_install',這樣內核Makefile會把提供給應用程序的頭文件提取並放在內核源碼的“usr/include”目錄下。
(請勿擔心git會發現文件增加了,usr目錄中的.gitignore文件已經讓git忽略了其下的include文件夾)
2、在編譯應用程序的時候,在GCC的CFLAG參數中添加“-I(內核源碼路徑)/usr/include”,這樣編譯器就知道在編譯時找到相關的頭文件了。
----------------------------------------------------------------------------------------------
平時我們在編譯應用程序的時候,不可避免的會使用內核頭文件,比如v4l2,字符驅動等等。此時直接的使用內核源碼中include目錄下的頭文件,可能就會有警告。這個警告現在看來僅在"include/linux/types.h"中存在,因為這個文件中包含了很多內核自定義的類型,你的應用程序如果也做了這樣的定義就可能出現問題。此時你就應該使用內核幫你處理過的專門提供給用戶空間的頭文件,這個就是為什麼'make
headers_install'會將頭文件(默認)放在usr(用戶)目錄下的原因。
關於這個頭文件的問題,其實是有一段歷史故事的:《內核頭文件傳奇》。挺有意思的,大家看過後就知道內核頭文件的使用為什麼是這樣了。
Copyright © Linux教程網 All Rights Reserved