24小时学通Linux内核之构建Linux内核
今天是臘八節,說好的女票要給我做的臘八粥就這樣泡湯了,好傷心,好心酸呀,看來代碼寫久了真的是惹人煩滴,所以告誡各位技術男敲醒警鐘,不要想我看齊,不然就只能和代碼為伴了的~~話說沒了臘八粥但還是有代碼,還有各位讀者的支持呀,所以得繼續寫下去,靜下心來,完成Linux內核的學習,堅持,加油~
到目前為止,我們已經認識了Linux內核子系統,也探究了系統的初始化過程,并且深入探索了start_kernel()函數,同樣,了解內核映像的創建也是非常重要的,接下來將討論一下內核映像的編譯和鏈接過程,那么這些當然需要工具鏈了,工具鏈包含編譯程序、匯編程序、鏈接程序,是創建Linux內核映像的一組程序集合,下圖說明了工具鏈的鏈式關系:
ELF二進制目標文件
可執行ELF目標文件包括:ELF頭,程序頭表(用于加載的節),第1節,第2節。。。。節頭表(可選)
ELF頭文件
typedef struct elf32_hdr{unsigned char e_ident[EI_NIDENT]; //標識該文件是否為ELF文件Elf32_Half e_type; //指定目標文件類型,例如可執行文件,重定位文件,共享的目標文件Elf32_Half e_machine; //被編譯文件所在系統的體系結構Elf32_Word e_version; //目標文件的版本Elf32_Addr e_entry; /* Entry point */ //程序的起始地址Elf32_Off e_phoff; //保存程序頭表在文件中的偏移量Elf32_Off e_shoff; //保存節頭表在文件中的偏移量Elf32_Word e_flags; //保存于特定與處理器的標志Elf32_Half e_ehsize; //字段保存ELF頭的大小Elf32_Half e_phentsize; //保存程序頭表中的每一項的大小Elf32_Half e_phnum; //程序頭中表項的個數Elf32_Half e_shentsize; //節頭表中每一項的大小Elf32_Half e_shnum; //保存節頭中項的數量,表明該文件中有多少節Elf32_Half e_shstrndx; //保存節頭中節字符串的索引 } Elf32_Ehdr;節頭表
typedef struct elf32_shdr {Elf32_Word sh_name; //包含節名Elf32_Word sh_type; //包含節的內容Elf32_Word sh_flags; //各種屬性的內容Elf32_Addr sh_addr; //節在內存映像中的地址 Elf32_Off sh_offset; //保存ELF文件中這一節中初始字節的偏移量Elf32_Word sh_size; //包含節的大小Elf32_Word sh_link; //表鏈接的索引Elf32_Word sh_info; //包含附加信息Elf32_Word sh_addralign; //包含地址對其的約束Elf32_Word sh_entsize; //節中每項的大小 } Elf32_Shdr;非可執行ELF文件節
| 節點 | 說明 |
| .data | 已初始化的數據 |
| bss | 為初始化的數據 |
| .hash | 符號散列表 |
| .init | 初始化代碼 |
| .symtab? | 符號表 |
| .text ? | 可執行的指令 |
| .plt ? | 過程鏈接表 |
| .rodata? | 只讀數據 |
| dynamic | 動態鏈接信息 |
?
?
?
?
?
?
?
?
?
?
程序頭表
typedef struct elf64_phdr {Elf64_Word p_type; //描述該段的類型Elf64_Word p_flags; //以p_type而定Elf64_Off p_offset; //<span style="font-family: Arial, Helvetica, sans-serif;">該段的開始相對于文件開始的偏移量</span>Elf64_Addr p_vaddr; //段虛擬地址Elf64_Addr p_paddr; //段的虛擬地址 Elf64_Xword p_filesz; //文件映像中該段的字節數Elf64_Xword p_memsz; //內存映像中該段的字節數Elf64_Xword p_align; //描述要對齊的段在內存中如何對齊,該值是2的整數次冪}?Elf64_Phdr;?
通過這些信息,系統函數exec()和鏈接程序合作,為可執行程序在內存中創建進程映像,該過程如下:
- 將可執行文件的段加入內存
- 加載所有需要的共享庫
- 需要時重定向可執行文件及其共享對象
- 將控制權交給程序
那么內核是如何被編譯成二進制文件的呢,又是如何在執行前裝入內存。下面將開始介紹編譯內核源代碼。內存啟動始于執行arch/x86/boot/目錄中的實模式匯編代碼。查看arch/x86/kernel/setup_32.c文件可以看出保護模式的內核怎樣獲取實模式內核收集的信息。第一條信息來自于init/main.c中的代碼,深入挖掘init/calibrate.c可以對BogoMIPS校準理解得更清楚,而include/asm-your-arch/bugs.h則包含體系架構相關的檢查。
內核中的時間服務由駐留于arch/your-arch/kernel/中的體系架構相關的部分和實現于kernel/timer.c中的通用部分組成。從include/linux/time*.h頭文件中可以獲取相關的定義。
jiffies定義于linux/jiffies.h文件中。HZ的值與處理器相關,可以從include/asm-your-arch/ param.h找到,內存管理源代碼存放在頂層mm/目錄中。
Linux的官方源代碼發布網址是www.kernel.org。其源代碼目錄結構示意圖如下:
利用內核配置工具自動生成.config的內核配置文件,這是編譯的第一步,.config文件位于源代碼目錄下,其選項的位置根據它們在內核配置工具中的位置進行排序,我們來看看一個.config文件的節選:
1 #2 # Automatically generated make config: don't edit3 #4 CONFIG_X86=y5 CONFIG_MMU=y6 CONFIG_UID16=y7 CONFIG_GENERIC_ISA_DMA=y //這4行位于頂層菜單中 8 9 # 10 # Code maturity level options 11 # 12 CONFIG_EXPERIMENTAL=y 13 CONFIG_CLEAN_COMPILE= 14 CONFIG_STANDALONE=y 15 CONFIG_BROKEN_ON_SMP=y //這4行位于代碼成熟度選項菜單中 16 17 # 18 # General setup 19 # 20 CONFIG_SWAP=y 21 CONFIG_SYSVIPC=y 22 #CONFIG_POSIX_MQUEUE is not set 23 CONFIG_BSD_PROCESS_ACCT=y //這4行位于通用設置選項菜單中
最后來粗略的介紹一下Linux內核的Makefile文件,也只能簡單的介紹一下啦,這個可是重難點,這里我稍微說一下,以后會具體去學習。Linux內核是一種單體內核,但是通過動態加載模塊的方式,使它的開發非常靈活 方便。那么,它是如何編譯內核的呢?我們可以通過分析它的Makefile入手。以下是 一個簡單的hello內核模塊的Makefile.?
ifneq ($(KERNELRELEASE),)obj-m:=hello.o
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
??????? $(MAKE) -C $(KERNELDIR)? M=$(PWD) modules
clean:
??????? rm -rf *.o *.mod.c *.mod.o *.ko
endif
首先,由于make 后面沒有目標,所以make會在Makefile中的第一個不是以.開頭的目標作為默認的目標執行。于是default成為make的目標。make會執行 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules shell是make內部的函數,make執行了兩次。
第一次執行時是讀hello模塊的源代碼所在目錄/home/s tudy/prog/mod/hello/下的Makefile。
第二次執行時是執行/usr/src/linux/下的Makefile時.?
這其中很復雜,我也不知道怎么講了。關于make modules的更詳細的過程可以在scripts/Makefile.modpost文件的注釋 中找到。不過我找到了一個大牛寫的跟我一下學Makefile的博客,我把博客地址附在下面,供大家參考一下:http://blog.csdn.net/haoel/article/details/2886/
?
小結
本章探究了目標文件的編譯,鏈接過程,以及目標文件的結構,以便理解可執行代碼的最終形式,構建Linux內核涵蓋了內核編譯所需要的工具,最后還簡單的描述了Makefile,,這些都是難點,,得多加縮習啦,,盡管今天沒吃到臘八粥,但是轉轉鍋還是很給力的,吃到現在還不餓,是一個難忘的一天 ~~
?
版權所有,轉載請注明轉載地址:http://www.cnblogs.com/lihuidashen/p/4253752.html
轉載于:https://www.cnblogs.com/lihuidashen/p/4253752.html
總結
以上是生活随笔為你收集整理的24小时学通Linux内核之构建Linux内核的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 女人洒脱大气的句子 关于女人要活得潇洒的
- 下一篇: 王者荣耀古风游戏网名107个