根文件系統構建和實驗過程


一、一、根文件系統構建路線linux

一、先逐步構建文件夾形式的根文件系統而後在製做燒錄鏡像shell



二、一、busybox移植實戰windows

一、busybox中是一些shell命令集bash

二、busybox×××服務器

(1)busybox是一個開源代碼,能夠在網上下載架構

(2)busybox的版本新舊無所謂,隨便下載一個,busybox安裝在咱們建立的那個根文件系統文件夾形式的目錄下,先將文件解壓到一個本身建立的文件夾下ide

(3)busybox的玩法和Linux內核的玩法很像,都是須要配置的函數


三、makefile的修改工具

(1)ARCH = armoop

(2)CROSS_COMPINE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-


四、make menuconfig進行配置

(1)配置參考老師提供的文檔


五、而後make,而後make install

(1)make 編譯,若是有錯誤,第一種方法就是去看哪一個地方出錯了,進行源代碼的修改。可是通常狀況下,出錯的地方的那個應該實現的功能多是咱們不想要的,通常出錯是因爲咱們的arm-gcc交叉編譯工具鏈和咱們的這個busybox中的makefile不兼容致使的,因此咱們第二種方法就是讓他不編譯那個出錯的文件,用find -name 「xxx」來查找這個文件在地方。發現這個文件所在的目錄後,看這個目錄下有沒有makefile,若是有在makefile中將這個文件不添加編譯就行,若是沒有,就看有沒有kbuid這個文件,也能夠在這個文件中將那個文件不進行編譯,怎麼作呢,就是在對應的makefile或者kbuid中找到這個文件所對應的那個CONFIG宏,完了以後再make menuconfig中將這個宏對應的東西配置成沒有就行了,若是沒有這個宏,那麼就直接用出錯的那個文件的名字找就好了,找到後給它去掉,未來make的時候就不會編譯這個文件了,在次進行make 編譯後,編譯出來了busybox這個東西,就在證實編譯經過了

(2)make install 執行的時候就是執行busybox頂層目錄的一個目標install,就是在執行這個目標

(3)make install 在全部的Linux下的軟件中,這個目標的一個做用就是安裝軟件,源代碼安裝,安裝的做用就是將編譯生成的可執行程序及其依賴的庫文件和配置文件頭文件等這些有用的東西安裝到咱們當前系統中咱們指定的目錄下,通常都是能夠本身指定安裝到哪一個目錄下,若是不指定通常都有個默認目錄下,默認的目錄不一樣軟件是不樣的,因此咱們通常是本身去指定,在make menuconfig的Busybox Settings--->中有一個install的默認安裝地方,能夠看出來默認是安裝在哪裏的,也能夠在這裏進行修改,咱們要安裝到咱們的那個根文件系統文件夾下


二、二、inittab詳解

一、一個配置文件,在根文件系統的文件夾下,建立一個etc文件夾,將inittab放到這裏,在次啓動內核用nfs掛載這個根文件系統就成功了,最小的根文件系統


二、inittab格式詳解

(1)這個inittab的工做原理被/linuxrc(也就是busybox)執行時調用起做用

(2)inittab在/etc目錄下,因此是一個運行時的配置文件,是文本格式的(內容是由不少字符構成的,按照必定格式組織的),實際工做的時候busybox會按照必定的格式去解析這個inittab文件,這個格式是由busybox決定的,在busybox的代碼中能夠體現,而後根據解析的內容來決定怎麼工做

(3)busybox究竟如何完成解析,而且解析的結果如何去工做(busybox中,實現/etc/inittab的原理並非咱們的目標,這些是寫busybox的人須要知道的),咱們的重點是要知道inittab的格式是怎麼樣的,咱們看到一個inittab後怎麼去分析inittab對啓動的影響,明白inittab這樣寫是什麼意思

(4)inittab的格式在busybox中定義的。網上能夠找到。

(5)#是行註釋

(6):冒號在裏面是分隔符,分隔開各個部分

(7)inittab是以行爲單位的,行和行之間沒有關聯,每行是一個配置項,每個配置項表示已個獨立的含義

