天天看點

ARM嵌入式——制作根檔案系統并使用NFS挂載運作。

制作根檔案系統并使用NFS挂載運作。

文章目錄

    • 上位機準備:
      • 添加系統啟動的必要配置檔案和腳本
      • 添加系統啟動腳本檔案rcS
      • 添加系統啟動的配置檔案fstab
    • 下位機執行
    • 案例.向根檔案系統rootfs添加自己移植或者自己制作的動态庫
      • 在根檔案系統中添加應用程式自啟動功能
        • 如何将自己制作的rootfs制作成一個單個二進制鏡像檔案呢,也就是将/opt/rootfs(目錄)->rootfs_ext4.img(單個檔案)
        • 向EMMC燒寫戰果rootfs_ext4.img
        • 切記:如果對分區進行了修改,記得要對EMMC重新分區

  • 準備busybox,安裝menuconfig所需依賴的庫:
    • sudo apt-get install build-essential
    • sudo apt-get install libncurses5
    • sudo apt-get install libncurses5-dev
  • 在busybox中執行make menuconfig
Linux Module Utilities  ---> 
       		 			 //按N鍵去除選項(insmod/lsmod/rmmod精簡版指令)
       		 			 [*] Simplified modutils (NEW)  
       		 			 去除以上選項,立馬出現完整版的指令選項:
       		 			 [*]   insmod (NEW)                                                           │ │  
  							 [*]   rmmod (NEW)                                                            │ │  
  						   [*]   lsmod (NEW) 
  						   [*]   Pretty output (NEW) 
  						   [*]   Blacklist support                                                               │ │  
  							 [*]   modprobe (NEW)                                                         │ │  
  					     [*]   depmod (NEW)
  		  儲存退出
  			注意:目前busybox提供的指令已經足夠使用

           
  • 修改Makefile進行交叉編譯:
    • vim Makefile +164 //修改為指定的交叉編譯器。
    • vim Makefile +190 //修改為ARCH=arm。(指定架構)
    • 儲存退出
  • 正式進行編譯:
    • make
    • make install
    • ls _install/ //檢視編譯生成的内容
    • cd _install; linuxrc bin sbin usr //驗證了busybox僅僅提供各種指令。
  • 建立根檔案目錄:
    • cp _install /opt/rootfs -frd
    • cd /opt/rootfs //進入制作好的根檔案系統根目錄下。
    • mkdir dev lib etc proc sys //建立必要的系統目錄。
    • mkdir home tmp var mnt //建立可選的目錄
  • 添加必要的依賴動态庫:
//擷取到編譯busybox的交叉編譯器的路徑
             which is arm-cortex_a9-linux-gnueabi-gcc
             //進入交叉編譯器的根目錄
             cd /opt/toolchains
             
             //添加libc.so.6動态庫
             find . -name libc.so.6 得到:
                ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libc.so.6
             ls ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libc.so.6 -lh 得到
             		./arm-cortex_a9-linux-gnueabi/sysroot/lib/libc.so.6 -> libc-2.18-2013.10.so
								說明libc.so.6也僅僅是一個軟連接配接檔案,是以拷貝時務必将實體檔案一塊拷走
						 cp ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libc.so.6 /opt/rootfs/lib/ -d
						 cp ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libc-2.18-2013.10.so /opt/rootfs/lib/ -d
						 
             //添加libm.so.6動态庫
             cd /opt/toolchains
             find . -name libm.so.6 得到:
                ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libm.so.6
             ls ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libm.so.6 -lh 得到
             		./arm-cortex_a9-linux-gnueabi/sysroot/lib/libm.so.6 -> libm-2.18-2013.10.so
								說明libc.so.6也僅僅是一個軟連接配接檔案,是以拷貝時務必将實體檔案一塊拷走
						 cp ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libm.so.6 /opt/rootfs/lib/ -d
						 cp ./arm-cortex_a9-linux-gnueabi/sysroot/lib/libm-2.18-2013.10.so /opt/rootfs/lib/ -d
    		
      		   //切記切記切記:最後還要添加動态庫使用時所需的加載器
      		   cd /opt/toolchains
      		   find . -name ld-*  得到加載器
      		      ./arm-cortex_a9-linux-gnueabi/sysroot/lib/ld-2.18-2013.10.so
                ./arm-cortex_a9-linux-gnueabi/sysroot/lib/ld-linux.so.3
						 cp ./arm-cortex_a9-linux-gnueabi/sysroot/lib/ld-* /opt/rootfs/lib/ -d
           

  • inittab配置檔案
