歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> Linux文化 >> Linux的啟動和核心介紹

Linux的啟動和核心介紹

日期:2017/2/27 12:20:40   编辑:Linux文化

前幾天大家對Linux的啟動有些討論。
於是整理了一下前段時間與他人交流的提綱,希望起到拋磚引玉的作用。
[email protected]
這是一次對Linux介紹後的整理。
對象是一些剛對Linux核心感興趣,並且准備進一步研究和改造的同志。
因為是由提綱整理而成,有些亂,見諒!
 
四部分內容:
一、Linux核心源碼結構介紹
二、編譯和配置的過程
三、系統啟動順序的相關文件
四、核心改造的一些經驗
一、
當我們安裝好一個Linux系統,通常核心源碼存放在/usr/src/linux/目錄。
下面先看看這目錄下的各個子目錄及文件。
[/]#cd /usr/src/linux
[linux]#ls -aF
./ MAINTAINERS drivers/ kernel/ scripts/
../ Makefile fs/ lib/
COPYING README include/ mm/
CREDITS Rules.make init/ modules/
Documentation/ arch/ ipc/ net/
下面我們逐一描述:
COPYING
## GPL版權申明,看後你至少應該知道,你對具有GPL版權的源代碼改動而
形成的程序,或使用GPL工具產生的程序,具有使用GPL發表的義務。其中之一就是
公開源代碼。
CREDITS
## 光榮榜,你應當感謝的一些人的信息,其中的每一個人都對Linux做出過
很大貢獻。
Documentation/
## 文檔目錄,可有選擇地看一下你感興趣的部分
MAINTAINERS
## 維護人員列表,對當前版本的內核各部分都有誰負責,如果你研究的
夠深入,可以與他們討論
Makefile
## 如果你在UNIX編譯過程序,可以看明白
README
## Linus 所寫,核心及其編譯配置方法簡單介紹
Rules.make
## make時使用的一些共同規則
arch/
## architecture(體系結構)我關心的i386啟動過程在其中,
## 包括Linux在多種平台下的實現。如果要移植系統到一個新的
##CPU環境中,這就是你要關心的目錄
drivers/
## 驅動程序目錄,包含大量設備驅動的實現,按類別分子目錄
fs/
## 文件系統,實現了當前流行的幾乎所有文件系統。Cool
include/
## 嵌入文件目錄
init/
## 初始化文件,包含main.c和version.c兩個文件。Initialize
ipc/
## ipc的實現,與SYS V兼容
kernel/
## 最核心代碼,調度,中斷,信號等的處理
lib/
## 一些工具。
Mm/
## 內存管理,Memory Manager,虛擬頁、緩沖的實現。
Modules/
## 模塊文件目錄,用於存放編譯時產生的模塊目標文件(參考編譯過程)
net/
## 網絡實現,包括TCP/IP在內的大量網絡協議的實現。
Scripts/
## 描述文件,腳本,用於對核心的配置。
 
二、
構造內核
常用命令包括:
make config, dep, clean, mrproper, zImage, bzImage, modules, modules_install

(1) make config
核心配置,調用./scripts/Configure 按照arch/i386/config.in 來進行
配置。
命令執行完後產生文件.config,其中保存著配置信息。
下一次再做make config將產生新的.config文件,原.config被改名為.config.old
(2)make dep
尋找依存關系。
產生兩個文件.depend和.hdepend
其中.hdepend表示每個.h文件都包含其它哪些嵌入文件。
而.depend 文件有多個,在每個會產生目標文件(.o)文件的目錄下均有,
它表示每個目標文件都依賴哪些嵌入文件(.h)。
 
(3)make clean
清出以前構核所產生的所有目標文件、模塊文件、核心以及一些臨時文件等,
不產生任何文件
 
(4)make rmproper
刪除所有因構核過程中產生的所有文件,及除了做make clean外,還要
刪除.config,.depend等文件,把核心源碼恢復到最原始的狀態。
下次構核時就必須重新配置了。
 