(8)每一行的配置項都是由三個冒號分隔開的四個配置值共同肯定的,這四個配置值是id:runlevels:action:process

可是有些配置值能夠空缺,可是空缺了冒號是不能丟的。因此有時會看到連續的冒號

(9)每一行的配置項中,四個配置值,最重要的就是action和process,action是一種狀態,process是一個可被執行的程序pathname,合起來的意思就是,當知足action的條件時,就會執行process的程序,這個在busybox的源代碼中能夠分析出來,由於busybox最後是進入到了一個死循環中,在這個死循環中,busybox不斷的去檢查action知足的條件,知足一個就去執行一個對應的process進程。因此咱們的這個busybox進程1(也就是linuxrc,也就是init)最後始終在死循環中,不斷的檢查者個inittab文件中的action是否條件成立,若是成立執行一個對應的pricess,因此在整個操做系統運行起來的過程當中,這個inittab是一直在被用的

(10)明白各個action是什麼意思

::sysinit:/etc/init.d/rcS  這個action是sysinit,意思是當控制檯啓動以前執行後面的process,其餘的action是什麼含義在網上搜busybox inittab就能夠知道了


二、三、busybox源碼的分析1

一、進行解壓

二、整理目錄

三、創建SI工程

四、整個程序的入口確認

(1)在uboot中和內核中,由於操做系統尚未運做起來,咱們程序的入口要看連接腳本中指定的入口是哪裏

(2)可是咱們busybox程序是一個Linux內核啓動起來後運行的,這個busybox未來是安裝到根文件系統中的,因此這個busybox是一個應用程序,因此對於應用程序而言,對於操做系統運行起來的狀況下,咱們的程序入口就應該是main函數。

咱們程序入口是在Appletlib.c中的main函數中,當咱們在命令行下輸入一個命令的時候,這個命令就做爲這個函數的argv[0]了,經過這個argv來找到對應的那個xxx_main函數去運行執行這個命令,在返回到這個mian函數中,在次去看argv,因此busybox就是靠這種方法,來實現一個程序能夠當作不少命令的程序的



二、四、busybox源碼的分析2

一、inittab解析與執行

(1)inittab解析是在busybox中的init.c中的init_main中,啓動的時候執行的真正的函數

二、pwd命令執行路徑分析

三、busybox體積優點管理



二、五、rcS文件介紹

一、/etc/init.d/rcS這個文件是一個配置文件,是咱們Linux運行中最重要的一個配置文件,這個文件是在busybox調用/etc/inittab這個配置文件時,被運行的。在後面的其餘的配置文件,都是由這個文件引出來的,這個文件能夠複雜也能夠簡單的,裏面有不少配置項

二、PATH=XXX

(1)PATH這個環境變量是Linux系統內部定義的一個環境變量,含義是操做系統在執行一個程序時會默認的奧PATH指定的各個目錄下去尋找,若是找不到就認定這個程序不存在,若是找到了就去執行他,將一個可執行程序的目錄導出到PATH,可讓咱們不帶路徑的去執行這個程序。

(2)因此我在作根文件系統的時候,咱們的/etc/init.d/rcS這個配置文件中的PATH做用就是,讓咱們在執行那些命令集的時候也就是執行那些應用程序的時候,能夠不用指定路徑,達到咱們Ubuntu中的那個效果。

(3)但是咱們當前的狀況是,咱們並無將這個文件添加到咱們/etc/init.d目錄下,咱們沒有這個文件,可是內核掛載了這個根文件系統後,再命令行下,咱們直接ls也是好使的,而不用加上路徑去執行這個程序?也就是說爲何咱們的rcS文件尚未添加,咱們系統就有了PATH中的值?由於在busybox的源碼中,busybox用硬編碼的方式導出了一些環境變量,其中就有PATH,而且有個默認值

三、runlevel=S

(1)runlevel和運行階段有關,就是從系統啓動到啓動完畢的幾個階段,=S表示將系統設置爲單用戶模式

四、prevlevel=N

五、umask 022

(1)umask是Linux的一個命令,做用是設置Linux系統的umask值

