NFS文件系統製作與移植

1.NFS文件系統簡介:

NFS是由Sun開發並發展起來的一項在不同機器、不同操作系統之間通過網絡共享文件的技術。在嵌入式Linux系統的開發調試階段,可以利用該技術在主機上建立基於NFS 的根文件系統,掛載到嵌入式設備,可以很方便地修改根文件系統的內容。以上討論的都是基於存儲設備的文件系統(memory-based file system),它們都可用作Linux的根文件系統。實際上,Linux還支持邏輯的或僞文件系統(logical or pseudo file system),例如procfs(proc文件系統),用於獲取系統信息,以及devfs(設備文件系統)和sysfs,用於維護設備文件。


2.在內核中添加對nfs的支持:

Networking  --->

    Networking options  --->

         [*]   IP: kernel level autoconfiguration  

         [ ]     IP: DHCP support

         [ ]     IP: BOOTP support

         [ ]     IP: RARP support   

File systems  --->

    Network File Systems  ---> 

        <*> NFS file system support

         [ ]   Provide NFSv3 client support 

         [ ]   Provide NFSv4 client support (EXPERIMENTAL)  

         [ ]   Allow direct I/O on NFS files

         < > NFS server support

        [*] Root file system on NFS  

注:對於nfs文件系統,上面紅色標註的要選上,其餘選項根據自身的情況而言。


3.參考根文件系統製作的文檔,製作用於系統啓動的NFS文件系統:

[lingyun@localhost opt]$ ls rootfs

apps    bin   dev  home  init  linuxrc  media  opt   root  stat  tmp  var

backup  data  etc  info  lib   logs     mnt    proc  sbin  sys   usr

[lingyun@localhost opt]$


確認並安裝NFS服務依賴軟件包

一般NFS服務器要提供服務,必須啓動inet,nfs, mount,portmaprpcbind這些守護進程並保持在後臺狀態運行這裏需要提示的是從RHEL6開始系統使用rpcbind替換了以前早期版本中NFS依賴的portmap服務。

在使用NFS共享文件之前,我們首先使用rpm命令確認我們安裝了這些應用程序。如果沒有安裝,則從安裝光盤中找到他們並安裝,或者使用yum安裝。下面顯示我們在安裝系統時,已經選擇安裝了NFS服務相關軟件

[lingyun@localhost opt]$ rpm -qa | grep nfs

nfs4-acl-tools-0.3.3-6.el6.x86_64

nfs-utils-lib-1.1.5-4.el6.x86_64

nfs-utils-1.2.3-36.el6.x86_64

[lingyun@localhost opt]$ rpm -qa | grep rpcbind

rpcbind-0.2.0-11.el6.x86_64

[lingyun@localhost opt]$ 


修改主機上的NFS配置文件,導出/opt目錄使用NFS共享:

backup  data  etc  info  lib   logs     mnt    proc  sbin  sys   usr  xxx

[lingyun@localhost opt]$ sudo vim /etc/exports 

/opt/ *(rw,sync,no_root_squash)

下面是一些NFS共享的常用參數:

ro 只讀訪問

rw 讀寫訪問

sync 所有數據在請求時寫入共享

async NFS在寫入數據前可以相應請求

secure NFS通過1024以下的安全TCP/IP端口發送

insecure NFS通過1024以上的端口發送

wdelay如果多個用戶要寫入NFS目錄,則歸組寫入(默認)

no_wdelay 如果多個用戶要寫入NFS目錄,則立即寫入,當使用async時,無需此設置。

hide NFS共享目錄中不共享其子目錄

no_hide 共享NFS目錄的子目錄

subtree_check 如果共享/usr/bin之類的子目錄時,強制NFS檢查父目錄的權限(默認)

no_subtree_check 和上面相對,不檢查父目錄權限

all_squash 共享文件的UIDGID映射匿名用戶anonymous,適合公用目錄。

no_all_squash 保留共享文件的UIDGID(默認)

root_squash root用戶的所有請求映射成如anonymous用戶一樣的權限(默認)

no_root_squas root用戶具有根目錄的完全管理訪問權限

anonuid=xxx 指定NFS服務器/etc/passwd文件中匿名用戶的UID