cd /opt/rootfs/
   vim etc/inittab 添加如下内容
   ::sysinit:/etc/init.d/rcS
   ::respawn:-/bin/sh
   儲存退出
           
  • 說明:系統啟動流程
  • 上電CPU從EMMC的512位元組運作uboot
  • ->uboot運作首先進行硬體初始化,然後根據bootcmd從某個地方加載核心到記憶體并且啟動核心, 在啟動核心之前給核心傳遞參數通過bootargs。
  • ->核心uImage啟動,首先做7大子系統的初始化最後根據bootargs到某個地方找根檔案系統rootfs。
  • ->核心找到rootfs以後,核心啟動rootfs中的/sbin/init 第一号程序,第一号程序init首先打開rootfs目錄下的etc/inittab檔案,第一号程序init會解析inittab檔案,首先找到sysinit關鍵字,一旦找到此關鍵字, 第一号程序會建立一個子程序執行sysinit關鍵字指定的, 腳本程式etc/init.d/rcS,父程序第一号程序會等待子程序, 執行完rcS腳本程式
  • ->子程序執行完rcS腳本程式以後,父程序init繼續執行,繼續解析inittab檔案,找到respawn關鍵字,一旦找到這個關鍵字,父程序init繼續建立一個子程序,子程序就會執行respawn對應的程式/bin/sh,父程序繼續等待子程序 至此啟動了一個shell程式,使用者可以輸入各種指令

存于根檔案系統rootfs的etc/init.d/目錄下
               cd /opt/rootfs
               mkdir etc/init.d/
               vim etc/init.d/rcS 添加如下内容
               mount -a 
               mkdir /dev/pts
               mount -t devpts devpts /dev/pts
               echo /sbin/mdev > /proc/sys/kernel/hotplug
               mdev -s
               儲存退出即可
           
  • mount -a:系統會自動解析fstab配置檔案,系統根據此配置檔案進行一系列的挂接動作。
  • mount -t devpts devpts /dev/pts:将虛拟檔案系統devpts挂接到/dev/pts目錄下,将來/dev/pts目錄就可以作為 devpts虛拟檔案系統的入口 此指令用于将來可以遠端登入開發闆, 例如:telnet
  • echo /sbin/mdev > /proc/sys/kernel/hotplug: 向檔案/proc/sys/kernel/hotplug寫入字元串"/sbin/mdev" 起始就是告訴核心驅動将來建立裝置檔案的程式(人)是/sbin/mdev
  • mdev -s:系統啟動,将核心驅動對應的裝置檔案進行自動建立

存于根檔案系統rootfs的etc目錄下 
               cd /opt/rootfs
               vim etc/fstab 添加如下内容
                proc   /proc   proc    defaults   0   0
                sysfs  /sys    sysfs   defaults   0   0
                tmpfs  /dev    tmpfs   defaults   0   0
               儲存退出
           
  • 說明:
  • 第一列:表示要挂接的裝置
               
  • 第二列:表示挂接點,将來的入口
               
  • 第三列:表示指定的檔案系統格式
               
  • 第四,五,六:分别指定通路權限
               
  • 結論:
  • 将來/proc目錄,/sys目錄,/dev/目錄分别作為procfs,sysfs,tmpfs三種虛拟檔案系統的入口并且以上三種虛拟檔案系統将來建立的内容都是核心來建立,并且分别建立到/proc,/sys,/dev/三個目錄中,關鍵的關鍵,這三個目錄下将來核心建立的目錄也好,檔案也好,都是存在于記憶體中,掉電就會丢失!
               

重新開機下位機,進入uboot指令行執行:
              setenv bootargs root=/dev/nfs nfsroot=192.168.1.8:/opt/rootfs 
               ip=192.168.1.110:192.168.1.8:192.168.1.1:255.255.255.0 init=/linxurc 
               console=ttySAC0,115200 maxcpus=1
              saveenv
              tftp 48000000 uImage
              bootm 48000000 //檢視是否能夠挂接自己制作的根檔案系統
              注意:shell終端之前的列印資訊仔細看,是否有錯誤!
           
  • 在自己制作的根檔案系統中添加一個應用程式
  • 上位機執行:
cd /opt/rootfs
   vim helloworld.c //最好是線程程式
   arm-cortex_a9-linux-gnueabi-gcc -o helloworld helloworld.c
           
  • 下位機測試:
cd /
           ls
              helloworld
           ./helloworld //看是否能夠正常運作
           
  • 是否出現類似:libxxx.so…找不到
  • 問:如何解決呢?
  • 答:隻需到交叉編譯器中找到對應的動态庫并且 拷貝到根檔案系統rootfs的lib目錄下 注意軟連接配接問題噢!
  • 問:cannot run /etc/init.d/rcS: Permission denied
  • 答:rcS腳本檔案沒有可執行權限,解決辦法:
cd /opt/rootfs
 chmod 777 etc/init.d/rcS
           

實施步驟:

1.明确:自己移植或者自己制作的動态庫一律不允許放到根檔案系統rootfs

的必要目錄lib下,要單獨存放,注意設定環境變量

2.上位機執行:

mkdir /opt/rootfs/home/applib  
  cd /opt/rootfs/home/applib
  vim test.h //聲明 添加如下内容
    #ifndef __TEST_H
    #define __TEST_H
    extern void my_test(void);
    #endif
  儲存退出
  vim test.c //定義 添加如下内容
  #include <stdio.h>
  void my_test(void)
  {
  	printf("%s\n", __func__);
  }
  儲存退出
  
  vim main.c //調用 
  #include <stdio.h> 
  #include "test.h" 
  
  int main(void)
  {
  	my_test(); //調用
  	return 0;
  }  
  
  編譯:
  arm-cortex_a9-linux-gnueabi-gcc -shared -fpic -o libtest.so test.c 
  arm-cortex_a9-linux-gnueabi-gcc -o main main.c -L. -ltest
  注意:不要将libtest.so拷貝到/opt/rootfs/lib下,相當危險!
  
  下位機測試:
  進入下位機的linux系統,執行:
  cd /home/applib 
  ls
     libtest.so main
  ./main  //勢必提示libtest.so找不到
  解決辦法:
  export LD_LIBRARY_PATH=/home/applib:$LD_LIBRARY_PATH
  然後
  ./main
           

  • 上位機實施步驟:
cd /opt/rootfs
vim etc/init.d/rcS 在檔案最後添加如下内容:
export LD_LIBRARY_PATH=/home/applib:$LD_LIBRARY_PATH
/home/applib/main &
儲存退出
           

重新開機下位機,看main程式是否能夠自己運作

  • 問:rootfs_ext4.img從何而來?
  • 答:rootfs_ext4.img僅僅是根檔案系統rootfs一個鏡像檔案而已,此鏡像中同樣包含了根檔案系統rootfs的内容

cd /opt/
  sudo dd if=/dev/zero of=rootfs_ext4.img bs=1k count=8196
           
  • 指令說明:
  • dd:用于建立一個單個鏡像檔案
  • if=/dev/zero:将來建立的單個鏡像檔案裡面的内容全部來自裝置/dev/zero, /dev/zero裝置能夠源源不斷産生0資料
  • of=rootfs_ext4.img:指定将來建立單個鏡像檔案名, 并且此檔案裡面填充全0
  • bs=1k:生成的rootfs_ext4.img以塊為機關,一塊1024位元組
  • count=8196:總共8196塊
  • 結論:生成的rootfs_ext4.img資料塊為8MB
sudo mkfs.ext4 rootfs_ext4.img //格式化鏡像檔案rootfs_ext4.img
                                 //把rootfs_ext4.img比作U盤
                                 指定的檔案系統格式為ext4
                                 //類似windows下格式化U盤
  
  sudo mkdir /mnt/initrd //建立一個目錄
  sudo mount -t ext4 -o loop rootfs_ext4.img /mnt/initrd
           
  • 挂接rootfs_ext4.img到目錄/mnt/initrd,并且指定的檔案系統類型ext4, 挂接指令的結果就是将來隻需要通路/mnt/initrd,本質就是在通路rootfs_ext4.img裡面的内容。
  • sudo cp /opt/rootfs/* /mnt/initrd -frd //向目錄initrd,拷貝rootfs的内容,本質上就是向rootfs_ext4.img,拷貝rootfs的内容,結果是拷貝完畢,rootfs_ext4.img裡面的内容就是/opt/rootfs裡面的内容。
  • sudo umount /mnt/initrd //解除安裝/mnt/initrd,将來initrd不再作為rootfs_ext4.img的入口。
  • cp rootfs_ext4.img /tftpboot至此第一天燒寫系統使用的rootfs_ext4.img就是這麼來的!

  • 下位機重新開機,進入uboot指令行模式執行:
  • 1.向下位機部署系統軟體之前,切記記得要進行分區規劃

    EMMC存儲空間的劃分:

    0–512----------1M--------7M--------17M---------剩餘

    uboot uImage rootfs 大片

    mmcblkboot0 mmcblk0p1 mmcblk0p2

    uboot已經完成 自己分 自己分

  • 2.燒寫uImage
tftp 48000000 uImage
  mmc write 48000000 0x800  0x3000 //emmc位址以塊機關,一塊0x200=512位元組
           
  • 3.燒寫rootfs_ext4.img
tftp 480000000 rootfs_ext4.img //下載下傳自己制作的rootfs
  mmc write 48000000 3800 5000
           
  • 4.設定系統啟動參數
setenv bootcmd mmc read 48000000 0x800  0x3000 \; bootm 48000000
  setenv bootargs root=/dev/mmcblk0p2 console=ttySAC0,115200 rootfstype=ext4
         maxcpus=1
  saveenv
           

  • 利用uboot提供的fdisk指令
fdisk 2 2 0x100000:0x600000 0x700000:0xa00000
           
  • 第一個‘2’:表示emmc
               
  • 第二個‘2’:表示分兩個分區(uImage+rootfs),uboot分區不用做。
    0x100000:0x600000:第二個分區的起始位址和大小
    0x700000:0xa00000:第三個分區的起始位址和大小
               

繼續閱讀