(2)umask的值決定當前用戶在建立文件時的文件的默認的權限

六、mount -a

(1)mount命令是用來掛載文件系統的,mount -a的意思是掛載全部的應該掛載的文件系統,在busybox中mount -a時會去查找一個文件/etc/fstab、並執行這個文件,這個文件中按照必定的格式列出了應該被掛載的文件系統(包括了虛擬文件系統),因此想要mount -a工做,就必需要有fstab這個文件來配合


七、目前爲止的根文件系統製做實戰


(1)在以前的咱們的根文件系統文件夾下的,按照咱們的inittab中的第一步要執行的東西,咱們知道要在etc目錄下中建立一個init.d文件夾,將rcS這個配置文件放到裏面,由於rcS中用到mount -a要掛載fstab中列出的全部文件系統包括虛擬文件系統,因此須要用到fstab這個配置文件。因此咱們將fstab這個配置文件在放到/etc目錄下,以後去啓動內核nfs掛載這個根文件系統文件夾,發現仍是說這個rcS不存在,是由於rcS這個腳本文件中的內容是在windows中編寫的,回車有差別,改下便可。能夠說明若是在shell腳本中,若是內容格式不對,運行時會被認爲文件不存在


(2)有時一個應用程序在執行的時候也會提示文件不存在,多是由於這個應用程序所調用的一個動態連接庫找不到


(3)PATH和runlevel的測試


由於在busybox源碼中,PATH默認的值就給出來了,是/sbin:/bin:/usr/sbin:/usr/bin,因此咱們在rcS中不加這個PATH的時候,在命令行下,也是能看到PATH被賦值了的,因此咱們能夠不用設置這個值。

runlevel這個是運行級別,就是咱們inittab配置文件中的每個配置項對應的那個id:runlevel:action:process中的那個runlevel級別,可是在busybox中是不支持的,之後若是想更加詳細的去理解,能夠去網上搜索學習


(4)umask

umask是設置咱們當前用戶下建立文件時該文件的文件權限的,通過測試,知道

當咱們將umask的值設置成022時,咱們建立文件後,文件擁有的權限是644,

當咱們將umask的值設置成044時,建立一個文件的時候,文件的權限是622

當咱們將umask的值設置成444時,建立一個文件的時候,文件的權限是222


因此能夠看出來umask的值含義就是0對應文件權限6就是可讀可寫,2對應的文件權限是4也就是可讀,4對應的文件權限是2,也就是可寫,加起來是666.


(5)mount測試

當前掛載的時候所有出錯

緣由是咱們當前的根文件系統中找不到掛載點,掛載點就是咱們要將目標文件系統(固然這裏是虛擬文件系統)掛載到當前文件系統的某一個目錄中,這個目錄就是掛載點

解決方案就是,本身在製做的根文件系統的根目錄下,建立掛載點目錄就行

驗證是否掛載是否成功,能夠看咱們掛載時的一個輸出信息,沒有報錯就掛載成功了,還能夠在啓動後,去看咱們的proc和sys文件夾,若是在Ubuntu中看裏面沒有東西,在咱們開發板中的這些文件能看到東西,就說明掛載成功了


八、mdev -s

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

(1)medv是udev的嵌入式簡化版本,udev/mdev是用來配合Linux驅動工做的一個應用層的軟件,mdev/udev的做用就是配合Linux驅動生成相應的設備文件,/dev目錄下

(2)在rcS文件中,沒有啓動mdev的時候,咱們的/dev目錄下啓動後是沒有東西的,在rcS文件中添加上mdev相關的兩行內容後,在次啓動系統,發現咱們的/dev目錄下有內容了,全是設備驅動文件。

(3)/dev目錄下的設備驅動文件,就是mdev生成的,這就是mdev的意義


九、hostname

(1)hostname是Linux中的一個命令,這個命令執行後(hostname xxx)能夠用來設置當前系統的主機名,直接hostname能夠顯示當前系統的主機名

(2)/bin/hostname -F /etc/sysconfig/HOSTNAME 

