什麼是Symbol? 其實就是kernel中的變量(Variable Name)或函數名稱(Function Name),
這樣可以方便程序員在寫程序時可以直接參照這一份Symbol的索引文件,找到所需要的kernel信息,這一份Symbol的索引文件又稱爲kernel symbol table。
二,內核符號表(Kernel Symbol Table)?
2.1)定義:
內核符號表,就是在內核的內部函數或變量中,可供外部引用的函數和變量的符號表。
其實說白了就是一個索引文件,它存在的目的就是讓外部軟件可以知道kernel文件內部實際分配的位置。
2.2)所在文件:
編譯內核時,System.map文件用於存放內核符號表信息。
(System.map文件位於/或者/boot、/usr/src/linux/下)
2.3)文件的生成:
符號表是所有內核符號及其對應地址的一個列表,隨着每次內核的編譯,就會產生一個新的對應System.map文件,當內核運行出錯時,通過System.map中的符號表解析,就可以查到一個地址值對應的變量名。System.map文件記錄了所有代碼的運行地址(所有函數和變量)。
【內核並不使用符號名。它是通過變量或函數的地址(指針)來使用變量或函數的。其實內核連System.map文件都不使用,只是生成用於調試用的。】
2.4)system.map文件的格式:
線性地址 類型 符號
ffffffff81002590 t create_dev
ffffffff81009c00 T show_regs
其中,類型 若是小寫字母則表示局部引用, 若是大寫字母則表示全局引用(外部).
2.5)內核符號表的存在意義:
1)把內核的符號地址,轉化爲程序猿可以看懂的符號名稱。
內核符號表就是爲程序員通過符號來訪問程序體的對應地址(指針),建立了一個動態的,可變更的映射表格。
例如:
內核不會使用符號名create_dev,而會使用ffffffff81002590來引用這個變量。但程序猿們更喜歡符號名create_dev這樣直觀的名字。
所以就需要這麼一個對應關係表。這個類似於網絡裏的DNS,沒有誰願意去記那沒規律的IP地址,而記個網址就好記多了。
2)轉換之後,就可以更方便的調試內核代碼。
對於系統的oop消息、或者通過gdb的調試消息,都需要根據該對照表,將內核熟悉的函數地址轉化爲用戶熟悉的函數名稱,便於用戶進行故障定位、運行監控。
而內核本身並不真正使用System.map,而只是用於做調試用。
2.6)內核符號表存儲位置
2.6.1) System.map
磁盤中真實存在的文件,存儲內核中靜態編譯的函數和變量地址,每個新編譯內核對應一個System.map文件,當klogd輸出內核消息時,會通過/boot/System.map來將函數、變量地址轉換爲名稱,方便用戶理解。該文件對應不同的編譯內核有對應的實現文件。
2.6.2 )/proc/kallsyms
內核啓動時候創建,供oops時定位錯誤,文件大小總爲0,包含當前內核導出的、可供使用的變量或者函數;它只是內核數據的簡單表示形式。
2.7)System.map 和 /proc/kallsyms 區別
二者相似點:
都是內核函數、變量的符號表,結構一致;對於可導出的內核變量、函數,其運行時在物理內存中的位置是一樣的。
二者區別:
兩者側重點不同,
(1)System.map文件面向內核,對於內核中的沒有導出的變量或者函數名,比如kthread_create_list鏈表頭指針,也有其相應的內核地址,該文件一般是隻讀的、固定大小的,沒有動態添加模塊中的變量、函數名;
(2)而kallsyms在內核啓動過程中創建,並實時更新,反映的是系統的當前最新情況,其內部也包含內核或者是已加載模塊導出的函數、變量名稱。
所以和System.map文件有差別,kallsyms文件動態變化,大小不固定。
總結就是:
System.map文件較單純,是在用戶一開始編譯就產生的固定文件,不會因爲任何原因更改,除非被換掉。
而/proc/kallsyms是一個在啓動時由Linux kernel實時產生的文件,當系統有任何變更時,它就會馬上做出修正。
因爲這是動態的信息,當用戶新增或刪除一個module,都會自動做實時的修正(/proc下的都是這一類型的文件)
2.8)分類
Linux內核的符號表位於兩個部分。
2.8.1)首先是內核的靜態部分,也就是內核文件映像vmlinuz部分的符號表,對應於/proc/kallsyms和System.map這兩個文件。
2.8.2)還有一部分則是Linux可配置模塊部分的符號表。
2.9)形成過程
Linux內核符號表/proc/kallsyms的形成過程
(1)./scripts/kallsyms.c負責生成System.map
(2)./kernel/kallsyms.c負責生成/proc/kallsyms
(3)./scripts/kallsyms.c解析vmlinux(.tmp_vmlinux)生成kallsyms.S(.tmp_kallsyms.S),然後內核編譯過程中將kallsyms.S(內核符號表)編入內核鏡像uImage
內核啓動後./kernel/kallsyms.c解析uImage形成/proc/kallsyms
要在一個內核中啓用 kallsyms 功能,必須用進行內核配置,make menuconfig設置 CONFIG_KALLSYMS 選項爲y;如果你要在 kallsyms 中包含全部符號信息,必須設置 CONFIG_KALLSYMS_ALL 爲y。
三,導出符號表
驅動程序中,如果該驅動程序中有被其他內核代碼調用的部分,可以用EXPORT_SYMBOL導出到內核符號表中。
附:
內核符號表類型
|
||||||||||||||||||||||||||||||||||||||||||||
參考網址:
http://www.blogbus.com/wanderer-zjhit-logs/172382425.html
http://www.360doc.com/content/14/0218/09/2613145_353425431.shtml
http://blog.chinaunix.net/uid-24148050-id-95497.html
http://book.51cto.com/art/200903/117056.htm