Linux内核常见FAQ
?? ? 推薦一些好的Linux內(nèi)核參考書?
a.《Linux Device Drivers, Second Edition》,有中文譯本
b.《Understanding the Linux Kernel, 2nd Edition》
c.《Linux內(nèi)核源代碼情景分析》,分上下兩冊
d.《邊干邊學(xué)-Linux內(nèi)核指導(dǎo)》
? ? 如何得到某一版本的Linux內(nèi)核源代碼?
a. http://www.kernel.org或ftp://ftp.kernel.org,這是Linux內(nèi)核版本的發(fā)布網(wǎng)站。
b. 很多鏡像或本地網(wǎng)站也提供部分Linux內(nèi)核版本的下載,多用ftp搜索引擎。
c. 一般的Linux發(fā)行版如Redhat之類會(huì)隨盤提供相應(yīng)的內(nèi)核源代碼,不過這個(gè)源代碼往往是改動(dòng)過的,與同版本的標(biāo)準(zhǔn)Linux內(nèi)核可能有些差異。
? ? 推薦一些源代碼查看工具?
a. Windows系統(tǒng)可以用Source Insight,Linux系統(tǒng)可以用Source Navigator。
b. vim或emacs編輯器,配合cscope、ctags、etags等交叉索引工具。
c. vim或emacs編輯器,配合grep、egrep等文本搜索工具,不過最好要對源代碼目錄結(jié)構(gòu)有所熟悉
d. LXR,以網(wǎng)頁的形式通過瀏覽器瀏覽,安裝復(fù)雜,可從http://lxr.linux.no/下載該工具也可以直接訪問http://lxr.linux.no/source/在線閱讀Linux內(nèi)核源代碼。
? ? xx結(jié)構(gòu)的定義在哪個(gè)內(nèi)核源文件中?
a. 請使用源碼查看工具,見問題2.2。
b. 如果用grep等文本搜索工具,主要在include/linux和include/asm兩個(gè)目錄下搜索。
? ? volatile和__volatile__是什么意思?
a. volatile是C語言定義的關(guān)鍵字,gcc為了需要又定義了__volatile__,它和volatile表達(dá)的是同一意思。
b. volatile的本意是"易變的",由于訪問寄存器的速度快于訪存,所以編譯器一般都會(huì)作優(yōu)化以減少訪存。如果變量加上volatile修飾,則編譯器就不會(huì)對此變量的讀寫操作進(jìn)行優(yōu)化,即不通過寄存器緩沖而直接訪存。
c. __asm__ __volatile__一起指示編譯器不要改動(dòng)優(yōu)化后面的匯編語句。
? ? do{ ... } while(0)是什么意思?
a. 主要是為了避免宏在不同情況展開可能會(huì)出現(xiàn)的一些錯(cuò)誤。
b. 在http://www.kernelnewbies.org/faq/上有詳細(xì)介紹。
? ? list_entry的定義是怎么回事?
a. list_entry的定義在內(nèi)核源文件include/linux/list.h中:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
b. 其功能是根據(jù)list_head型指針ptr換算成其宿主結(jié)構(gòu)的起始地址,該宿主結(jié)構(gòu)是type型的,而ptr在其宿主結(jié)構(gòu)中定義為member成員。如下圖:
req>|type型對象起始地址
|
|... ...
ptr>|ptr指針?biāo)傅膍ember成員地址
|
|... ...
ptr指向圖中所示的位置,通過(unsigned long)(&((type*)0)->member)得到ptr和req之間的差值,ptr減去這個(gè)差值就得到了type型宿主結(jié)構(gòu)的指針req,返回類型為(type*)。
? ? 模塊編程需要注意什么?
a. 在gcc編譯選項(xiàng)中增加-c
b. 在gcc編譯選項(xiàng)中定義兩個(gè)宏:-DMODULE -D__KERENL__
或直接在源文件中定義這兩個(gè)宏:
#define MODULE
#define __KERNEL__
c. 在源文件中包括module.h文件:
#include
d. 如果要用inline功能,需要在gcc編譯選項(xiàng)中增加-O2
? ? 為什么insmod一個(gè)模塊時(shí)顯示版本不匹配?
假定你現(xiàn)在運(yùn)行的內(nèi)核的源碼目錄絕對路徑是MyKernelSrcPath,在gcc編譯時(shí)增加選項(xiàng):
-I $MyKernelSrcPath/include
? ? 為什么出現(xiàn)Unresolved Symbol?
a. 首先查看文件/proc/ksyms,看內(nèi)核有沒有輸出這個(gè)符號,不同的內(nèi)核版本如2.2和2.4輸出的符號會(huì)有些變化。
b. 如果內(nèi)核輸出的符號帶有版本控制信息如符號printk_R12345678,則性質(zhì)同問題3.2。
? ? 為什么出現(xiàn)no license錯(cuò)誤?
在源文件加入下面一行:
MODULE_LICENSE("GPL");
? ? 為什么看不到用printk打印的信息?
a. 打印消息受級別的限制,消息級別可以通過printk設(shè)置,如:
printk("something"); /* 其中0<=n<=7 */
假設(shè)控制臺(tái)的消息級別為m, 當(dāng)n 這樣一方面可以提高要打印消息本身的級別(數(shù)字越小級別越高),另一方面可以改變控制臺(tái)的消息級別(可從1到8),如改為8可用以下命令:
# echo "8" > /proc/sys/kernel/printk
b. 用dmesg命令看。
c. 當(dāng)系統(tǒng)運(yùn)行klogd和syslogd時(shí),內(nèi)核消息就會(huì)由klogd分發(fā)到syslogd,syslogd會(huì)根據(jù)配置文件/etc/syslog.conf作相應(yīng)處理,具體可以查看syslogd和syslog.conf的man頁。
? ? 怎么制作、使用patch文件?
patch文件是由diff命令生成的,使用patch文件用patch命令,具體可查看diff和patch的man頁和info。
? ? 在內(nèi)核中可以使用系統(tǒng)調(diào)用嗎?
a. 可以。內(nèi)核源代碼中就有使用系統(tǒng)調(diào)用的例子,如open()、execve()等。
b. 在內(nèi)核中使用系統(tǒng)調(diào)用必須要在源文件中包括以下兩行:
#define __KERNEL_SYSCALLS__
#include
c. 內(nèi)核中使用系統(tǒng)調(diào)用的相關(guān)定義可查看文件include/asm/unistd.h。
如果要用的系統(tǒng)調(diào)用該文件中沒有定義,可以按照其格式自行添加。
? ? 在內(nèi)核中怎么打開并操作一個(gè)文件?
a. 直接用open()、read()等系統(tǒng)調(diào)用,見問題4.2。
b. 用filp_open()函數(shù)打開文件,得到struct file *的指針fp。
使用指針fp進(jìn)行相應(yīng)操作,如讀文件可以用fp->f_ops->read。
最后用filp_close()函數(shù)關(guān)閉文件。
filp_open()、filp_close()函數(shù)在fs/open.c定義,在include/linux/fs.h中聲明。
c. 自己寫包裝函數(shù),可參照文件fs/exec.c中的open_exec()和kernel_read()函數(shù)。
在http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=363455&page=&view=&sb=&o=&vc=1上有些代碼可以參照。
? ? 在內(nèi)核中讀寫文件時(shí)為什么會(huì)出現(xiàn)EFAULT錯(cuò)誤?
a. 內(nèi)核文件系統(tǒng)提供的read()和write()之類的函數(shù),期望是對用戶態(tài)程序服務(wù)的,所以它會(huì)驗(yàn)證讀寫緩沖區(qū)不超過用戶空間的上限即0xC000 0000。但現(xiàn)在內(nèi)核中要讀寫文件,緩沖區(qū)在內(nèi)核中即地址會(huì)超過0xC000 0000。
b. 在讀寫文件前先得到當(dāng)前fs:mm_segment_t old_fs=get_fs();
并設(shè)置當(dāng)前fs為內(nèi)核fs:set_fs(KERNEL_DS);
在讀寫文件后再恢復(fù)原先fs: set_fs(old_fs);
set_fs()、get_fs()等相關(guān)宏在文件include/asm/uaccess.h中定義。
? ? 請問xx命令、xx庫的源碼是哪個(gè)文件?
a. 一個(gè)系統(tǒng)除了內(nèi)核以外,還需要有shell、gcc等一系列工具和命令以及C庫等一系列庫,這些作為應(yīng)用程序其源代碼都不在內(nèi)核中,需要另外下載相應(yīng)的源代碼。
b. 對于Redhat系統(tǒng),可以用rqm -qf命令來查找某一命令所在的軟件包,然后再找相應(yīng)的源代碼包安裝。
總結(jié)
以上是生活随笔為你收集整理的Linux内核常见FAQ的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows令牌学习
- 下一篇: Linux内核编译学习1