天天看點

2.19.根檔案系統建構實驗及過程詳解

章節目錄

2.19.1.根檔案系統的建構路線

2.19.2.busybox的移植實戰

2.19.3.inittab詳解

2.19.4.busybox源碼分析1

2.19.5.busybox源碼分析2

2.19.6.rcS檔案介紹1

2.19.7.rcS檔案實戰1

2.19.8.rcS檔案介紹2

2.19.9.profile檔案和使用者登入理論

2.19.10.使用者登入實戰

2.19.11.動态連結庫的拷貝

2.19.12.開機自啟動與主流rcS格式介紹

2.19.13.制作ext2格式的鏡像并燒錄啟動

#############################################################

rootfs 的主要檔案

etc/: //不是busybox自動生成

etc/init.d/rcS:

主要是做開機前的配置,和開機自啟動運作一些程式

凡是開機幹啥都是在rcS檔案中設定

環境變量的配置

etc/fstab

etc/inittab

內建很多個小程式來完成一個大的功能

可以設定使用者登入界面

inittab是幫助init完成系統配置的主要檔案

inittab的工作原理就是被/linuxrc(也就是busybox)執行時所調用起作用

etc/profile

檔案裡存放的是系統的環境變量,對所有使用者都有效果

如(使用者登陸界面的[root@liu ~]#)

etc/sysconfig/HOSTNAME

在檔案中添加主機名

etc/passwd

存放銘文密碼

etc/shadow

存放密文密碼

____________________________________

/lib: //不是busybox自動生成

程式運作需要的動态連接配接庫

/dev: //不是busybox自動生成

目錄下的裝置驅動檔案就是rcS的mdev生成的,這就是mdev的效果和意義

/proc //不是busybox自動生成

/sys //不是busybox自動生成

/var //不是busybox自動生成

/tmp //不是busybox自動生成

/root //不是busybox自動生成

作為根使用者的使用者和空間

********************************

busybox自動生成:bin linuxrc sbin usr

#############################################################

2.19.1.根檔案系統的建構路線

2.19.1.1、課程安排變化。

2.19.1.2、先逐漸建構檔案夾形式根檔案系統然後制作燒錄鏡像

(1)rootfs有2種格式:nfs方式啟動的檔案夾形式的rootfs和用來燒錄的鏡像形式的rootfs。

(2)傳統的教育訓練機構中上課時,rootfs制作實驗都是直接給制作文檔,學生參照制作文檔的步驟自己動手做,一步到位做出來的就是可供燒錄的rootfs。

(3)我們先從空檔案夾開始,逐漸向其中添加一些rootfs中必備的東西,然後做一步就用nfs方式去挂載啟動,觀察啟動後的現象,并且理論上去分析原因。

2.19.1.3、動手實踐和理論分析相結合。

2.19.1.4、逐漸添加不斷複雜化的rootfs

2.19.2.busybox的移植實戰

2.19.2.1、busybox源碼下載下傳

(1)busybox是一個開源項目,是以源代碼可以直接從網上下載下傳。

簡介:

​​https://wenku.baidu.com/view/1c921dd676eeaeaad1f33070.html​​

被譽為“嵌入式linux的瑞士軍刀”

(2)busybox的版本差異不大,版本新舊無所謂。

(3)下載下傳busybox可以去linuxidc等鏡像網站,也可以去www.busybox.net官方網站下載下傳。

2.19.2.2、修改Makefile

(1) ARCH = arm

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

ARCH = arm

CROSS_COMPILE = /usr/local/arm_x210/bianyilian/arm-2009q3/bin/arm-none-linux-gnueabi-

2.19.2.3、make menuconfig進行配置

(1)參照網盤中章節目錄下的《busybox menuconfig配置.txt》檔案中的記錄進行配置。

2.19.2.4、make 然後 make install

(1)make編譯,如果有錯誤解決之

(2)make install執行的時候其實是在執行busybox頂層目錄下的一個目标install。

(3)make install在所有的linux下的軟體中作用都是安裝軟體。在傳統的linux系統中安裝軟體時都是選擇源代碼方式安裝的。我們下載下傳要安裝的軟體源代碼,然後配置、編譯、安裝。make install的目的就是将編譯生成的可執行程式及其依賴的庫檔案、配置檔案、頭檔案安裝到目前系統中指定(一般都可以自己指定安裝到哪個目錄下,如果不指定一般都有個預設目錄)的目錄下

出錯:

找檔案的位置:

發現沒有Makefile

隻有進入找Kbudlie

在menuconfig找SYNC

出現busybox就表示編譯成功

預設安裝目錄

cd ./_install

Busybox Settings --->

Installation Options ("make install" behavior) --->

What kind of applet links to install (as soft-links) --->

(./_install) BusyBox installation prefix

再次make install

實驗結果:

1.nfs挂載成功

2.執行/linuxrc失敗。

2.19.2.5、設定bootargs挂載添加了busybox移植的rootfs

(1)之前建立了一個空的檔案夾然後自己touch linuxrc随便建立了一個不能用的/linuxrc然後去nfs挂載rootfs,實驗結果是:挂載成功,執行/linuxrc失敗。

(2)現在我們移植了busybox後/linuxrc就可以用了,然後再次去nfs挂載這個rootfs。預計看到的效果是:挂載成功,執行/linuxrc也能成功。

(3)注意uboot的bootargs設定成:setenv bootargs root=/dev/nfs nfsroot=192.168.1.141:/root/porting_x210/rootfs ip=192.168.1.10:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200

(4)實驗結果:

1.挂載成功,

2.執行/linuxrc(也就是busybox)成功,

3.但是因為找不到/etc/init.d/rcS和/dev/tty2等檔案是以一直在列印錯誤提示資訊,但是其實有進入指令行。

2.19.3.inittab詳解

2.19.3.1、添加一個典型的inittab

inittab就是一個普通的配置檔案(是根檔案系統第一個執行的檔案)

(1)将我提供的典型的inittab檔案複制到我們制作的rootfs的根目錄下的/etc/目錄下

(2)再次啟動核心挂載這個rootfs看效果

(3)實驗現象是成功啟動并且挂載rootfs進入了控制台指令行。目前制作的最小rootfs成功了

2.19.3.2、inittab格式解析

簡介:

由于BusyBox自身的一些特點,BusyBox init非常适合在嵌入式系統開發中使用,被譽為“嵌入式linux的瑞士軍刀”,它可以為嵌入式系統提供隻要的init功能,并且通過定制可以做得非常 精煉。inittab是幫助init完成系統配置的主要檔案。 

(1)inittab的工作原理就是被/linuxrc(也就是busybox)執行時所調用起作用。

(2)inittab在/etc目錄下,是以屬于一個運作時配置檔案,是文本格式的(内容是由一系列的遵照一個格式組織的字元組成的),實際工作的時候busybox會(按照一定的格式)解析這個inittab文本檔案,然後根據解析的内容來決定要怎麼工作。

(3)busybox究竟如何完成解析并且解析結果如何去工作(busybox中實作/etc/inittab的原理)并不是我們的目标,我們的重點是inittab的格式究竟怎樣的?我們看到一個inittab後怎麼去分析這個inittab對啟動的影響。

(4)inittab的格式在busybox中定義的,網上可以搜尋到詳細的格式說明,具體去參考即可:

第一個:#開始的行是注釋

::askfirst:-/bin/sh

加上”-”的語句會在登陸終端之後,調用/etc/目錄下的profile檔案,而不加”-”的不會執行這個腳本。

第二個:冒号在裡面是分隔符,分隔開各個部分。

第三個:inittab内容是以行為機關的,行與行之間沒有關聯,每行都是一個獨立的配置項,每一個配置項表示一個具體的含義。

第四個:每一行的配置項都是由3個冒号分隔開的4個配置值共同确定的。這四個配置值就是id:runlevels:action:process。值得注意得是有些配置值可以空缺,空缺後冒号不能空缺,是以有時候會看到連續2個冒号。

第五個:每一行的配置項中4個配置值中最重要的是action和process,

1.id

盡管該格式與發行版linux的Sys V init類似,但是,id在BusyBox的init中具有不同的意義。對BusyBox而言,id用來指定啟動程序的控制終端。如果所啟動的程序并不是可以互動的shell,例如BusyBox的sh(ash),應該會有個控制終端,如果控制終端不存在,BusyBox的sh會報錯。

2.runlevel_ignored

由該字段的名稱可知,BusyBox init忽略runlevel_ignored字段,是以配置inittab時空着它就行了。

3.action

是一個條件/狀态,

4.process

是一個可被執行的程式的pathname。

合起來的意思就是:當滿足action的條件時就會執行process這個程式。

注意:了解inittab的關鍵就是明白“當滿足action的條件時就會執行process這個程式。

” 你去分析busybox的源代碼就會發現,busybox最終會進入一個死循環,在這個死循環中去反複檢查是否滿足各個action的條件,

如果某個action的條件滿足就會去執行對應的process。

程序1 一直在檢查action

第六個:明白各個action什麼意思

2.19.4.busybox源碼分析1

2.19.4.1、源碼目錄梳理

2.19.4.2、SourceInsight工程建立

2.19.4.3、整個程式入口确認

(1)分析一個程式,不管多龐大還是小,最好的路線都是按照程式運作時的邏輯順序來。是以找到一個程式的入口至關重要。

(2)學C語言的時候都知道程式的主函數main函數就是整個程式的入口。這種情況适應于作業系統下工作的應用程式的情況。

(3)在uboot和linux kernel這兩個大的C語言的項目中,main函數都沒有,都不是入口。在我們這種裸機程式中入口不是main函數,而是由連接配接腳本來指定的。

(4)busybox是linux啟動起來後工作的一個應用程式,是以其中必然有main函數,而且main就是入口。

2.19.4.4、busybox中main函數全解析

(1)busybox入口就是main函數,其中有很多個main但是隻有一個起作用了,其他的是沒起作用的。真正的busybox工作時的入口是libbb/appletlib.c中的main函數

(2)busubox中有很多xxx_main函數,這些main函數每一個都是busybox支援的一個指令的真正入口。譬如ls_main函數就是busybox當作ls函數使用時的入口程式。

有的檔案不是包含真正main函數的檔案也編譯了

隻有去分析它的連接配接腳本

(3)ls或者cd等指令其實都是busybox一個程式,但是實際執行時的效果卻是各自的效果。

busybox是如何實作一個程式化身萬千還能各自工作的?

答案就是main轉xxx_main。

也就是說busybox每次執行時都是先執行其main,在main函數中識别(靠main函數的傳參argv[0]來識别)我們真正要執行的函數(譬如ls)然後去調用相應的xxx_main(譬如ls_main)來具體實作這個指令。

2.19.5.busybox源碼分析2

2.19.5.1、inittab解析與執行

(1)inittab的解析是在busybox/init/init.c/init_main函數中

(2)執行邏輯是:

先通過parse_inittab函數解析/etc/inittab(解析的重點是将inittab中的各個action和process解析出來),

然後後面先直接執行sysinit和wait和once(注意這裡隻執行一遍),

然後在while(1)死循環中去執行respwan和askfirst。

2.19.5.2、pwd指令執行路徑分析

(1)根據上節講的,我們在busybox指令行下執行pwd指令時實際執行的是pwd_main這個函數。

2.19.5.3、busybox的體積優勢原理

(1)busybox實際上就是把ls、cd、mkdir等很多個linux中常用的shell指令內建在一起了。內建在一起後有一個體積優勢:

就是busybox程式的大小比busybox中實作的那些指令的大小加起來要小很多。

Ubuntu的指令檔案大小

busybox的指令大小

(2)busybox體系變小的原因主要有2個:

第一個是busybox本身提供的shell指令是閹割版的(busybox中的指令支援的參數選項比發行版中要少,譬如ls在發行版中可以有幾十個-x,但是在busybox中隻保留了幾個常用的選項,不常用的都删除掉了);

第二個是busybox中因為所有的指令的實作代碼都在一個程式中實作,而各個指令中有很多代碼函數都是通用的

(譬如ls和cd、mkdir等指令都會需要去操作目錄,是以在busybox中實作目錄操作的函數就可以被這些指令共用),共用會降低重複代碼出現的次數,進而減少總的代碼量和體積。

(3)經過分析,busybox的體積優勢是嵌入式系統本身的要求和特點造成的。

2.19.6.rcS檔案介紹1

2.19.6.0、/etc/init.d/rcS檔案是linux的運作時配置檔案中最重要的一個,

其他的一些配置都是由這個檔案引出來的。這個檔案可以很複雜也可以很簡單,裡面可以有很多的配置項。

2.19.6.1、PATH=xxx

(1)首先從shell腳本的文法角度分析,這一行定義了一個變量PATH,值等于後面的字元串

(2)後面用export導出了這個PATH,那麼PATH就變成了一個環境變量。

(3)PATH這個環境變量是linux系統内部定義的一個環境變量,

含義是作業系統去執行程式時會預設到PATH指定的各個目錄下去尋找。如果找不到就認定這個程式不存在,如果找到了就去執行它。将一個可執行程式的目錄導出到PATH,可以讓我們不帶路徑來執行這個程式。

實驗:

PATH預設就是這個

讓PASH為空

為空後就不能用ls ,隻能用/bin/ls

在重新定義PASH

就可以用ls

(4)rcS中為什麼要先導出PATH?

就是因為我們希望一旦進入指令行下時,

PATH環境變量中就有預設的/bin /sbin /usr/bin /usr/sbin 這幾個常見的可執行程式的路徑,

這樣我們進入指令行後就可以ls、cd等直接使用了。

(5)為什麼我們的rcS檔案還沒添加,

系統啟動就有了PATH中的值?

原因在于busybox自己用代碼寫死為我們導出了一些環境變量,其中就有PATH。

(6)這個語句的意義:

當我們自己想添加别的環境變量的時候,就可以在這裡添加

2.19.6.2、runlevel=

(1)runlevel也是一個shell變量,并且被導出為環境變量。

(2)runlevel這個環境變量到底有什麼用?

(3)runlevel=S表示将系統設定為單使用者模式

2.19.6.3、umask=

(1)umask是linux的一個指令,作用是設定linux系統的umask值。

(2)umask值決定目前使用者在建立檔案時的預設權限。

2.19.6.4、mount -a

(1)mount指令是用來挂載檔案系統的

注意:

這裡就在開始挂載其他檔案系統了,也是第一次挂載檔案系統

(2)mount -a是挂載所有的應該被挂載的檔案系統,在busybox中mount -a時busybox會去查找一個檔案/etc/fstab檔案,這個檔案按照一定的格式列出來所有應該被挂載的檔案系統(包括了虛拟檔案系統)

2.19.7.rcS檔案實戰1

2.19.7.1、PATH&runlevel

先複制rcs 和 fstab 到虛拟機

(1)我們實戰發現rcS檔案明明存在但是卻提示不存在,

問題原因就是rcS檔案在windows下建立的,行尾換行符為'\r\n',多了點東西。但是因為ubuntu中的vi對行尾做了優化,是以在ubuntu中是看不出來多了東西的。但是在securecrt下一看就發現每一行末尾多出來了一個^M。

(2)這個故事告訴我們:shell腳本檔案如果格式不對,運作時可能會被提示檔案不存在。

(3)擴充講一個:有時候一個應用程式執行時也會提示檔案不存在,問題可能是這個程式所調用的一個動态連結庫找不到。

(4)測試結果:

PATH本來在busybox中就已經用代碼導出過了,是以rcS中再次導出沒有任何明顯的現象,是以看不出什麼差别;

runlevel實際執行結果一直是unknown,問題在于busybox并不支援runlevel這個特性。(這個結論重要)

2.19.7.2、umask測試

(1)umask是022的時候,預設touch建立一個檔案的權限是644

(2)umask是044的時候,預設touch建立一個檔案的權限是622

(3)umask是444的時候,預設touch建立一個檔案的權限是222

總結:umask的規律就是:umask值和預設建立檔案的權限值加起來是666.

2.19.7.3、mount測試

(1)挂載時全部出錯:

(2)原因是因為根檔案系統中找不到挂載點。所謂挂載點就是我們要将目标檔案系統(當然這裡都是虛拟檔案系統)挂載到目前檔案系統中的某一個目錄中,這個目錄就是挂載點。

(3)解決方案就是自己在制作的rootfs根目錄下建立這些挂載點目錄即可。

mkdir proc sys var tmp dev

(4)驗證是否挂載成功,可以看挂載時輸出資訊;還可以啟動後去看proc和sys檔案夾,如果有檔案出現則證明挂載成功了,如果沒東西就證明失敗了。

在Ubuntu中:ls sys 後,啥也沒有

在序列槽中:ls sys 後

原因:以後再說

2.19.8.rcS檔案介紹2

2.19.8.1、mdev

(1)mdev是udev的嵌入式簡化版本,udev/mdev是用來配合linux驅動工作的一個應用層的軟體,udev/mdev的工作就是配合linux驅動生成相應的/dev目錄下的裝置檔案。

(2)因為這個問題涉及到驅動,是以詳細講解要等到驅動部分。這裡我們隻是通過一些直覺的現象來初步了解udev/mdev的工作效果。

(3)在rcS檔案中沒有啟動mdev的時候,/dev目錄下啟動後是空的;在rcS檔案中添加上mdev有關的2行配置項後,再次啟動系統後發現/dev目錄下生成了很多的裝置驅動檔案。

添加:

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

mdev -s

(4)/dev目錄下的裝置驅動檔案就是mdev生成的,這就是mdev的效果和意義。

添加代碼之前啥也沒有

添加之後

生成這些檔案有什麼用,不生成又有什麼用,這要到驅動部分講解

2.19.8.2、hostname

(1)hostname是linux中的一個shell指令。指令(hostname xxx)執行後可以用來設定目前系統的主機名為xxx,直接hostname不加參數可以顯示目前系統的主機名。

預設主機名:

(2)/bin/hostname -F /etc/sysconfig/HOSTNAME -F來指定了一個主機名配置檔案(這個檔案一般檔案名叫hostname或者HOSTNAME)

先在rcS中添加指令:/bin/hostname -F /etc/sysconfig/HOSTNAME

再建立 /etc/sysconfig/HOSTNAME 檔案,在添加主機名

如果自己設定了HOSTNAME

如果沒設定HOSTNAME,就為IP位址

2.19.8.3、ifconfig

(1)有時候我們希望開機後進入指令行時ip位址就是一個指定的ip位址(譬如192.168.1.30),

這時候就可以在rcS檔案中ifconfig eth0 192.168.1.30

2.19.9.profile檔案和使用者登入理論

2.19.9.1、profile檔案添加

(1)之前添加了/bin/hostname在/etc/sysconfig/HOSTNAME檔案中定義了一個hostname(aston210),實際效果是:指令行下hostname指令查到的host名字确實是aston210。但是問題就是指令行的提示符是沒有顯示的。

(2)這個問題的解決就要靠profile檔案。

将提供的profile檔案放入/etc/目錄下即可。

(3)添加了之後的實驗現象:指令行提示符前面顯示:[@aston210 ]#

結論是:

第一,profile檔案起了作用,hostname顯示出來了。

第二,還有個問題,登入使用者名沒顯示出來。

原因就是我們直接進入了指令行而沒有做登入。等我們添加了使用者登入功能,并且成功登陸後這個問題就能解決。

(4)profile檔案工作原理是:

profile檔案也是被busybox(init程序)自動調用的,是以是認名字的。

自己查詢資料得到:

/etc/profile檔案裡存放的是系統的環境變量,對所有使用者都有效果,要對其更改的話,必須要在root使用者權限下才能進行。

我們可以使用env來檢視系統目前所有的環境變量,set可以檢視所有本地定義的shell變量。

我們在/etc/profile裡面修改的話,是對所有使用者起作用,是以一般所有使用者都要使用的環境變量就應該放在該檔案心裡面,這樣系統運作之後該檔案裡面的環境變量都會生效。

常見的環境變量如下:

  PATH:決定了shell将到哪些目錄中尋找指令或程式

  HOME:目前使用者主目錄

  MAIL:是指目前使用者的郵件存放目錄。

  SHELL:是指目前使用者用的是哪種Shell。

  HISTSIZE:是指儲存曆史指令記錄的條數。

  LOGNAME:是指目前使用者的登入名。

  HOSTNAME:是指主機名稱,許多應用程式如果要用到主機名的話,通常是從這個環境變量中來取得的。

  LANG/LANGUGE:是和語言相關的環境變量,使用多種語言的使用者可以修改此環境變量。

  PS1:是基本提示符,對于root使用者是#,對于普通使用者是$。

  PS2:是附屬提示符,預設是“>”。

2.19.9.2、如何看到使用者登入界面

(1)linux中有一個原則就是用一個小程式來完成一個功能。如果我們産品确實需要很複雜的綜合型的功能,我們傾向于先使用很多個小程式完成其中的一個功能,然後再将這些小程式內建起來完成整個大功能的産品。

(2)這種內建很多個小程式來完成一個大的功能,有很多種技術實作。譬如shell腳本,還有一些别的技術,譬如linux啟動中的inittab。

(3)因為我們之前intttab中有一個配置項 ::askfirst:-/bin/sh,這個配置項作用就是當系統啟動後就去執行/bin/sh,執行這個就會出現指令行。是以我們這樣的安排就會直接進入指令行而不會出現登入界面。

(4)我們要出現登入界面,就不能直接執行/bin/sh,

而應該執行一個負責出現登入界面并且負責管理使用者名和密碼的一個程式,

busybox中也內建了這個程式(就是/bin/login和/sbin/gettty),

是以我們要在inittab中用/bin/login或者/sbin/getty去替代/bin/sh。

2.19.9.3、使用者名和密碼的設定

(1)使用者名和密碼的設定是和登入程式有關聯的,

但是/bin/login和/sbin/getty在使用者名和密碼的管理上是一樣的。其實常見的所有的linux系統的使用者名和密碼的管理幾乎都是一樣的。

(2)密碼一般都是用加密文字的,而不是用明文。

意思就是系統中的密碼肯定是在系統中的一個專門用來存密碼的檔案中存儲的,用明文存密碼有風險,是以linux系統都是用密文來存儲密碼的。關于密文密碼的使用下節課實踐時會詳細講。

2.19.10.使用者登入實戰

2.19.10.1、添加/bin/login到sysinit

(1)在inittab中修改,去掉/bin/sh,換上/bin/login,則系統啟動後出現登入界面。

可以輸入使用者名和密碼。

(2)實驗現象:

成功出現使用者登入界面,但是死活密碼不對。

2.19.10.2、添加passwd和shadow檔案

(1)為什麼使用者名和密碼不對?

因為我們根本沒有為root使用者設定密碼。

(2)linux系統中用來描述使用者名和密碼的檔案是passwd和shadow檔案,這兩個檔案都在etc目錄下。passwd檔案中存儲的是使用者的密碼設定,

shadow檔案中存儲的是加密後的密碼。

(3)我們直接複制ubuntu系統中的/etc/passwd和/etc/shadow檔案到目前制作的rootfs目錄下,然後再做修改即可。

然後删除其他使用者,隻留root

建立root使用者的檔案夾

修改root的執行腳本為/bin/sh

(4)/etc/passwd和/etc/shadow修理好後,

shadow中預設有一個加密的密碼密碼,這個密碼和你拷貝的shadow本身有關,像我的ubuntu中root使用者的密碼就是root,是以複制過來後登陸時的密碼還是root。

2.19.10.3、重置密碼實踐

(1)ubuntu剛裝好的時候預設登入是用普通使用者登入的,預設root使用者是關閉的。普通使用者的密碼是在裝系統的時候設定的,普通使用者登陸後可以使用su passwd root給root使用者設定密碼,設定了密碼後root使用者才可以登入。

(2)其實這個原因就是root使用者在/etc/shadow檔案中加密密碼是空白的。是以是不能登入的。

(3)busybox中因為沒有普通使用者,

是以做法是:預設root使用者如果加密密碼是空的則預設無密碼直接登入。等我們登陸了之後還是可以用passwd root給root使用者設定密碼。

輸入後root後就登陸了

我們可以先讓/etc/shadow的密文為空

然後再設定密碼123456

設定之後就有密文了

(4)平時有時候我們忘記了自己的作業系統的密碼,怎麼辦?有一種解決方法就是用其他系統(WindowsPE系統或者ubuntu的單使用者模式等···)來引導啟動,啟動後挂載到我們的硬碟上,然後找到/etc/shadow檔案,去掉密文密碼後儲存。然後再重新開機系統後密碼就沒了。

(5)解決:

原因:是沒有指定序列槽

找到序列槽名字s3c2410_serial2

添加到/etc/inittable

結果:

其實這裡我自己出現了一個問題,就是

原因是我沒有在rootfs1下建立root檔案

我建立到rootfs1/etc下了

更改之後就可以了

2.19.10.4、getty實戰

(1)大家後面做項目會發現,

inittab中最常見的用于登入的程式不是/bin/login,

反而是/sbin/getty。

(2)這兩個的差别不詳,但是在busybox中這兩個是一樣的。這兩個其實都是busybox的符号連結而已。是以不用嚴格區分這兩個

(3)我們可以在inittab中用getty替換login程式來實作同樣的效果。

2.19.11.動态連結庫的拷貝

2.19.11.1、靜态編譯連結helloworld程式并執行

(1)任務:自己寫一個helloworld程式,然後交叉編譯連接配接,然後丢到開發闆根檔案系統中,開機後去運作。

(2)C程式如果使用gcc來編譯則可以在主機ubuntu中運作,但是不能在開發闆運作;要在開發闆運作需要用arm-linux-gcc來交叉編譯,但是這時候就不能在主機ubuntu中運作了。我們可以用file xx指令來檢視一個elf可執行程式是哪個架構的。

(3)靜态連結:arm-linux-gcc hello.c -o hello_satic -static

(4)實驗結果:靜态編譯連接配接後生成的hello_satic已經可以成功運作。

2.19.11.2、動态編譯連接配接helloworld程式并執行

(1)動态連結:arm-linux-gcc hello.c -o hello_dynamic

(2)實驗結果:-sh: ./hello_dynamic: not found運作時提示找不到程式。

(3)錯誤分析:動态連接配接的hello程式中調用到了printf函數,而printf函數在動态連接配接時要在運作時環境(開發闆的rootfs)中去尋找對應的庫檔案(開發闆rootfs中部署的動态連結庫中包含了printf函數的那個庫檔案)。

如果找到了則printf函數就會被成功解析,然後hello_dynamic程式就會被執行;如果找不到則程式就不能被執行,指令行會提示錯誤資訊-sh: ./hello_dynamic: not found

(4)解決方案:将arm-linux-gcc的動态連結庫檔案複制到開發闆rootfs的/lib目錄下即可解決。

2.19.11.3、找到并複制動态連結庫檔案到rootfs中

由于它預設是沒有lib檔案,是以要先建立

(1)我們用的arm-2009q3這個交叉編譯工具鍊的動态連結庫在/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib目錄下。其他的一些交叉編譯工具鍊中動态連結庫的目錄不一定在這裡,要去找一下。找的方法就是find

我自己是在/usr/local/arm_x210/bianyilian/arm-2009q3/libc/lib

(2)複制動态連結庫到roots/lib目錄下。複制時要注意參數用-rdf,主要目的就是符号連結複制過來還是符号連結。

複制指令:

cp /usr/local/arm_x210/bianyilian/arm-2009q3/arm-none-linux-gnueabi/libc/lib/*so* ./lib/ -rdf

(3)現在再去測試./hello_dynamic看看是否可以運作,實驗結果是可以運作。

2.19.11.4、使用strip工具去掉庫中符号資訊

動态連結庫so檔案中包含了調試符号資訊,這些符号資訊在運作時是沒用的(調試時用的),這些符号會占用一定空間。在傳統的嵌入式系統中flash空間是有限的,為了節省空間常常把這些符号資訊去掉。這樣節省空間并且不影響運作。

去掉符号指令:arm-linux-strip *so*

實際操作後發現庫檔案由3.8M變成了3.0M,節省了0.8M的空間。

2.19.12.開機自啟動與主流rcS格式介紹

2.19.12.1、修改rcS實作開機自啟動

(1)開機自啟動指的是讓一些應用程式能夠開機後自動執行

(2)開機自啟動的實作原理就是在開機會自動執行的腳本rcS中添加上執行某個程式的語句代碼即可

2.19.12.2、前台運作與背景運作

(1)程式運作時占用了目前的控制台,是以這個程式不結束我們都無法使用控制台,這就叫前台運作。預設執行程式就是前台運作的。

(2)背景運作就是讓這個程式運作,并且同時讓出控制台。這時候運作的程式還能照常運作而且還能夠不影響目前控制台的使用。

(3)讓一個程式背景運作的方法就是 ./xxx &

2.19.12.3、開機裝載驅動等其他開機自動執行

凡是開機幹啥都是在rcS檔案中設定

2.19.12.4、實際開發中rootfs的rcS是怎樣的

(1)我們以X210開發闆九鼎科技做的rootfs中rcS部分來分析

(2)分析inittab發現:sysinit執行rcS,shutdown時執行rcK。

(3)分析/etc/init.d/rcS和rcK檔案發現,rcS和rcK都是去周遊執行/etc/init.d/目錄下的S開頭的腳本檔案,差別是rcS傳參是start,rcK傳參是stop。

(4)由此可以分析出來,正式産品中的rcS和rcK都是一個引入,而不是真正幹活的。真正幹活的配置腳本是/etc/init.d/S??*。這些檔案中肯定有一個判斷參數是start還是stop,然後start時去做一些初始化,stop時做一些清理工作。

2.19.13.制作ext2格式的鏡像并燒錄啟動

2.19.13.1、确定檔案夾格式的rootfs可用

(1)設定bootargs為nfs啟動方式,然後從主機ubuntu中做好的檔案夾格式的rootfs去啟動,然後看啟動效果,作為将來的參照物。

2.19.13.2、動手制作ext2格式的鏡像

(1)

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/

(2)向./rootfs中複制内容,用cp ../rootfs2/* ./ -rf

(3)umount /dev/loop1

losetup -d /dev/loop1

(4)完成後得到的rootfs.ext2就是我們做好的rootfs鏡像。拿去燒錄即可。

2.19.13.3、燒錄鏡像并設定合适的bootargs

(1)使用fastboot燒錄制作好的rootfs.ext2到開發闆inand中

fastboot flash system rootfs.ext2

燒錄完成後重新開機系統

(2)設定bootargs為:set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext2

bootargs=root=/dev/nfs nfsroot=192.168.43.30:/home/liu/ARM/rootfs/rootfs1 ip=192.168.43.10:192.168.43.30:192.168.43.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200

(3)

出錯:說不能打開mmc通道0

原因:由于他上次就沒結局kernel中mmc初始化的問題,是以我們這個zImage就沒能初始化mmc

解決:燒錄九鼎的QT 鏡像就可以了

結果:成功運作

(4)啟動後發現現象和之前nfs方式啟動挂載rootfs後一樣的,至此rootfs制作實驗圓滿完成。

2.19.13.4、總結

(1)13節課将rootfs的制作步驟和原理已經完全清楚的講完了

繼續閱讀