歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 內核學習FAQ大集錦

內核學習FAQ大集錦

日期:2017/2/27 14:20:44   编辑:更多Linux
  1. 請推薦一些好的Linux內核參考書? a.《Linux Device Drivers, Second Edition》,有中文譯本 b.《Understanding the Linux Kernel, 2nd Edition》 c.《Linux內核源代碼情景分析》,分上下兩冊 d.《邊干邊學-Linux內核指導》 2. 內核源代碼問題 2.1 如何得到某一版本的Linux內核源代碼? a. http://www.kernel.org或FTP://ftp.kernel.org,這是Linux內核版本的發布 網站。 b. 很多鏡像或本地網站也提供部分Linux內核版本的下載,多用ftp搜索引擎。 c. 一般的Linux發行版如Redhat之類會隨盤提供相應的內核源代碼,不過這個源代 碼往往是改動過的,與同版本的標准Linux內核可能有些差異。 2.2 請推薦一些源代碼查看工具? a. Windows系統可以用Source Insight,Linux系統可以用Source Navigator。 b. vim或emacs編輯器,配合cscope、ctags、etags等交叉索引工具。 c. vim或emacs編輯器,配合grep、egrep等文本搜索工具,不過最好要對源代碼目 錄結構有所熟悉 d. LXR,以網頁的形式通過浏覽器浏覽,安裝復雜,可從http://lxr.linux.no/下 載該工具也可以直接訪問http://lxr.linux.no/source/在線閱讀Linux內核源 代碼。 2.3 xx結構的定義在哪個內核源文件中? a. 請使用源碼查看工具,見問題2.2。 b. 如果用grep等文本搜索工具,主要在include/linux和include/asm兩個目錄下 搜索。 2.4 volatile和__volatile__是什麼意思? a. volatile是C語言定義的關鍵字,gcc為了需要又定義了__volatile__,它和 volatile表達的是同一意思。 b. volatile的本意是"易變的",由於訪問寄存器的速度快於訪存,所以編譯器一般 都會作優化以減少訪存。如果變量加上volatile修飾,則編譯器就不會對此變量 的讀寫操作進行優化,即不通過寄存器緩沖而直接訪存。 c. __asm__ __volatile__一起指示編譯器不要改動優化後面的匯編語句。 2.5 do{ ... } while(0)是什麼意思? a. 主要是為了避免宏在不同情況展開可能會出現的一些錯誤。 b. 在http://www.kernelnewbies.org/faq/上有詳細介紹。 2.6 list_entry的定義是怎麼回事? a. list_entry的定義在內核源文件include/linux/list.h中: #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) b. 其功能是根據list_head型指針ptr換算成其宿主結構的起始地址,該宿主結構是 type型的,而ptr在其宿主結構中定義為member成員。如下圖: req-->type型對象起始地址 ... ... ptr-->ptr指針所指的member成員地址 ... ... ptr指向圖中所示的位置,通過(unsigned long)(&((type*)0)->member)得到ptr 和req之間的差值,ptr減去這個差值就得到了type型宿主結構的指針req,返回 類型為(type*)。 3. 模塊編程問題 3.1 模塊編程需要注意什麼? a. 在gcc編譯選項中增加-c b. 在gcc編譯選項中定義兩個宏:-DMODULE -D__KERENL__ 或直接在源文件中定義這兩個宏: #define MODULE #define __KERNEL__ c. 在源文件中包括module.h文件: #include <linux/module.h>