anongid=xxx 指定NFS服務器/etc/passwd文件中匿名用戶的GID

關於/etc/exports文件的更加詳細的配置說明,我們可以使用man exports命令來查看幫助手冊。

重新啓動rpcbindportmapnfs服務

使用root權限運行“service rpcbind restart(RHEL高於6.0版本)或“service portmap restart(RHEL5及以下版本)命令重啓NFS依賴的服務:

[lingyun@localhost opt]$ sudo service rpcbind restart

Stopping rpcbind:                                          [  OK  ]

Starting rpcbind:                                            [ OK  ]

使用root權限運行“service nfs restart”命令重啓NFS服務,讓其生效:

[lingyun@localhost opt]$ sudo service nfs restart

Shutting down NFS daemon:                         [  OK  ]

Shutting down NFS mountd:                          [  OK  ]

Shutting down NFS quotas:                           [  OK  ]

Shutting down NFS services:                         [  OK  ]

Starting NFS services:                                    [ OK  ]

Starting NFS quotas:                                      [  OK ]

Starting NFS mountd:                                     [  OK  ]

Starting NFS daemon:                                    [  OK  ]

[lingyun@localhost opt]$ 

使用service rpcbind status命令和“service nfs status”命令查看相關服務的運行狀態,同時可以使用“showmount –e”命令可以查看我們通過NFS服務共享的文件:

[lingyun@localhost opt]$ service rpcbind status

rpcbind (pid  3719) is running...

[lingyun@localhost opt]$ service nfs status

rpc.svcgssd is stopped

rpc.mountd (pid 7935) is running...

nfsd (pid 7962 7961 7960 7959 7958 7957 7956 7955) is running...

rpc.rquotad (pid 7931) is running...

[lingyun@localhost opt]$ showmount -e

Export list for localhost.localdomain:

/opt           *

/usr/local/src *

[lingyun@localhost opt]$ 

測試NFS訪問

在另外一個Linux機器上,或者在本機上通過mount命令掛載並測試如下:

[lingyun@localhost opt]$ sudo mkdir -p /mnt/nfs

[lingyun@localhost opt]$ sudo mount -t nfs 192.168.1.3:/opt /mnt/nfs

[lingyun@localhost opt]$ mount

/dev/sda2 on / type ext4 (rw)

proc on /proc type proc (rw)

sysfs on /sys type sysfs (rw)

devpts on /dev/pts type devpts (rw,gid=5,mode=620)

tmpfs on /dev/shm type tmpfs (rw)

none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)

nfsd on /proc/fs/nfsd type nfsd (rw)

192.168.1.2:/var/ftp/pub on /opt/pub type nfs (rw,nolock,vers=4,addr=192.168.1.2,clientaddr=192.168.1.3)

192.168.1.3:/opt on /mnt/nfs1 type nfs (rw,vers=4,addr=192.168.1.3,clientaddr=192.168.1.3)

[lingyun@localhost opt]$ ls /mnt/nfs/

buildroot-2012.08  mtd  pub  rootfs

[lingyun@localhost opt]$ ls /mnt/nfs1/rootfs/

apps    bin   dev  home  init  linuxrc  media  opt   root  stat  tmp  var

backup  data  etc  info  lib   logs     mnt    proc  sbin  sys   usr xxx

[lingyun@localhost opt]$ ls /opt/rootfs/

apps    bin   dev  home  init  linuxrc  media  opt   root  stat  tmp  var

backup  data  etc  info  lib   logs     mnt    proc  sbin  sys   usr  xxx

[lingyun@localhost opt]$ rm /mnt/nfs1/rootfs/xxx 