/bin/hostname 執行了這個程序,-F指定了一個主機名的配置文件(這個文件的通常文件名叫hostname或者大寫的HOSTNAME)。

(3)使用方法就是在根文件系統中,將關於hostname的這一行內容添加到rcS中,在根文件系統的/etc目錄下建立一個sysconfig文件夾,在這個文件夾下建立一個HOSTNAME文件,在這個文件中寫入咱們想要的主機名字就好了。


十、ifconfig

(1)有時咱們但願看機後,進入命令行時,咱們的IP地址就有一個指定的IP地址,這時咱們就能夠在rcS文件中ifconfig eth0 一個IP地址



十一、profile文件和用戶登陸理論

(1)以前咱們在HOSTNAME中輸入了咱們的主機名字,但是咱們的命令下仍是沒有變,因此把這個profile配置文件添加到etc目錄下就能夠解決這個問題了。

(2)添加這個profile文件後,發如今命令行下咱們的主機名字能顯示出來了,可是咱們用戶名尚未,因此只有咱們添加用戶登陸功能之後,這個用戶名才能顯示出來,就達到了咱們Ubuntu中的效果了,好比root用戶,就是root@Ubuntu

(3)profile的工做原理:也是被init進程調用執行的,因此是認名字的,profile這幾個字不能寫錯。本身去網上搜吧


十二、如何看到用戶登陸界面

(1)由於以前的inittab中有一個配置項::askfirst:-/bin/sh,做用是當咱們系統啓動後,就去執行/bin/sh,執行這個後當咱們按下回車後就會進入命令行,所以咱們這樣安排的話。就不會出現用戶登陸界面,會直接進入命令行

(2)咱們要出現登陸界面,就不能執行這個/bin/sh程序,而應該執行一個負責負責出現登陸界面而且能管理用戶名和密碼的一個程序,busybox中集成了一個這樣的程序,這個程序就是/bin/login或者/sbin/getty,這兩個都行。


1三、用戶名和密碼的設置

(1)用戶名和密碼的設置確定是和咱們的登陸程序有關的,是在登陸程序中寫死的,可是全部的Linux的用戶名和密碼的管理幾乎都是同樣的

(2)密碼通常都是加密的文字,意思就是系統中的密碼確定是在系統的一個專門用來存放密碼的文件中存儲的,不是明文,否則你得系統被攻破了之後,別人就能夠直接知道你的密碼。


1四、用戶登陸的實戰

(1)將inttab配置文件中的askfirst這個action註釋掉,添加一個sysinit action對應process是/bin/login、

(2)重啓系統後,能夠進入到登陸界面,咱們當前用的是單用戶模式,因此只能是root用戶登陸,可是咱們的密碼怎麼輸都不對

(3)由於咱們根本就沒有給root用戶設置密碼,因此固然不對了

(4)添加psswd和shadow文件,Linux系統中用來描述用戶名和密碼的文件是psswd和shadow文件,這兩個文件都要在etc目錄下,shadow文件中存儲的是密文的密碼,psswd中存儲的是用戶密碼的設置

(5)咱們直接複製Ubuntu中的/etc/psswd 和 /etc/shadow這兩個文件到咱們的根文件系統的etc目錄下就行,在進行相應的修改就行,好比在psswd文件中留下咱們用的用戶root,將root用戶登陸後對應的目錄建立或者本身修改,將登陸root用戶後執行的腳本改爲/bin/sh,由於busybox中不支持bash只支持sh默認。

(6)咱們能夠先將root用戶對應的shadow那段密碼的位置,弄成沒有,完了以後啓動系統,咱們直接輸入root就能夠進入root用戶了,默認是無密碼的,我能夠經過psswd root給這個root用戶設置密碼、

(7)有時若是咱們忘記了操做系統的密碼,咱們怎麼辦呢,解決方法就是咱們在啓動這個操做系統的時候進入到uboot界面bootloader界面,告訴內核咱們的根文件系統是nfs的,以後拿一根網線和咱們另外一臺電腦上,用這臺電腦登陸一個相似於Ubuntu的系統,在這個系統上搭建nfs服務器,建立對應根文件系統的文件夾,咱們把啓動忘記密碼的那操做系統後,就會掛載到咱們的這個Ubuntu根文件系統文件夾下,咱們在這個文件夾下找到那個加密的文件,將用戶對應的密碼設置成空,在重啓系統就行了。

