歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

讀核日記(一)

今天開始我的讀核罹難記.第一次讀內核,整整上學時的考試前.胡裡胡塗的就過去了,沒甚收獲.這次我發誓要徹底讀一次. 面對近50 m 的源碼,困惑是難免的所以我決定先從大面上把握,再在某一些具體的點上切入.這樣一來linux 的啟動過程便十分重要,因此我先用dmesg命

今天開始我的讀核罹難記.第一次讀內核,整整上學時的考試前.胡裡胡塗的就過去了,沒甚收獲.這次我發誓要徹底讀一次.

面對近50 m 的源碼,困惑是難免的所以我決定先從大面上把握,再在某一些具體的點上切入.這樣一來linux 的啟動過程便十分重要,因此我先用dmesg命令察看一下linux啟動時打出的消息.(我想源文件應在/usr/src/linux/init/main.c中)

內核的啟動最後是到 start_kernel ( in /init/main.c )也就是說啟動的過程是從 head.S ( arch/i386/boot/ ) 一直運行到 main.c(start_kernel) .它的作用是完成開機後的設置與內核的初始化,然後,系統究竟入一個無限的循環中等待用戶的輸入,調用fork來產生子進程.從而達到交互式操作系統的設計要求.

第一部分 : 內核初始化以及啟動.

.啟動系統.當PC機加電開始啟動時,80X86的處理器(CPU)在實模式下自檢,開始執行物理地址0xFFFF0即ROM-BIOS的起始地址處的代碼。PC機的BIOS進行系統自檢,初始化中斷向量表到物理地址0x0。然後把引導設備的第一個扇區加載到地址0x7C00,執行此處的指令。到這裡與linux無關,x86系列的硬件設置如此.

linux的內核本身是不能自舉的,所以lilo和loadlin的作用就是加載系統內核.有關lilo的原理可以參考lilo的readme.從加電到內核加載的過程是:加電->執行BIOS->加載第一扇區->lilo->加載內核

Linux內核的最初部分代碼是用匯編語言寫的(文件是boot/bootsect.s)。(我的匯編水平有限,暫且不看),它首先把自身這部分代碼移到絕對地址0x90000,把下面的2K代碼從引導設備加載到地址0x90200上,內核的其余部分加載到地址0x10000處。在加載系統時顯示“loading...”. 然後,程序控制權交給另一個實模式匯編程序(boot/Setup.S)。接下來,此程序把整個系統從地址0x10000移到地址0x1000,進入保護模式。程序控制轉給系統的其余部分即地址0x1000。

下一個步驟是系統內核的解壓過程,這部分代碼在地址0x1000(文件/Boot/head.S),該段程序初始化寄存器,然後執行decompress_kernel(),這個函數源於zBoot/inflate.c、zBoot/unzip.c和zBoot/misc.c三個文件

Loading ....[ bootsect.S ]

uncompress .....[ decompress_kernel() ]

main.c ---> start_kernel() 開始.

開始 printk(banner);

Linux version 2.2.6 (root@lance) (gcc version 2.7.2.3) (檢查一下GCC 的版本號, 在/init/main.c 中如果gcc 的版本號不夠,時不允許編譯內核的)

#40 Sun Apr 18 17:44:20 CST 1999

調用init_time()打印出以下內容:

Detected 199908264 Hz processor.

然後運行 console_init() --> drivers/char/tty_io.c */

Console: colour VGA+ 80x25

運行一個循環,測量一下 MIPS – 據說是要用一個確定的機器指令周期來實現實時的延遲.

Calibrating delay loop... 199.48 BogoMIPS

初始化內存/* init_mem */