rm: remove write-protected regular empty file `/mnt/nfs1/rootfs/xxx'? y

[lingyun@localhost opt]$ ls /mnt/nfs/rootfs/    

apps    bin   dev  home  init  linuxrc  media  opt   root  stat  tmp  var

backup  data  etc  info  lib   logs     mnt    proc  sbin  sys   usr

[lingyun@localhost opt]$ ls /opt/rootfs/         

apps    bin   dev  home  init  linuxrc  media  opt   root  stat  tmp  var

backup  data  etc  info  lib   logs     mnt    proc  sbin  sys   usr

[lingyun@localhost opt]$ 


4.uboot設置和映像燒錄啓動

[ s3c2440@fulinux ]# set bootcmd_rootfs 'nand read 30008000 100000 400000;bootm 30008000'

[ s3c2440@fulinux ]# set bootcmd 'run bootcmd_rootfs'

注:下面這個設置只爲保存nfs的啓動bootargs參數

[ s3c2440@fulinux ]# set bootargs_nfs 'noinitrd console=ttyS0,115200 init=/linuxrc mem=64M loglevel=7 root=/dev/nfs rw nfsroot=192.168.1.3:/opt/rootfs ip=192.168.1.111:192.168.1.3:192.168.1.1:255.255.255.0:localhost.com:eth0:off'

[ s3c2440@fulinux ]# set bootargs 'noinitrd console=ttyS0,115200 init=/linuxrc mem=64M loglevel=7 root=/dev/nfs rw nfsroot=192.168.1.3:/opt/rootfs ip=192.168.1.111:192.168.1.3:192.168.1.1:255.255.255.0:localhost.com:eth0:off'

注:上面的設置中ip=<my-ip>:<serv-ip>這兩個是必須在bootargs中出現,不然可能無法啓動。

[ s3c2440@fulinux ]# set bkr 'tftp 30008000 linuxrom-fulinux.bin;nand erase 100000 400000;nand write 30008000 100000 400000'


[ s3c2440@fulinux ]# pri

bbl=nand erase 0 100000;tftp 30008000 u-boot-$cpu.bin;nand write 30008000 0 $filesize

norbbl=erase bank 1;tftp 30008000 u-boot-$cpu.bin;cp.b 30008000 0 $filesize

bkr=tftp 30008000 uImage-$cpu.gz;nand erase 100000 400000;nand write 30008000 100000 $filesize

bootcmd_rootfs=nand read 30008000 100000 400000;bootm 30008000

tpb=tftp 30008000 uImage-$cpu.gz;tftp 30800000 ramdisk-$cpu.gz;bootm 30008000 

mtdids=nand0=nand0

mtdparts=mtdparts=nand0:1M@0x0(u-boot),5M@0x100000(kernel),10M@0x600000(ramdisk),10M@0x1000000(cramfs),20M@0x1a00000(yaffs2),20M@0x2e00000(ubifs),-(users)

bootdelay=1

baudrate=115200

ethaddr=08:00:3e:26:0a:6b

ethact=dm9000

bcramfs=tftp 30800000 rootfs.cramfs;nand erase f00000 600000;nand write 30800000 f00000 600000

bjffs2=tftp 30008000 rootfs.jffs2;nand erase 1e00000 1400000;nand write.jffs2 30008000 1e00000 1400000

bootargs_jffs2=noinitrd root=/dev/mtdblock4 rootfstype=jffs2 init=/linuxrc console=ttyS0,115200

bootargs_cramfs=noinitrd root=/dev/mtdblock3 rootfstype=cramfs init=/linuxrc console=ttyS0,115200

bootargs_ubifs=console=ttyS0,115200 mem=64M ubi.mtd=6 root=ubi0:rootfs rootwait rootfstype=ubifs rw

bubifs=tftp 30008000 ubifs-$cpu.img;nand erase 6e00000 900000;nand write 30008000 6e00000 900000

cpu=arm920t

brdfs=tftp 30008000 ramdisk.gz;nand erase 500000 a00000;nand write 30008000 500000 500000

filesize=4B065C

fileaddr=30008000

netmask=255.255.255.0

ipaddr=192.168.1.111

serverip=192.168.1.3

bootcmd_ramdisk=nand read 30008000 100000 400000;nand read 30800000 500000 500000;bootm 30008000

bootargs_ramdisk=console=ttyS0,115200 mem=64M initrd=0x30800000,16M root=/dev/ram0 rw loglevel=7

ip=192.168.1.111:192.168.1.3:192.168.1.1:255.255.255.0:localhost.com:eth0:off

bootcmd=run bootcmd_rootfs

bootargs_nfs=noinitrd console=ttyS0,115200 init=/linuxrc mem=64M loglevel=7 root=/dev/nfs rw nfsroot=192.168.1.3:/opt/rootfs ip=192.168.1.111:192.168.1.3:192.168.1.1:255.255.255.0:localhost.com:eth0:off

bootargs=noinitrd console=ttyS0,115200 init=/linuxrc mem=64M loglevel=7 root=/dev/nfs rw nfsroot=192.168.1.3:/opt/rootfs ip=192.168.1.111:192.168.1.3:192.168.1.1:255.255.255.0:localhost.com:eth0:off

注:也可以是下面這樣

bootargs=noinitrd console=ttyS0,115200 init=/linuxrc mem=64M loglevel=7 root=/dev/nfs rw nfsroot=192.168.1.3:/opt/rootfs ip=192.168.1.111:192.168.1.3

stdin=serial

stdout=serial

stderr=serial

Environment size: 2123/131068 bytes

[ s3c2440@guowenxue ]#

上面的bootargs參數解析:

initrd, noinitrd:

當你沒有使用ramdisk啓動系統的時候,你需要使用noinitrd這個參數,但是如果使用了的話,就需要指定initrd=r_addr,size, r_addr表示initrd在內存中的位置,size表示initrd的大小。


console=ttyS?[,options] 使用特定的串口,options可以是這樣的形式bbbbpnx,這裏bbbb是指串口的波特率,p是奇偶位,n是指的bits。不過我們一般默認會使用console=ttyS0,115200作爲參數;有時,在s3c24x0的u-boot環境變量中,我們會看到



console=ttySAC0,115200,這時因爲在Linux-2.6以後的某個版本開始(如我們移植的linux-2.6.24),將drivers/serial/s3c2410.c中設置:

#define S3C24XX_SERIAL_NAME    "ttySAC"

另外,在struct uart_driver s3c24xx_uart_drv中定義

.dev_name   = "s3c2410_serial",



這時,我們將上面的兩處定義分別修改爲下面值就OK了:

#define S3C24XX_SERIAL_NAME    "ttyS"


static struct uart_driver s3c24xx_uart_drv = {

{

  ****

  .dev_name   = "ttyS",

  ****

}


init指定的是內核啓起來後,進入系統中運行的第一個腳本,一般init=/linuxrc, 或者init=/etc/preinit,preinit的內容

一般是創建console,null設備節點,運行init程序,掛載一些文件系統等等操作。請注意,很多初學者以爲init=/linuxrc

是固定寫法,其實不然,/linuxrc指的是/目錄下面的linuxrc腳本,一般是一個連接罷了。如果內核找不到linurc文件,

將會依次搜索/sbin/init,/etc/init,bin/init,/bin/sh

mem:        指定內存大小,非必須的

loglevel:   設置內核的調試打印級別,非必須的;

lpj:   該選項爲啓動時間優化選項,非必須。LPJ值在硬件條件不變的情況下不會變化,這裏我們強制設置LPJ的值,

可以節約啓動時間。如果沒有預設該值的話,內核啓動後,使用dmesg可以看到啓動過程打印:

>: dmesg | grep BogoMIPS

Calibrating delay loop... 201.93 BogoMIPS (lpj=504832)

如果設置該值後,dmesg則會顯示:

>: dmesg | grep BogoMIPS

Calibrating delay loop (skipped)... 201.93 BogoMIPS preset

root:

用來指定rootfs的位置, 常見的情況有: 

ramdisk文件系統使用:root=/dev/ram0 rw

cramfs文件系統使用: root=/dev/mtdblock3 rootfstype=cramfs

jffs2文件系統使用:   root=/dev/mtdblock5 rootfstype=jffs2

yaffs2文件系統使用:  root=/dev/mtdblock4 rootfstype=yaffs2

NFS文件系統使用:  root=/dev/nfs



在文件系統爲基於NFS的文件系統時。指定root=/dev/nfs之後,還需要指定nfsroot。

這裏的/dev/nfs並非真的設備,而是一個告訴內核經由網絡取得根文件系統的旗標。

nfsroot這個參數告訴內核以哪一臺機器,哪個目錄以及哪個網絡文件系統選項作爲根文件系統使用。參數的格式如下:

nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]

如果指令列上沒有給定 nfsroot 參數,則將使用‘/tftpboot/%s’預設值。其它選項如下:

<server-ip> --指定網絡文件系統服務端的互聯網地址(IP address)。如果沒有給定此欄位,則使用由 nfsaddrs 變量

(見下面)所決定的值。此參數的用途之一是允許使用不同機器作爲反向地址解析協議(RARP)及網絡文件系統服務端。

通常你可以不管它(設爲空白)。

<root-dir> -- 服務端上要作爲根掛入的目錄名稱。如果字串中有個‘%s’ 符記(token),此符記將代換爲客戶端互聯網

地址之ASCII 表示法。

<nfs-options> -- 標準的網絡文件系統選項。所有選項都以逗號分開。如果沒有給定此選項欄位則使用下列的預設值:

        port            = as given by server portmap daemon

        rsize           = 1024

        wsize           = 1024

        timeo           = 7

        retrans         = 3

        acregmin        = 3

        acregmax        = 60

        acdirmin        = 30

        acdirmax        = 60

        flags           = hard, nointr, noposix, cto, ac

參數nfsaddrs設定網絡通訊所需的各種網絡接口地址。如果沒有給定這個參數,則內核核會試著使用反向地址解析協議

以及/或是啓動協議(BOOTP)以找出這些參數。其格式如下:

ip:

下面是U-boot官方文檔提供的IP參數解析:

setenv bootargs ${bootargs}

ip=${ipaddr}:${serverip}:\

${gatewayip}:${netmask}:\

${hostname:${netdev}:off

 

注意,上面換行的地方均有空格。其中 192.168.1.244是開發板的IP,192.168.1.155

是PC端(或虛擬機)的 IP,上面的IP根據自己的實際情況修改,不要弄錯了。

 

nfsaddrs=<my-ip>:<serv-ip>:<gw-ip>:<netmask>:<name>:<dev>:<auto>

<my-ip> -- 客戶端的互聯網地址。如果沒設,此地址將由反向地址解析協議(RARP)或啓動協議來決定。使用何種協議端

視配置核心時打開的選項以及 參數而定。如果設定此參數,就不會使用反向地址解析協議或啓動協議。

<serv-ip> -- 網絡文件系統服務端之互聯網地址。如果使用反向地址解析協議來決定客戶端地址並且設定此參數,則只

接受從指定之服務端傳來的迴應。要使用不同的機器作爲反向地址解析與網絡文件系統服務端的話,在此指定你的反向

地址解析協議服務端(保持空白)並在 nfsroot 參數(見上述)中指定你的網絡文件系統服務端。如果此項目空白則

使用回答反向地址解析協議或啓動協議之服務端的地址。

<gw-ip> -- 網關(gateway)之互聯網地址,若服務端位於不同的子網絡上時。如果此項目空白則不使用任何網關並假設

服務端在本地的(local)網絡上,除非由啓動協議接收到值。

<netmask> -- 本地網絡界面的網絡掩碼。如果爲空白,則網絡掩碼由客戶端的互聯網地址導出,除非由啓動協議接收到值。

<name> -- 客戶端的名稱。如果空白,則使用客戶端互聯網地址之 ASCII-標記法,或由啓動協議接收的值。

<dev> -- 要使用的網絡設備名稱。如果爲空白,所有設備都會用來發出反向地址解析請求,啓動協議請求由最先找到的

設備發出。網絡文件系統使用接收到反向地址解析協議或啓動協議迴應的設備。如果你只有一個設備那你可以不管它。

<suto> -- 用以作爲自動配置的方法。如果是 `rarp' 或是 `bootp' 則使用所指示的協議。如果此值爲`both' 或空白,

若配置核心時有打開這兩種協議則都使用。 `none' 表示不使用自動配置。這種情況下你必須指定前述欄位中所有必要的值。

此參數可以作爲 nfsaddrs 的參數單獨使用(前面沒有任何 `:` 字符),這種情況下會使用自動配置。然而,此種情況

不能使用 `none'作爲值。

下載內核:

[ s3c2440@fulinux ]# run bkr

啓動:

[ s3c2440@fulinux ]# boot


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章