配置uboot指定nfs挂载根文件系统

  • Post author:
  • Post category:其他


介绍如何使用nfs技术调试文件系统

概念

NFS是Network File System的缩写及网络文件系统。要功能是通过局域网络让不同的主机系统之间可以共享文件或目录。NFS系统和Windows网络共享、网络驱动器类似, 只不过windows用于局域网, NFS用于企业集群架构中, 如果是大型网站, 会用到更复杂的分布式文件系统FastDFS,glusterfs,HDFS

介绍

nfs实现原理

当用户读写有关的nfs下的目录, 最终由内核解析完成后驱动硬件,完成相应的操作。

1.用户进程访问NFS客户端,使用不同的函数对数据进行处理

2.NFS客户端通过TCP/IP的方式传递给NFS服务端。

3.NFS服务端接收到请求后,会先调用portmap进程进行端口映射。

4.nfsd进程用于判断NFS客户端是否拥有权限连接NFS服务端。

5.Rpc.mount进程判断客户端是否有对应的权限进行验证。

6.idmap进程实现用户映射和压缩

7.最后NFS服务端会将对应请求的函数转换为本地能识别的命令,传递至内核,由内核驱动硬件。

rpc是一个远程过程调用,那么使用nfs必须有rpc服务

使用nfs的作用

1.实现多台服务器之间数据共享

2.实现多台服务器之间数据的一致

3.在嵌入式开发中,避免频繁地对存储介质进行读写,减少时间的同时保证了存储介质的寿命。

NFS存储优点

1.NFS文件系统简单易用、方便部署、数据可靠、服务稳定、满足中小企业需求。

2.NFS文件系统内存放的数据都在文件系统之上,所有数据都是能看得见。


NFS存储缺点

1.存在单点故障, 如果构建高可用维护麻烦。(web-》nfs()-》backup)

2.NFS数据明文, 并不对数据做任何校验。

3.客户端挂载无需账户密码, 安全性一般(内网使用)

配置uboot指定nfs挂载根文件系统

嵌入式系统Linux内核对nfs文件系统的支持

->  Networking support
  ->  Networking options
      [*]   IP: kernel level autoconfiguration
 
-> File systems
  [*] Network File Systems
      <*>   NFS client support
      <*>     NFS client support for NFS  version 3
      [*]       NFS client support for the NFSv3  ACL protocol extension
      [*]   Root file system on NFS
  • 开启nfs服务(开发机)

安装nfs服务(ubuntu为例)

sudo apt-get install nfs-kernel-server -y
  • 配置好 /etc/exports
$ sudo cat /etc/exports
 
...
 
/fs_path/fs  *(rw,sync,no_root_squash,no_subtree_check)

重启nfs-kernel-server或者重启机器,使修改生效

sudo service nfs-kernel-server restart 
  • uboot修改bootargs

最好是备份好bootargs

setenv bootargs 'root=/dev/nfs nfsroot=${serverip}:/xxx/fs,tcp rw ip=${ipaddr}:${serverip}:${gatewayip}:${netmask} ::eth0:on init=/linuxrc console=ttyAMA0,115200'
saveenv
 
 
注:
${ipaddr}     开发板本身的地址
${serverip}    tftp及nfs目录所在系统的地址
${gatewayip}    网关
${netmask}      子网掩码
 
 
 
 
其中:
root=/dev/nfs
    /dev/nfs并非真的设备,而是一个告诉内核要通过网络取得根文件系统。
 
nfsroot=<server-ip>:<root-dir>
    参数nfsroot这个参数告诉内核以哪一台机器的哪个目录以及哪个网络文件系统选项作为根文件系统使用。
    <server-ip>  指定网络文件系统服务端的IP地址。如果没有指定定,则使用nfsaddrs变量指定的值。
    <root-dir>    服务端上要作为根文件系统要挂载的目录名称。
 