d. 如果要用inline功能,需要在gcc編譯選項中增加-O2 3.2 為什麼insmod一個模塊時顯示版本不匹配? 假定你現在運行的內核的源碼目錄絕對路徑是MyKernelSrcPath,在gcc編譯時 增加選項: -I $MyKernelSrcPath/include 3.3 為什麼出現Unresolved Symbol? a. 首先查看文件/proc/ksyms,看內核有沒有輸出這個符號,不同的內核版本如 2.2和2.4輸出的符號會有些變化。 b. 如果內核輸出的符號帶有版本控制信息如符號printk_R12345678,則性質同 問題3.2。 3.4 為什麼出現no license錯誤? 在源文件加入下面一行: MODULE_LICENSE("GPL"); 3.5 為什麼看不到用printk打印的信息? a. 打印消息受級別的限制,消息級別可以通過printk設置,如: printk("<n>something"); /* 其中0<=n<=7 */ 假設控制台的消息級別為m, 當n<m時消息打印到控制台,否則不打印。 這樣一方面可以提高要打印消息本身的級別(數字越小級別越高), 另一方面可以改變控制台的消息級別(可從1到,如改為8可用以下命令: # echo "8" > /proc/sys/kernel/printk b. 用dmesg命令看。 c. 當系統運行klogd和syslogd時,內核消息就會由klogd分發到syslogd, syslogd會根據配置文件/etc/syslog.conf作相應處理,具體可以查看syslogd 和syslog.conf的man頁。 4. 內核開發問題 4.1 怎麼制作、使用patch文件? patch文件是由diff命令生成的,使用patch文件用patch命令,具體可查看diff和 patch的man頁和info。 4.2 在內核中可以使用系統調用嗎? a. 可以。內核源代碼中就有使用系統調用的例子,如open()、execve()等。 b. 在內核中使用系統調用必須要在源文件中包括以下兩行: #define __KERNEL_SYSCALLS__ #include <linux/unistd.h> c. 內核中使用系統調用的相關定義可查看文件include/asm/unistd.h。 如果要用的系統調用該文件中沒有定義,可以按照其格式自行添加。 4.3 在內核中怎麼打開並操作一個文件? a. 直接用open()、read()等系統調用,見問題4.2。 b. 用filp_open()函數打開文件,得到strUCt file *的指針fp。 使用指針fp進行相應操作,如讀文件可以用fp->f_ops->read。 最後用filp_close()函數關閉文件。 filp_open()、filp_close()函數在fs/open.c定義,在include/linux/fs.h中 聲明。 c. 自己寫包裝函數,可參照文件fs/exec.c中的open_exec()和kernel_read()函數。 在http://www.linuxforum.net/forum/showflat.PHP?Cat=&Board=linuxK &Number=363455&page=&view=&sb=&o=&vc=1上有些代碼可以參照。 4.4 在內核中讀寫文件時為什麼會出現EFAULT錯誤? a. 內核文件系統提供的read()和write()之類的函數,期望是對用戶態程序服務的, 所以它會驗證讀寫緩沖區不超過用戶空間的上限即0xC000 0000。但現在內核中 要讀寫文件,緩沖區在內核中即地址會超過0xC000 0000。 b. 在讀寫文件前先得到當前fs:mm_segment_t old_fs=get_fs(); 並設置當前fs為內核fs:set_fs(KERNEL_DS); 在讀寫文件後再恢復原先fs: set_fs(old_fs); set_fs()、get_fs()等相關宏在文件include/asm/uAccess.h中定義。 5. 其它 5.1 請問xx命令、xx庫的源碼是哪個文件? a. 一個系統除了內核以外,還需要有shell、gcc等一系列工具和命令以及C庫等一 系列庫,這些作為應用程序其源代碼都不在內核中,需要另外下載相應的源代碼。 b. 對於Redhat系統,可以用rqm -qf命令來查找某一命令所在的軟件包,然後再找 相應的源代碼包安裝。



要讀寫文件,緩沖區在內核中即地址會超過0xC000 0000。 b. 在讀寫文件前先得到當前fs:mm_segment_t old_fs=get_fs(); 並設置當前fs為內核fs:set_fs(KERNEL_DS); 在讀寫文件後再恢復原先fs: set_fs(old_fs); set_fs()、get_fs()等相關宏在文件include/asm/uAccess.h中定義。 5. 其它 5.1 請問xx命令、xx庫的源碼是哪個文件? a. 一個系統除了內核以外,還需要有shell、gcc等一系列工具和命令以及C庫等一 系列庫,這些作為應用程序其源代碼都不在內核中,需要另外下載相應的源代碼。 b. 對於Redhat系統,可以用rqm -qf命令來查找某一命令所在的軟件包,然後再找 相應的源代碼包安裝。



Copyright © Linux教程網 All Rights Reserved