(5)make, make zImage, make bzImage
make:
構核。通過各目錄的Makefile文件進行。
會在各個目錄下產生一大堆目標文件,若核心代碼沒有錯誤,將
產生文件vmlinux,這就是所構的核心。並產生映射文件System.map
通過各目錄的Makefile文件進行。
.version 文件中的數加1,表示版本號(又產生一個新的版本了),讓你
明白,你已經對核心改動過多少次了。
Make zImage:
在make的基礎上產生壓縮的核心映象文件./arch/$(ARCH)/boot/zImage
以及在./arch/$(ARCH)/boot/compresed/目錄下產生一些臨時文件。
Make bzImage:
在make 的基礎上產生壓縮比例更大的核心映象文件
./arch/$(ARCH)/boot/bzImage
以及在./arch/$(ARCH)/boot/compresed/目錄下產生一些臨時文件。
在核心太大時進行。
(6)make modules
編譯模塊文件,你在make config時所配置的所有模塊將在這時編譯,
形成模塊目標文件,並把這些目標文件存放在modules目錄中。
使用如下命令看一看。
Ls modules
(7)make modules_install
把上面編譯好的模塊目標文件目錄/lib/modules/$KERNEL_VERSION/ 中。
比如我的版本是2.0.36,做完這個操作後可使用下面的命令看看:
ls /lib/modules/2.0.36/
 
相關的命令還有很多,有興趣可看相關資料和Makefile文件。
另外注意,這兒我們產生了一些隱含文件
.config
.oldconfig
.depend
.hdepend
.version
它們的意義應該很清楚了。
三、
系統的啟動順序及相關文件
仍在核心源碼目錄下,看以下幾個文件
./arch/$ARCH/boot/bootsect.s
./arch/$ARCH/boot/setup.s
./init/main.c
 
bootsect.S 及 setup.S
 這個程序是linux kernel的第一個程序,包括了linux自己的bootstrap程序,
但是在說明這個程序前,必須先說明一般IBM PC開機時的動作(此處的開機是指
"打開PC的電源"):
  一般PC在電源一開時,是由內存中地址FFFF:0000開始執行(這個地址一定
在ROM BIOS中,ROM BIOS一般是在FEOOOh到FFFFFh中),而此處的內容則是一個
jump指令,jump到另一個位於ROM BIOS中的位置,開始執行一系列的動作,包
括了檢查RAM,keyboard,顯示器,軟硬磁盤等等,這些動作是由系統測試代碼
(system test code)來執行的,隨著制作BIOS廠商的不同而會有些許差異,但都
是大同小異,讀者可自行觀察自家機器開機時,螢幕上所顯示的檢查訊息。
  緊接著系統測試碼之後,控制權會轉移給ROM中的啟動程序
(ROM bootstrap routine),這個程序會將磁盤上的第零軌第零扇區讀入
內存中(這就是一般所謂的boot sector,如果你曾接觸過電腦病
毒,就大概聽過它的大名),至於被讀到內存的哪裡呢? --絕對
位置07C0:0000(即07C00h處),這是IBM系列PC的特性。而位在linux開機
磁盤的boot sector上的正是linux的bootsect程序,也就是說,bootsect是
第一個被讀入內存中並執行的程序。現在,我們可以開始來
看看到底bootsect做了什麼。
第一步
 首先,bootsect將它"自己"從被ROM BIOS載入的絕對地址0x7C00處搬到
0x90000處,然後利用一個jmpi(jump indirectly)的指令,跳到新位置的
jmpi的下一行去執行,
第二步
 接著,將其他segment registers包括DS,ES,SS都指向0x9000這個位置,
與CS看齊。另外將SP及DX指向一任意位移地址( offset ),這個地址等一下
會用來存放磁盤參數表(disk para- meter table )
第三步
 接著利用BIOS中斷服務int 13h的第0號功能,重置磁盤控制器,使得剛才