ip=<my-ip>:<serv-ip>:<gw-ip>:<netmask>:<name>:<dev>:<auto>
    参数ip设定网络通讯所需的各种网络接口地址。
    如果没有给定这个参数,则内核核会试着使用反向地址解析协议或是启动协议(BOOTP)以找出这些参数。
    <ipaddr>         客户端的IP地址。
    <serverip>       网络文件系统服务端的IP地址。
    <gatewayip>   网关(gateway)的IP地址。
    <netmask>      本地网络的网络掩码。如果为空白,则掩码由客户端的IP地址导出。
    <name>          客户端的名称。如果空白,则使用客户端IP地址的ASCII标记值。
    <dev>             要使用的网络设备名称。如果你只有一个设备,那么你可以不管它。一般指定为eth0
    <auto>            用以作为自动配置的方法。,可以是on可以是off
 
init=/linuxrc 指定初始化文件
 
console=ttySAC2,115200 控制台选择

至此,kernel通过nfs方式加载了根文件系统rootfs,此时在rootfs文件是在宿主机上,此时控制器和宿主机之间的网络不能出现故障,否则在控制器终端就不能访问文件系统了,所以在启动脚本中不能修改使用nfs挂载根文件系统的网卡IP地址(或者改动一致)。

常见问题

Q:挂载以后

ls -al

发现权限异常权限变成了

???

A:一般是因为:nfs服务器的配置问题

Q:挂载以后只读内核提示了 :

VFS: Mounted root (nfs filesystem) readonly on device.

,而且在文件系统中无法进行写操作(包括修改/删除文件,创建/删除目录)

A1:要么是 nfs服务器的配置中,权限与网段之间多了一个空格

/arm/fs * (rw,sync,no_root_squash,no_subtree_check) # 错误的
/arm/fs *(rw,sync,no_root_squash,no_subtree_check)  # 正确的

A2:要么是 bootargs 没有指定rw权限

root=/dev/nfs nfsroot=192.168.10.150:/xxx/fs,tcp rw ip=192.168.10.110:192.168.10.150:192.168.10.1:255.255.255.0::eth0:on 

附录:nfs参数详解

关于nfs部分,在内核文档里(Documentation/filesystems/nfs/nfsroot.txt)有详细说明,摘取部分如下:

所述的参数最终都变成了Kernel command line,传递给linux内核,内核解析Kernel command line的内容,做相应处理

2.) Kernel command line
-------------------


When the kernel has been loaded by a boot loader (see below) it needs to be
told what root fs device to use. And in the case of nfsroot, where to find
both the server and the name of the directory on the server to mount as root.
This can be established using the following kernel command line parameters:


root=/dev/nfs
This is necessary to enable the pseudo-NFS-device. Note that it's not a
real device but just a synonym to tell the kernel to use NFS instead of
a real device.


nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
If the `nfsroot' parameter is NOT given on the command line,
the default "/tftpboot/%s" will be used.


<server-ip>    Specifies the IP address of the NFS server.
        The default address is determined by the `ip' parameter
        (see below). This parameter allows the use of different
        servers for IP autoconfiguration and NFS.


<root-dir>    Name of the directory on the server to mount as root.
        If there is a "%s" token in the string, it will be
        replaced by the ASCII-representation of the client's
        IP address.


<nfs-options>    Standard NFS options. All options are separated by commas.
        The following defaults are used:
            port        = as given by server portmap daemon
            rsize        = 4096
            wsize        = 4096
            timeo        = 7
            retrans        = 3
            acregmin    = 3
            acregmax    = 60
            acdirmin    = 30
            acdirmax    = 60
            flags        = hard, nointr, noposix, cto, ac




ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
This parameter tells the kernel how to configure IP addresses of devices
and also how to set up the IP routing table. It was originally called
`nfsaddrs', but now the boot-time IP configuration works independently of
NFS, so it was renamed to `ip' and the old name remained as an alias for
compatibility reasons.


If this parameter is missing from the kernel command line, all fields are
assumed to be empty, and the defaults mentioned below apply. In general
this means that the kernel tries to configure everything using
autoconfiguration.


