1. 程式人生 > >Linux kernel 分析之一:核心映象

Linux kernel 分析之一:核心映象

跌跌撞撞的在軟體開發行業這麼久了,各種語言也都見識過了各種平臺也都差不多見識了一下,但都瞭解不夠深入,唯獨對Linux核心知之甚少,想想今天開始學習還來得及,所以Just do it....

讀核心原始碼是一件很有意思的事。它像一條線,把作業系統,編譯原理,C語言,資料結構與演算法,計算機體系結構等等計算機的基礎課程串起來。

好,讓我們開始Linux核心之旅。
      我們的出發點是在CPU加電的一剎那,系統處於16位實地址模式下,終點是核心開始執行start_kernel(),系統處於32位頁式定址的保護模式下。那時核心映象bzImage已經解壓完畢,運行於核心態。系統中已經有了一個叫swapper的0號程序,有自己的核心堆疊,情況就相對好理解得多。(儘管與使用者態程式相比,還要多操心不少事,包括對硬體的直接操作,核心態各種資料結構的初始化,對頁表的操作等等)。
不過,不妨先做些準備動作。

   首先,什麼是核心?
  目前,只知道編譯核心後,產生一個叫bzImage的壓縮核心映象。它不同於任何普通的可執行程式。我們甚至不知道它從哪裡開始執行。只知道把它往/boot/下一放,往boot loader的配置檔案(例如grub的menu.lst)中寫上相關資訊,機子就順利啟動了。因此,我對它的生成過程產生了濃厚興趣。於是,我查看了相關資料,最直接的資料來自於arch/i386/boot/下的Makefile。

     從Makefile中可以知道。bzImage的產生過程是這樣的:
    從arch/i386/boot/Makefile和arch/i386/boot/compressed/Makefile中可以看出(具體過程省略,)
    1.先生成vmlinux.這是一個elf可執行檔案
    2.然後objcopy成arch/i386/boot/compressed/vmlinux.bin,去掉了原elf檔案中的一些無用的section等資訊。
    3.gzip後壓縮為arch/i386/boot/compressed/vmlinux.bin.gz
    4.把壓縮檔案作為資料段連結成arch/i386/boot/compressed/piggy.o

    5.連結:arch/i386/boot/compressed/vmlinux = head.o+misc.o+piggy.o其中head.o和misc.o是用來解壓縮的。
     6.objcopy成arch/i386/boot/vmlinux.bin,去掉了原elf檔案中的一些無用的section等資訊。
     7.用arch/i386/boot/tools/build.c工具拼接bzImage = bootsect+setup+vmlinux.bin
    過程好複雜。
    這裡要介紹一下objcopy命令,它的作用是把一個object檔案轉化為另一種格式的檔案。在這裡,objcopy的作用就是去掉原來elf檔案中的elf header和一些無用的
section資訊。為什麼要這麼做呢?因為elf檔案中的elf header和一些section的作用是告訴elf loader如何載入elf可執行檔案。但是,linux核心作為一種特殊的elf檔案,需要特殊折輔助程式去裝載它。往往它的裝載地址是固定的。這時,為了保證通用性而存在的elf header和一些section對核心的裝載就沒有意義了。加上為了使核心儘可能小,所以乾脆把這些資訊去掉。
我們可以看一下vmlinux和arch/i386/boot/compressed/vmlinux。用file命令檢視,它們也是elf可執行檔案。只是沒有main函式而已參考:
Documentation/kbuild/makefiles.txtDocumentation/kbuild/modules.txt