(8)id號的提示,提示串口的id號,能夠在inittab中,將對應的id號添加上就行了。咱們用的是串口,在/dev目錄下找到那個串口2的名字寫到inittab中,咱們添加的那個action是sysinit,proess是/bin/login上的id中


1五、getty的作法和login的作法是同樣的,二者應該在busybox中沒有區別


一、1六、動態連接庫的拷貝

一、靜態連接hellowrod程序並執行

(1)咱們在Ubuntu中寫一個C語言程序,寫完後若是咱們是用gcc編譯的話,就不能再咱們的arm平臺上運行,由於個人Ubuntu是80386架構的,因此咱們要用arm-linux-gcc去交叉編譯成能夠在arm平臺上運行的可執行程序


(2)咱們先靜態編譯連接這個helloword程序,也就是用 arm-linux-gcc hello.c -o hello_static -static 這樣去靜態編譯連接

(3)實驗結果是,咱們靜態編譯生成的hello_static能夠成功的運行在咱們的系統上,


二、動態連接並執行

(1)動態連接:

arm-linux-gcc hello.c -o hello_dynamic


(2)若是不加動態連接庫的話,是不能運行在咱們開發板系統上的。


(3)動態連接的hello中,當在咱們的開發板的系統上運行時,執行那個printf函數時找不到當前運行時環境對應的動態連接庫,也就是說,在根文件系統中找不到lib中對應的動態連接庫文件,由於動態連接的程序,是在程序運行的時候,將調用的函數在動態連接庫中找到那個代碼段,進行加載運行的。因此咱們的rootfs中沒有動態連接,在執行動態連接的程序的時候就會找到不相應的代碼段,就會出錯


(4)因此咱們應該將arm-linux-gcc的動態連接庫文件複製到根文件系統目錄下的/lib目錄下,添加動態連接庫就行了


(5)arm-linux-gcc這個交叉編譯工具對應的動態連接庫,就在咱們安裝這個交叉編譯工具鏈時所在的某個目錄下,個人是在/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib中,因此複製這個目錄中的東西到咱們的根文件系統的/lib中,其餘一些的交叉編譯工具對應的動態連接庫可能不在這個目錄下,咱們能夠用find -name 「*libm.so*」去找。


(6)複製的時候,參數要加上 -rdf 目的是爲了讓符號連接複製過來後仍是符號連接。