The <autoconf> parameter can appear alone as the value to the `ip'
parameter (without all the ':' characters before). If the value is
"ip=off" or "ip=none", no autoconfiguration will take place, otherwise
autoconfiguration will take place. The most common way to use this
is "ip=dhcp".


<client-ip>    IP address of the client.
        Default: Determined using autoconfiguration.


<server-ip>    IP address of the NFS server. If RARP is used to determine
        the client address and this parameter is NOT empty only
        replies from the specified server are accepted.


        Only required for NFS root. That is autoconfiguration
        will not be triggered if it is missing and NFS root is not
        in operation.
        Default: Determined using autoconfiguration.
         The address of the autoconfiguration server is used.


<gw-ip>    IP address of a gateway if the server is on a different subnet.
        Default: Determined using autoconfiguration.


<netmask>    Netmask for local network interface. If unspecified
        the netmask is derived from the client IP address assuming
        classful addressing.
        Default: Determined using autoconfiguration.


<hostname>    Name of the client. May be supplied by autoconfiguration,
        but its absence will not trigger autoconfiguration.
        If specified and DHCP is used, the user provided hostname will
        be carried in the DHCP request to hopefully update DNS record.
        Default: Client IP address is used in ASCII notation.


<device>    Name of network device to use.


        Default: If the host only has one device, it is used.
             Otherwise the device is determined using
             autoconfiguration. This is done by sending
             autoconfiguration requests out of all devices,
             and using the device that received the first reply.


<autoconf>    Method to use for autoconfiguration. In the case of options
which specify multiple autoconfiguration protocols,
        requests are sent using all protocols, and the first one
        to reply is used.


        Only autoconfiguration protocols that have been compiled
        into the kernel will be used, regardless of the value of
        this option.
off or none: don't use autoconfiguration
                (do static IP assignment instead)
         on or any: use any protocol available in the kernel
             (default)
         dhcp: use DHCP
         bootp: use BOOTP
         rarp: use RARP
         both: use both BOOTP and RARP but not DHCP
         (old option kept for backwards compatibility)


Default: any


nfsrootdebug
This parameter enables debugging messages to appear in the kernel
log at boot time so that administrators can verify that the correct
NFS mount options, server address, and root path are passed to the
NFS client.


rdinit=<executable file>
To specify which file contains the program that starts system
initialization, administrators can use this command line parameter.
The default value of this parameter is "/init". If the specified
file exists and the kernel can execute it, root filesystem related
kernel command line parameters, including `nfsroot=', are ignored.


A description of the process of mounting the root file system can be
found in:


Documentation/early-userspace/README
  • :内核打印信息参考
## Booting kernel from Legacy Image at 42000000 ...
   Image Name:   Linux-3.18.20
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3954962 Bytes = 3.8 MiB
   Load Address: 40008000
   Entry Point:  40008000
   Loading Kernel Image ... OK
OK
 
Starting kernel ... 
 
Booting Linux on physical CPU 0x0
Initializing cgroup subsys cpu
Linux version 3.18.20 (root@ubuntu) (gcc version 4.9.4 20150629 (prerelease) (Hisilicon_v500_20170922) ) #6 SMP Mon Oct 21 14:41:20 CST 2019
CPU: ARMv7 Processor [414fc091] revision 1 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine model: Hisilicon HI3531D DEMO Board
Memory policy: Data cache writealloc
PERCPU: Embedded 9 pages/cpu @dfbd9000 s5696 r8192 d22976 u36864
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 130048
Kernel command line: root=/dev/nfs nfsroot=192.168.1.16:/home/schips/arm/fs ip=192.168.1.11:192.168.1.16:192.168.1.1:255.255.255.0::eth0:on init=/linuxrc console=ttyAMA0,115200
 
hi_gmac_v200 100a0000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
IP-Config: Complete:
     device=eth0, hwaddr=1a:ea:05:46:af:7c, ipaddr=192.168.10.111, mask=255.255.255.0, gw=192.168.10.1
     host=192.168.10.111, domain=, nis-domain=(none)
     bootserver=192.168.10.106, rootserver=192.168.10.106, rootpath=
VFS: Mounted root (nfs filesystem) on device 0:12.
Freeing unused kernel memory: 256K (c0700000 - c0740000)