1.NFS文件系統簡介:
2.在內核中添加對nfs的支持:
NFS是由Sun開發並發展起來的一項在不同機器、不同操作系統之間通過網絡共享文件的技術。在嵌入式Linux系統的開發調試階段,可以利用該技術在主機上建立基於NFS 的根文件系統,掛載到嵌入式設備,可以很方便地修改根文件系統的內容。以上討論的都是基於存儲設備的文件系統(memory-based file system),它們都可用作Linux的根文件系統。實際上,Linux還支持邏輯的或僞文件系統(logical or pseudo file system),例如procfs(proc文件系統),用於獲取系統信息,以及devfs(設備文件系統)和sysfs,用於維護設備文件。
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,portmap或rpcbind這些守護進程並保持在後臺狀態運行. 這裏需要提示的是從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 共享文件的UID和GID映射匿名用戶anonymous,適合公用目錄。
no_all_squash 保留共享文件的UID和GID(默認)
root_squash root用戶的所有請求映射成如anonymous用戶一樣的權限(默認)
no_root_squas root用戶具有根目錄的完全管理訪問權限
anonuid=xxx 指定NFS服務器/etc/passwd文件中匿名用戶的UID
anongid=xxx 指定NFS服務器/etc/passwd文件中匿名用戶的GID
關於/etc/exports文件的更加詳細的配置說明,我們可以使用man exports命令來查看幫助手冊。
重新啓動rpcbind或portmap和nfs服務
使用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