的設定發揮功能。
 
第四步
 完成重置磁盤控制器之後,bootsect就從磁盤上讀入緊鄰著bootsect的setup
程序,也就是setup.S,此讀入動作是利用BIOS中斷服務int 13h的第2號功能。
Setup的image將會讀入至程序所指定的內存絕對地址0x90200處,也就是在內存
中緊鄰著bootsect 所在的位置。待setup的image讀入內存後,利用BIOS中斷服
務int 13h的第8號功能讀取目前磁盤的參數。
第五步
 再來,就要讀入真正linux的kernel了,也就是你可以在linux的根目錄下看
到的"vmlinuz" 。在讀入前,將會先呼叫BIOS中斷服務int 10h 的第3號功能,
讀取游標位置,之後再呼叫BIOS 中斷服務int 10h的第13h號功能,在螢幕上輸
出字串"Loading",這個字串在boot linux時都會首先被看到,相信大家應該覺
得很眼熟吧。
第六步
 接下來做的事是檢查root device,之後就仿照一開始的方法,利用indirect
jump 跳至剛剛已讀入的setup部份
比較
  把大家所熟知的MS DOS 與linux的開機部份做個粗淺的比較,MS DOS 由位於
磁盤上boot sector的boot程序負責把IO.SYS載入內存中,而IO.SYS則負有把DOS
的kernel --MSDOS.SYS載入內存的重責大任。而linux則是由位於boot sector 的
bootsect程序負責把setup及linux的kernel載入內存中,再將控制權交給setup。
##這幾步內容主要參照一個台灣同胞寫的文檔,setup.s的內容希望有人補充。
 
 
Start_kernel()
當核心被載入後,首先進入的函數就是start_kernel。
./init/main.c 中函數start_kernel包含核心的啟動過程及順序。
通過它來看核心整個初始化過程。
首先進行一系列初始化,包括:
trap_init(); ##./arch/i386/kernel/traps.c 陷入
init_IRQ(); ##./arch/i386/kernel/irq.c setup IRQ
sched_init(); ##./kernel/sched.c 調度初始化,並初始化bottom_half
time_init(); ##./arch/i386/kernel/time.c
init_modules(); ##模塊初始化
mem_init(memory_start,memory_end);
buffer_init(); ## ./fs/buffer.c 緩沖區
sock_init(); ## ./net/socket.c socket初始化,並初始化各協議(TCP等)
ipc_init();
sysctl_init();
然後通過調用kernelthread()產生init進程,全權交由init進程處理。調用cpu_idle(N
ULL)休息。
感興趣又有時間的同志可以寫一個startkernel()函數的詳細分析報告。
 
 
 
下面看一看init進程的工作:
首先創建進程
bdflush ##./fs/buffer.c 緩沖區管理
和kswapd ##./mm/vmscan.c 虛擬內存管理
這兩個進程非常重要
系統初始化(系統調用setup)
系統初始化包含設備初始化及各文件系統初始化。
Sys_setup (./fs/filesystems.c)
|
|-device_setup
| |
| -- chr_dev_init(); ##字符設備
| blk_dev_init(); ##塊設備
| scsi_dev_init(); ##SCSI
| net_dev_init(); ##網絡設備
| console_map_init(); ##控制台
|-binfmt_setup();
|-init_nls() ##各文件系統初始化
|-init_ext_fs()
|-init_ext2_fs()
. .
. .
. .
|-init_autofs_fs()
--mount_root() ##mount root fs
##從這兒看看設備及文件的初始化順序,加入我們的設備時就有了大局觀。
執行/etc/rc ( rc.sysinit, rc.local, rc.# ) 和
執行/bin/sh
______________________________________________________
END
 

--
※ 來源:·BBS 水木清華站 bbs.net.tsinghua.edu.cn·[FROM: 162.105.17.237]


——摘自:北京Linux俱樂部


Copyright © Linux教程網 All Rights Reserved