Linux Kernel 2:使用者空間的初始化

來源:互聯網
上載者:User
上篇我們知道,kernel初始化後將啟動init進程,那麼這個進程將幹些什麼呢?除此之外,kernel還需要做些什麼事情呢?(想想檔案系統、根存放裝置是在什麼時候初始化的呢?)先從檔案系統初始化說起。以前一直不明白,有了kernel為何還需要一個檔案系統?經過反覆琢磨,明白一個道理,kernel載入到記憶體後,kernel運行起來是沒有問題的,但是如果沒有Root FS,就好像PC上沒有硬碟.....。另外,Linux中很多虛擬檔案系統(proc,sys,dev等)都是掛靠在RootFS中的,所以RootFS在Linux中更加關鍵(必要條件簡直就是)。(kernel中的FS是另外一個龐大的部分)一 根檔案系統1 FHS:File system Hierachy Standard:Linux上檔案系統布局的標準,例如 usr目錄大概是幹嗎的,tmp目錄大概是幹嘛的。有空可以瞧瞧....其實使用LINUX OS多了,自然就理解了。2 常用的檔案夾布局:其實就是ES上普遍的檔案目錄:
  • bin;dev;etc;home;lib;sbin;tmp;usr;var;
二 Post Boot這裡講的是execve init之前的事情,因為源碼中:
  • run_init_process("/usr/bin/init"):這個時候已經有FS的布局了,也就是init程式本身必須放在一個FS中。
三 initinit進程很重要,不過android上的init進程的工作流程比較簡單。這裡介紹非Android上的init。一般它讀取的設定檔是/etc/inittab中(ubuntu上似乎沒有這個檔案了,以後得找個FCore的系統看看)。另外,這裡還有一個叫run level的概念。見圖1.
圖1 run level

Run level說白了就是將系統運行狀態分成幾個層級,例如shutdown的時候init需要執行一些操作,reboot的時候需要執行一些操作。這裡關於Init的東西就不介紹了,很多關於linux系統配置的知識都有涉及。(確實比android的init要複雜多了) 四 Initial RAM DiskLK在早期初始化的過程中,需要mount一個FS,目前有新舊兩種方法:
  • old方法就是使用initial ram disk,也叫initrd
  • new方法就是使用iniramfs
這兩個東西非常常見,咱們要好好研究下。4.1 initrd這個功能需要配置kernel的編譯選項。
ARM支援將前面的initrd和vmlinux打包到一個image中。實際上只有ARM架構支援。(核心編譯的時候要選擇這一項)。講了這麼多,那麼到底怎麼用呢?
  • initrd也是一個image。由bootloader啟動的時候,或者bootloader下載到某個地方
  • bootloader把initrd的地址告訴核心。核心啟動時候把這個image解壓並掛載
  • 另外一種辦法,編譯的時候將initrd和kernel放到一個image中,這種方法只有ARM架構支援。使用這種辦法話,建議用initramfs。注意,android中使用的就是一個kernel+initramfs的單一image。也就是第二種辦法
(這裡有很多細節問題,以後我們分析源碼再來搞懂它)BL啟動核心的時候,需要給LK傳遞參數,即告訴LK這個initrd在什麼位置...很簡單不是?KL如何使用這個initrd呢?
  • KL先根據參數指定的initrd地址,將這個image拷貝到記憶體中,然後解壓,並掛載為/
  • 找到這個disk中的linuxrc檔案,然後執行裡邊的語句《====這給了我們定製化自己ES的好計劃
  • 處理完linuxrc後,KL unmount這個initrd,並載入真正的root device(看到沒,這個initrd就是做些初始化的工作,但是你也可以不umount這個initrd。)這裡的處理稍有差異。如果BL在參數中指明root=/dev/ram0,(代碼中可見到這些語句),那麼KL就不會執行linuxrc,並且也不會umount initrd。也就是這個initrd就是最終的根檔案系統了。
那麼如何製作這個Initrd呢?其實就是一個gzip打包的檔案夾....(這部分代碼在do_mounts.c中的prepare_namespace函數中)4.2 initramfs(詳細說明:參考kernel/documentations/filesystems/ramfs-rootfs-initramfs.txt)kernel預設支援這個initramfs,所以編譯的時候,會整一個default的initramfs放到核心中。initramfs是一個cpio的打包檔案。我特意查了下cpio的info。一般用法就是:讀取一個目錄下所有檔案的資訊及其所有檔案的內容(可能是直接read資料到一個buffer中),然後把這些資訊寫到一個檔案中。說白了,可能就是一個序列化的工具。然後LK用同樣的方法就可以還原序列化,恢複原來目錄中的內容了。前面說,LK編譯的時候預設會有一個簡單的initramfs目錄結構。這個結構由kernel/scripts/gen_initramfs_list.sh指令碼產生。這個指令碼很簡單:dir /dev 0755 0 0 nod /dev/console/ 0600 0 0 c 5 1dir /root 0700 0 0

執行的時候,前面加上mk...就產生一個目錄了,然後用cpio打包,產生iniramfs,最後由LK解包並掛載(具體內容,參考ramfs-rootfs-initramfs.txt)如何製作自己的initramfs呢?
  • 搞一個檔案夾吧,可仿照PC機器上linux的檔案結構。也可以把busybox放上去。
  • find testramfs -depth -print | cpio -ov > testramfs.cpio  cpio的輸入是檔案名稱,輸出通過>定向到testramfs.cpio。大家可以試試。
  • 解壓的話,cpio -ivd < testramfs.cpio。這樣就能還原testramfs檔案夾中的內容了。
cpio:-o表示output,-v表示列印一些verbose資訊,-i表示input,-d表示建立整個檔案夾結構。沒有-d的話,會出問題。不過有了kernel編譯的支援,我們不用自己調用cpio了,在編譯選項中有一個INITRAMFS_SOURCE,把它指向目標檔案夾,編譯的時候自然會產生這個initramfs了。參考文獻:這些參考文獻中,最重要的是最後一個,ols2k-9.ps,下載並處理後得到一個pdf,實際上一篇論文。主要介紹了Linux啟動的一些問題。再三解釋一下,為什麼需要init ram disk。FS一般安裝在儲存介質上,而讀取這些儲存介質需要驅動。核心啟動的時候如果把這些驅動都載入的話,會非常麻煩,即使你把驅動靜態編譯到核心中,也不是一個完美的解決辦法。所以。先整一個簡單的,基於記憶體的FS,這樣初始化工作都可以順利進行。最後,等驅動都載入完後,再把實際儲存上的FS掛載上來。這裡要明白一點,沒有一個FS的話,LK是沒法正常工作的。 五 U-Boot全名為Das U-Boot,是一個使用非常廣泛的Bootloader。以後會專門撰文介紹UB。這裡簡單說兩個點:
  • UB的代碼結構,先從CPU的start.S開始,這裡會根據不同的CPU進行初始化,大部分代碼都不需要我們修改
  • 再是Board的啟動,這個和具體的板子有關。現在改名叫lowlevel_init.S了。
(最難的部分在於各個裝置的初始化了,需要結合開發板的datasheet來做)這裡列出以下參考書:
其中,關於SDRAM.pdf,網址已經移到了:http://www.maxwell.com/products/microelectronics/docs/INTRO_TO_SDRAM.PDF各位看官可以下載看看。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.