Memory: 63396k/65536k available (848k kernel code, 408k reserved, 856k data

, 28k

/** dquote_init() **/

VFS: Diskquotas version dquot_6.4.0 initialized

察看cpu 的類型(在2.2.14 以後聽說增加了對多種cpu 的支持, 以後我可得用心看看,if I can find a bug of intel then ……)

CPU: Intel Pentium Pro stepping 09

初始或處理器與協處理器,對於比較老的處理器, linux 會用軟件模擬協處理器?

Checking 386/387 coupling... OK, FPU using exception 16 error reporting.

檢查治理的合法性

Checking 'hlt' instruction... OK.

POSIX conformance testing by UNIFIX

此後調用 linux_thread(init ,..,..,)(arch/i386/kernel/process.c)

創建一個運行 init 的進程.

進入了第二階段用戶模式 ( user_mode )End of start_kerne最後進入cpu_idle ( arch/i386/kernel/process.c )

第二部分 設備的初始化

對設備的初始化調用. init()--->do_basic_init()--+

pci_init() 對pci 設備的初始化( 在main.c文件中有這樣一段 ifdef PCI …..需要看一下)下面打印出結果:

PCI: PCI BIOS revision 2.10 entry at 0xfd8d1

PCI: Using configuration type 1

PCI: Probing PCI hardware

對Socket的初始化,socket_init() (這裡也許就是linux 的網絡秘密所在吧,以後我的注意) -Linux NET4.0 for Linux 2.2

Based upon Swansea University Computer Society NET3.039

NET4: Unix domain sockets 1.0 for Linux NET4.0.

NET4: Linux TCP/IP 1.0 for NET4.0

IP Protocols: ICMP, UDP, TCP

Starting kswapd v 1.5 kswapd_setup()

調用 device_setup()

Detected PS/2 Mouse Port.

初始化 聲卡

Sound initialization started

Sound initialization complete

初始化 軟驅

Floppy drive(s): fd0 is 1.44M

FDC 0 is a National Semiconductor PC87306

SCSI 設備的初始化

(scsi0) <Adaptec AIC-7880 Ultra SCSI host adapter> found at PCI 13/0

(scsi0) Wide Channel, SCSI ID=7, 16/255 SCBs

(scsi0) Downloading sequencer code... 419 instructions downloaded

scsi0 : Adaptec AHA274x/284x/294x (EISA/VLB/PCI-Fast SCSI) 5.1.10/3.2.4

<Adaptec AIC-7880 Ultra SCSI host adapter>

scsi : 1 host.

Vendor: SEAGATE Model: ST32155W Rev: 0596

ype: Direct-Access ANSI SCSI revision: 02

Detected scsi disk sda at scsi0, channel 0, id 0, lun 0

Vendor: SEAGATE Model: ST32155W Rev: 0596

Type: Direct-Access ANSI SCSI revision: 02

Detected scsi disk sdb at scsi0, channel 0, id 1, lun 0

scsi : detected 2 SCSI disks total.

(scsi0:0:0:0) Synchronous at 40.0 Mbyte/sec, offset 8.

SCSI device sda: hdwr sector= 512 bytes. Sectors= 4197405 [2049 MB] [2.0 GB ](scsi0:0:1:0) Synchronous at 40.0 Mbyte/sec, offset 8.

SCSI device sdb: hdwr sector= 512 bytes. Sectors= 4197405 [2049 MB] [2.0 GB]Partition check: sda: sda1 |

sdb: sdb1 sdb2 < sdb5 sdb6 > |

安裝 文件系統 filesystem_setup()

安裝設備驅動程序 mount_root()

VFS: Mounted root (ext2 filesystem) readonly.

Freeing unused kernel memory: 28k freed

Adding Swap: 66540k swap-space (priority -1)

Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996

SB 3.01 detected OK (220)

<ESS ES1688 AudioDrive (rev 11) (3.01)> at 0x220 irq 5 dma 1

YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1

996<Yamaha OPL3> at 0x388

NET4: AppleTalk 0.18 for Linux NET4.0

eth0: Intel EtherExpress Pro 10/100 at 0xf800, 00:A0:C9:49:2F:FF, IRQ 9.

Board assembly 645520-034, Physical connectors present: RJ45

Primary interface chip DP83840 PHY #1.

DP83840 specific setup, setting register 23 to 8462.

General self-test: passed.

Serial sub-system self-test: passed.

Internal registers self-test: passed.

ROM checksum self-test: passed (0x49caa8d6).

Receiver lock-up workaround activated.

NET4: AppleTalk 0.18 for Linux NET4.0

結束 do_basic_setup()

open("/dev/console", O_RDWR, 0)

開始執行 /sbin/init ( execv(...) )

內核就此啟動完畢...

這樣一來系統在啟動時需要的文件一目了然了.要讀啟動這方面的源碼,大概也就可以這樣行動即:

Boot/head.S

decompress_kernel(),然後按照個功能塊來讀取相應的函數.

其實對於整個kernel 來說,還應該解讀一下makefile ,說實話在編程來講我是很愛寫 makefile ,然而解讀內核,她就是工作十分難以進行.好在有了souce insight 可以讓我們輕松的找到,函數和常量的定義, 方便不少.

打開main.c (其實我是將2.2.14解到了windows 下).發現有n 個函數與2n 個常量的定義,只有幾個 init 函數在.對於其他的外部函數也定義了不少.這裡卻沒有主函數—我現在懷疑linux 程序是否和vc 一樣不知道從哪裡開始進行:__).不過馬上明白了, 整個內核事變在一塊的. 還包括.存儲管理, 處理機管理, 內存管理等許多模塊, 她該不會啟動以後就沒有時刻干了吧

好了, 一口吃不成胖子.我還是先從啟動讀起.不過我開始對是否要加中文祝時產生懷疑, 寫那些代碼的本身都是高手, 他們應知道怎樣是最好的注釋. 難道讀代碼的人連這點e 文也看不了?

Copyright © Linux教程網 All Rights Reserved