複製方法是用 cp xxx/*so* xxx/ -rdf  用*so* 來把不是動態連接庫的東西過濾出去


(7)複製過來後,由於這些動態連接庫文件中包含了一些調試用的符號信息,佔空間,因此能夠用arm-linux-strip *so* 用這個strip工具,將調試符號信息去掉,就省了一些空間了


二、六、開機自啓動與主流的rcS格式是什麼樣的

一、開機自動啓動這裏的意思是說,在開發板上的操做系統起來之後可讓一些應用程序自動執行。

(1)實現方法就是在rcS腳本中,加上想要開機直接執行的應用程序就行。由於根文件系統掛載後,會執行init進程1,這個進程就是/linuxrc,就是busybox,他先執行inittab,inittab中先執行了rcS,因此這個rcS中的內容會先被執行,能夠在這裏進行添加


二、前臺運行和後臺運行


(1)前臺運行:程序運行佔用了當前的控制檯,因此這個程序叫作前臺運行的程序。程序不結束會不到控制檯。好比咱們寫一個hello.c讓這個程序一直在執行,回不到控制檯的命令行下,那麼這個程序就是前臺運行,默認執行程序的時候就是前臺運行的。


(2)後臺運行:後臺運行就是讓這個程序運行,而且讓這個程序讓出控制檯,這時候這個程序還能運行,而且還能不影響當前控制檯的使用。在執行一個程序的時候在後面加上&符號就行,如 ./xxx &.



總結:根文件系統製做的流程和原理分析


(1)咱們的內核在啓動後最後要去掛載根文件系統,執行根文件系統下的linuxrc這個程序,也就是init進程,也就是進程1,執行這個進程爲了從內核態進入到用戶態,這時才代表操做系統真正的運行起來了


(2)先經過nfs的文件夾形式的根文件系統調試好,搭建主機端的nfs服務器,配置開發板內核支持nfs協議。bootargs傳參告訴內核是nfs的根文件系統。


(3)咱們linuxrc程序實際上是busybox這個程序,咱們在網上下載這個busybox程序,任意版本就行,由於咱們busybox這個程序未來是要在咱們的開發板上運行的,因此編譯這個程序的時候必須用arm的交叉編譯工具鏈,因此咱們將這個程序下載下來後要看makefile中CROSS_COMPINE這個環境變量的值是否是咱們交叉編譯工具鏈所在的位置,ARCH架構是否是arm,以後再參考老師的提供的文檔用make menuconfig對busybox進行配置,有錯誤的話,進行排查,配置的時候要安裝路徑也配置好,編譯好後安裝到咱們的根文件系統文件夾下,主機端建立的文件夾,這個位置是nfs通訊的那個文件夾。


(4)安裝好後,這個時候根文件系統就有linuxrc這個程序了,開發板系統啓動時執行了這個程序,可是由於busybox要調用/etc下的inittab這配置文件,因此咱們要在etc目錄下添加一個這個inittab配置文件,這個配置文件應該很好懂,看了就知道,不知道能夠去百度。


(5)添加了inittab配置文件後,在啓動的時候說找不到/etc/init.d目錄下的rcS程序,由於inittab這個配置文件中,第一個配置項就是執行這個rcS程序,因此在etc目錄下建立init.d目錄,而且將rcS配置文件添加進來,咱們打開rcS能夠發現這裏面有一系列內容,由於要mount -a掛載全部文件系統,因此須要在etc目錄下添加一個fstab這個配置文件,由於這個配置文件中有不少掛載點,因此要在根文件系統根目錄下建立這些掛載點,由於rcS中涉及到主機名,看內容知道主機名被指定在/bin/hostname -F /etc/sysconfig/HOSTNAME中,因此要在etc目錄下建立sysconfig目錄建立HOSTNAME文件,這個文件中的內容就是咱們的主機名,我寫的是why210,想讓這個主機名生效,在咱們命令行下顯示出來就須要profile這個配置文件的配合,因此還要在etc目錄下添加這個profile配置文件,這個時候在啓動就能夠在命令行下看到主機名了。


(6)爲了實現用戶登陸還有密碼,由於這個用戶登陸和密碼在busybox中是支持的,因此busybox中的程序就有這個的實現,因此咱們爲了讓用戶登陸在命令行出現以前就出現,咱們就要在inittab配置文件,在命令行出來以前添加這個用戶登陸的執行程序,因此添加了一個action和process,用戶登陸很密碼須要兩個文件的配合,能夠在Ubuntu中將/etc下的passwd和shadow複製到咱們的根文件系統etc目錄下,一箇中告訴了用戶登陸後的目錄,一箇中記錄了密文密碼。在這兩個文件的配合下,咱們的用戶登陸就能夠實現了。可是提示這個須要有id號,因此將咱們使用的串口id號添加到對應的這個inittab中的配置項的id中。

(7)爲了實現動態連接的程序能夠在開發板上運行,須要將arm-linux-gcc對應的動態連接庫文件拷貝到咱們的根文件系統下的lib目錄中。以支持交叉編譯的動態連接庫。

(8)以後就能夠製做成可燒錄的鏡像了,步驟以下


dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240

losetup  /dev/loop1 rootfs.ext2

mke2fs -m 0 /dev/loop1 10240

mount -t ext2 /dev/loop1 ./ext2_rootfs/


複製咱們的根文件系統文件夾形式的內容到ext2_roofs文件中,這樣就能夠放在roofs.ext2鏡像中了


umount /dev/loop1

losetup -d /dev/loop1

相關文章
相關標籤/搜索