<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > ARM Linux根文件系統(tǒng)Root Filesystem的制作

          ARM Linux根文件系統(tǒng)Root Filesystem的制作

          作者: 時間:2016-11-09 來源:網(wǎng)絡 收藏
          http://xianzilu.spaces.live.com/blog/fakehandlerpage.aspx?wa=wsignin1.0

          http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!290.entry

          本文引用地址:http://www.ex-cimer.com/article/201611/317986.htm

          關于根文件系統(tǒng)的制作,網(wǎng)絡上有很多文章,大多數(shù)都只講到建幾個目錄,然后用Busybox做個Shell,有很多關鍵的東西沒有說。經(jīng)過很長時間的摸爬滾打,我終于能夠白手起家建立一個根文件系統(tǒng)了。其實我也不懂得原理,只是告訴大家我的作法,其中也不免有錯誤,歡迎大家指正。

          首先介紹根文件系統(tǒng)的組成:目錄、Shell、庫、腳本,一個個來。
          • 目錄
          根文件系統(tǒng)要包含這些必須有的目錄:/dev、/bin、/usr、/sbin、/lib、/etc、/proc、/sys
          /dev是devfs(設備文件系統(tǒng))或者udev的掛在點所在。在使用devfs的內(nèi)核里如果沒有/dev,根本見不到Shell啟動的信息,因為內(nèi)核找不到/dev/console;在使用udev的系統(tǒng)里,也事先需要在/dev下建立console和null這兩個節(jié)點。關于devfs和udev的區(qū)別,網(wǎng)上很多文章說。當然如果你的內(nèi)核已經(jīng)不支持devfs了(2.6.12以后),可以使用純純的靜態(tài)節(jié)點。也就是用mknod人工生成。
          /bin、/usr/bin、/usr/sbin、/sbin是編譯Busybox這個Shell時候就有的,用于存放二進制可執(zhí)行文件,就不多解釋了。
          /lib用于存放動態(tài)鏈接庫。網(wǎng)上很多文章都說靜態(tài)編譯Busybox,可以省去建庫的麻煩過程。這樣做只能讓Busybox啟動,我們自己寫的,或者是編譯的軟件包還是需要動態(tài)庫的。除非全部靜態(tài)編譯,你可以試試,一個Hello world就要幾百k。關于庫的內(nèi)容后面仔細說。
          /etc是用來存放初始化腳本和其他配置文件的。關于初始化腳本的內(nèi)容后面仔細說。
          /proc是用來掛載存放系統(tǒng)信息虛擬文件系統(tǒng)——“proc文件系統(tǒng)”,“proc文件系統(tǒng)”在內(nèi)核里面可以選。如果沒有“proc文件系統(tǒng)”,很多Shell自己的命令就沒有辦法運行,比如ifconfig。“proc文件系統(tǒng)”不像devfs可以自動掛載,它需要使用初始化腳本掛載。另外,udev也需要“proc文件系統(tǒng)”的支持。
          /sys用于掛載“sysfs文件系統(tǒng)”,“sysfs文件系統(tǒng)”在內(nèi)核里面可以選。目前我認為它就是給udev提供支持的,。“sysfs文件系統(tǒng)”也需要使用初始化腳本掛載。
          另外還可以有/tmp、/mnt、/swp、/var這樣的不是嵌入式系統(tǒng)必須的目錄,在說完Shell的制作之后,我再談建立目錄的事情。
          • Shell
          Shell很簡單,就是Busybox,上網(wǎng)下載一個來:http://www.busybox.net/downloads/。說Busybox和arm-linux-gcc有兼容性問題,不過我覺得那是比較低版本的時代問題了,我用Busybox 1.8.2和arm-linux-gcc 3.4.1/3.3.2都可以。解壓縮以后找到Makefile里面的ARCH和CROSS_COMPILE,改成:
          ARCH ?= arm
          CROSS_COMPILE ?= /usr/local/arm/3.4.1/bin/arm-linux-
          當然CROSS_COMPILE由你自己的編譯器位置決定,然后
          # make menuconfig
          # make
          # make install
          注意配置的時候把一些uCLinux Only的東西去掉,不然會錯;配置的時候還可以修改安裝位置,默認是在Busybox下的“_install”。
          之后就可以在Busybox生成的Shell基礎上建立根文件系統(tǒng)了,我就用命令來說吧,Busybox在/home/lxz/busybox,根文件系統(tǒng)在/home/lxz/rootfs
          # mkdir /home/lxz/rootfs
          # cd /home/lxz/busybox/_install
          # cp -r ./ /home/lxz/rootfs
          # cd /home/lxz/rootfs
          # mkdir dev
          # mkdir etc
          # mkdir lib
          # mkdir proc
          # mkdir sys
          # mkdir tmp
          如果不用devfs,下面的命令是必須的。必須以root用戶執(zhí)行(用su命令可以切換為root,切換后用exit命令可以返回普通用戶):
          # cd /home/lxz/rootfs/dev
          # mknod -m 660 console c 5 1
          # mknod -m 660 null c 1 3
          如果不使用devfs沒有這兩個靜態(tài)節(jié)點,console的提示根本就看不到,出現(xiàn)的現(xiàn)象可能是內(nèi)核提示Free init memory: XXK之后,Warning: Unable to find a initial console之類的,具體的單詞記得不是很準確。我沒有試過使用udev的時候沒有這兩個靜態(tài)節(jié)點的情況,反正放了也不影響把/dev掛載為tmpfs。
          如果使用udev,還需要把udevd、udevstart、udevadmin這三個文件放到/sbin里面(我使用udev-117,網(wǎng)上介紹較多的udev-100有9個文件要放)。
          庫可是一件非常麻煩的事請。我建議初學者拷貝買的開發(fā)板里面帶的文件系統(tǒng)的庫,如果開發(fā)板的文件系統(tǒng)是映像,只需要把映像掛載在某個目錄下就可以訪問,假設映像叫做rootfs.cramfs,可以這樣
          # mkdir /home/lxz/evb_rootfs
          (切換為root用戶)
          # mount -o loop rootfs.cramfs /home/lxz/evb_rootfs
          (可以切換為普通用戶)
          # cd /home/lxz/evb_rootfs/lib
          # cp -r ./ /home/lxz/rootfs/lib
          一般開發(fā)板里都會帶有很多庫,但是總體積卻比較大。可以刪掉一些不用的庫來減小體積,但是,,我也不知道那些庫具體含有什么函數(shù),什么情況刪什么;也許以后我會把這部分補上。如果覺得庫體積太大,也可以自己編譯glibc或者uclibc,但是這是非常繁瑣的事請——目前我認為庫應該和編譯器arm-linux-gcc一起制作。有個傻瓜式的方案是使用cross-tool,下載地址:http://www.kegel.com/crosstool/。雖然cross-tool是用來制作交叉編譯器的,但是其過程中生成的glibc卻可以作為副產(chǎn)品為我們所用。cross-tool的使用可以看我之前的這篇文章http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!274.entry。在成功制作了交叉編譯器之后,就可以從cross-tool的目錄里把glibc取出來,假設cross-tool的路徑是/home/lxz/cross-tool,編譯出的編譯器叫做arm-linux-gnu-gcc,gcc版本3.4.5,glibc版本2.3.6,想要把glibc庫拷貝到/home/lxz/glibc,下面的操作還是用命令來說明。
          # cd /home/lxz/cross-tool/build/arm-linux-gnu-gcc/gcc-3.4.5-glibc-2.3.6/build-glibc
          # ../glibc-2.3.6/configure --prefix=/home/lxz/glibc
          # make install
          等候安裝結(jié)束
          # cd /home/lxz/glibc
          # cp -r lib /home/lxz/rootfs
          這樣就把glibc的大部隊拷貝好了,但是這樣還缺兩個庫,我們繼續(xù)
          # cd /home/lxz/cross-tool/build/arm-linux-gnu-gcc/gcc-3.4.5-glibc-2.3.6/build-gcc/gcc
          # cp libgcc_s.so* /home/lxz/rootfs/lib
          還缺少一個libtermcap庫,這個就稍微有些麻煩。libtermcap-2.0.8-35-armv4l源碼包的下載地址是http://www.netwinder.org/mirror/pub/netwinder/SRPMS/nw/9/libtermcap-2.0.8-35.src.rpm,你也可以在這里http://www.netwinder.org/allsrpms.html找到其他版本的。假設libtermcap-2.0.8-35.src.rpm下載到了/home/lxz/libtermcap,下面繼續(xù)用命令說明。
          # cd /home/lxz/libtermcap
          # rpm2cpio libtermcap-2.0.8-35.src.rpm | cpio -ivd
          # tar xvjf termcap-2.0.8.tar.bz2
          接下來要打13個補丁,很汗啊,請一定按照下面的順序來打補丁
          # patch -p0 -i termcap-2.0.8-shared.patch
          # patch -p0 -i termcap-2.0.8-setuid.patch
          # patch -p0 -i termcap-2.0.8-instnoroot.patch
          # patch -p0 -i termcap-2.0.8-compat21.patch
          # patch -p0 -i termcap-2.0.8-xref.patch
          # patch -p0 -i termcap-2.0.8-fix-tc.patch
          # patch -p0 -i termcap-2.0.8-ignore-p.patch
          # patch -p0 -i termcap-buffer.patch
          # patch -p0 -i termcap-2.0.8-bufsize.patch
          # patch -p0 -i termcap-2.0.8-colon.patch
          # patch -p0 -i libtermcap-aaargh.patch
          # patch -p0 -i termcap-2.0.8-glibc22.patch
          # patch -p0 -i libtermcap-2.0.8-ia64.patch
          然后到/home/lxz/libtermcap/termcap-2.0.8里,找到Makefile,修改其中的CC和AR,
          CC = /usr/local/arm/3.4.1/bin/arm-linux-gcc
          AR = /usr/local/arm/3.4.1/bin/arm-linux-ar
          當然,你的編譯器在哪里就改成相應的內(nèi)容。如果嫌麻煩,可以從本站資料頁面下載我已經(jīng)打好補丁,修改好Makefile的包,地址http://cosine.oicp.net/project/common/termcap-2.0.8.tar.bz2。需要注意的是,這個包里CC = arm-linux-gcc、AR = arm-linux-ar,請設置好缺省路徑。然后就可以編譯了:
          # cd /home/lxz/libtermcap/termcap-2.0.8
          # make
          # ln -s libtermcap.so.2.0.8 libtermcap.so.2
          # cp libtermcap.so* /home/lxz/rootfs/lib
          這樣,Shell啟動所需要的基本庫就都備齊了。但是,這些庫里面還含有調(diào)試信息,體積稍大,可以把這些信息去掉(當然不去掉也沒有什么影響)。
          # cd /home/lxz/rootfs/lib
          # arm-linux-strip *.so*
          至此,庫就制作好了。
          • 腳本
          有了以上的東西,Shell還是不能正常工作??赡軙莾?nèi)核提示Free init memory: XXK之后就什么輸出也沒有了,這時候向終端敲入文字,可以顯示;就是沒有終端提示符,不理會輸入的命令。這是因為初始化腳本沒有啟動Shell。下面介紹這些腳本。
          首先是/etc/inittab。內(nèi)核啟動、根文件系統(tǒng)掛載之后所必須的一個文件,其中列舉了Shell和整個系統(tǒng)初始化、關閉所需的命令。如果你想讓Shell出現(xiàn),那么只需要加入這么一行“::askfirst:/bin/ash”。當然如果在編譯Busybox的時候選擇的shell不是“ash”,而是hush、lash、msh之類,那就改成相應的東西。除了啟動Shell,inittab還干了很多事情,我就用我的inittab來說明了。注意,在編譯Busybox的時候要選上touch、syslogd、klogd等命令。
          # Startup the system
          null::sysinit:/bin/mount -o remount,rw /
          null::sysinit:/bin/mount -t proc proc /proc
          null::sysinit:/bin/mount -a
          null::sysinit:/bin/hostname -F /etc/hostname
          # Now run any rc scripts
          ::sysinit:/etc/init.d/rcS
          # Now invoke shell
          ::askfirst:/bin/ash
          # Logging junk
          null::sysinit:/bin/touch /var/log/messages
          null::respawn:/sbin/syslogd -n -m 0
          null::respawn:/sbin/klogd -n
          # Stuff to do for the 3-finger salute
          ::ctrlaltdel:/sbin/reboot
          # Stuff to do before rebooting
          null::shutdown:/usr/bin/killall klogd
          null::shutdown:/usr/bin/killall syslogd
          null::shutdown:/bin/umount -a -r
          null::shutdown:/sbin/swapoff -a
          好,把上面這些儲存為inittab,啟動系統(tǒng)。應該出現(xiàn)兩個提示,沒有/etc/fstab和/etc/init.d/rcS。目前我的理解/etc/fstab是用來執(zhí)行mount -a命令的,里面是文件系統(tǒng)的掛載表。還是用我的fstab來說明。
          #
          /dev/root / ext2 rw,noauto 0 1
          proc /proc proc defaults 0 0
          devpts /dev/pts devpts defaults,gid=5,mode=620 0 0
          tmpfs /tmp tmpfs defaults 0 0
          sysfs /sys sysfs defaults 0 0
          還有/etc/init.d/rcS,這在PC上是用來執(zhí)行/etc/init.d下所有初始化腳本的一個腳本,,請原諒我不懂得怎么寫這種腳本,對于嵌入式系統(tǒng),根本不需要這么復雜,直接寫在/etc/init.d/rcS里面了。還是用我的/etc/init.d/rcS來說明,其中啟動udev的那些指令對于使用靜態(tài)設備節(jié)點和devfs的系統(tǒng)不適用。
          # Start udev
          /bin/mount -t tmpfs tmpfs /dev
          /sbin/udevd --daemon
          /sbin/udevstart
          # Configure net interface
          /sbin/ifconfig lo 127.0.0.1 up
          /sbin/route add -net 127.0.0.0 netmask 255.0.0.0 lo
          /sbin/ifconfig eth0 192.168.2.25 netmask 255.255.255.0
          /sbin/route add default gw 192.168.2.1
          如果用的是udev,還必須有udev的配置腳本。這個寫起來有些麻煩,我們可以直接用udev自己帶的那些腳本,位置在udev目錄下的etc/udev/udev.conf和etc/udev/rules.d里面的文件。把這些放到根文件系統(tǒng)中去,etc/udev/udev.conf變?yōu)楦募到y(tǒng)的/etc/udev/udev.conf,etc/udev/rules.d里面的文件變?yōu)?etc/udev/rules.d里面的文件。
          至此,一個可用的最簡單文件系統(tǒng)就完成了。之后,可以使用mkcramfs、mkyaffs之類的工具制作文件映像,這我就不多說了。需要注意的是,cramfs文件系統(tǒng)是只讀的,就算用的是initrd加載的cramfs也一樣是只讀的,這對根文件系統(tǒng)的/var目錄有一定的影響。除了本文中說的辦法,還可以用buildroot這個工具來建,但是現(xiàn)在我還在嘗試中,以后再說。如果你嫌上面的這一切都很麻煩,可以從本站資料站下載我給Linux 2.6.19內(nèi)核做的最簡文件系統(tǒng)(1.5M),地址是http://cosine.oicp.net/project/at91rm9200/root.img,cramfs格式映像。


          評論


          技術(shù)專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();