Mounting the root filesystem via NFS (nfsroot)
英文原文位于inux内核源代码中的"Documentation/filesystems/nfs/nfsroot.txt"。
1996年由Gero Kuhlmann <gero@gkminix.han.de>初次编写,
1997年经Martin Mares <mj@atrey.karlin.mff.cuni.cz>,
2006年经Nico Schottelius <nico-kernel-nfsroot@schottelius.org>和Horms <horms@verge.net.au>更新。
为了使用一个无磁盘的系统(例如一个X终端或打印机),将根文件系统存放在非磁盘设备是必要的。它可以是通过NFS挂载的一个initramfs文件(参考Documentation/filesystems/ramfs-rootfs-initramfs.txt),或者一个ramdisk文件(参考Documentation/initrd.txt)或者一个文件系统。以下内容描述了如何通过NFS获取linux的根文件系统来启动系统。下文的客户端('client')表示无磁盘系统,服务器端('server')表示NFS服务器。
1.)启动nfsroot功能
为了使用nfsroot功能,在编译配置时,NFS客户端必须被选择为内置(built-in, 非模块)文件系统。NFS客户端被设置为内置,nfsroot选项将变为可选项,选择后才支持nfsroot功能(译者注:在没有将NFS客户端设置为内置文件系统时,nfsroot选项是不可见的)。
对于网络配置选项,选择内核自动配置,以及相应的自动配置类型。将DHCP,BOOTP和RARP三种类型全部选择上是最靠谱的。
2.)内核命令行参数
当引导加载程序(bootloader)加载一个linux内核时,需要知道使用的是什么根文件设备(root fs device)。在使用nfsroot时,需要知道从哪儿获取服务器地址和可挂载为根文件的目录名。可以通过以下内核命令行参数来设置nfsroot:
root=/dev/nfs
启动虚拟NFS设备(pseudo-NFS-device)所必需的参数。需要注意,/dev/nfs不是一个真实的设备,它只是一个告诉内核使用NFS功能来替换真实设备的一个符号。
nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
如果在内核启动命令行中没有指定'nfsroot'参数,内核将使用默认的"/tftpboot/%s"参数。
<server-ip> 指定NFS服务器的IP地址。默认IP地址是从'ip'参数中获取的(参见下一个参数)。该参数允许IP自动配置与NFS使用不同的服务器。
<root-dir> 将挂载为根文件系统的服务器端目录名。如果有"%s"标记在配置字符串中,它将被ASCII表示的客户端IP地址所替代。
<nfs-options> 规范的NFS选项。所有选项通过逗号(',')来分隔。默认使用以下配置,
port |
由服务器端的端口映射进程所给定 (centos7以前版本叫portmap,以后叫rpcbind) |
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>:<dns0-ip>:<dns1-ip>
该行参数告诉内核如何配置设备的IP地址以及如何配置IP路由表。起初被叫做'nfsaddrs',但是现在启动时IP配置已经独立于NFS,所以被重命名为'ip'并且为了兼容性旧名称'nfsaddrs'将作为别名存在。
如果没有在内核命令行参数中设置该参数,所有项将被视为空处理,所有默认值将按后面具体项中说明。通常是内核尝试自动配置所有项。
其中<autoconf>项可以单独地存在于'ip'参数中(没有任何的':')。如果值被设置为"ip=off"或者"ip=none",将不会被替换成自动配置,否则会被替换为自动配置。使用得最多的设置是"ip=dhcp"。
<client-ip> 客户端的IP地址。默认:通过自动配置获取。
<server-ip> NFS服务器的IP地址。如果使用RARP来获取客户端地址,并且该参数不为空时所指定的服务器才会被接受。
只有NFS root需要该参数。如果没有设置该参数或者不是使用的NFS root,那么自动配置将不会被触发。
默认:通过自动配置获取。将使用用于自动配置的服务器地址。
<gw-ip> 如果服务器位于不同的网段,那么需要通向IP地址相应的网关。默认:通过自动配置获取。
<netmask> 本地网络设备的子网掩码。如果没有指定,设备的子网掩码将从客户端IP地址的派生地址获取。默认:通过自动配置获取。
<hostname> 客户端名。可以通过自动配置来支持,但是如果不指定将不会触发自动配置。如果指定了该参数并且是使用的DHCP方式,用户指定的hostname将被应用于DHCP请求中进行DNS记录的更新。默认:所使用客户端IP地址的ASCII形式。
<device> 所使用的网络设备名。默认:如果本地只有一个设备,那么将直接使用它。否则将通过自动配置决定。它将通过所有设备发送自动配置请求,然后使用最先收到回复的那个设备。
<autoconf> 使用自动配置。如果设备了多个自动配置协议(DHCP/BOOTP/RARP),将使用所有协议都发送自动配置请求,然后使用最先收到回复的那个协议。
该选项中设置的协议只有被编译进内核的才能够使用。
off或者none:不使用自动配置(使用指定的IP地址)
on或者any:使用内核中任一可用的协议
dhcp: 使用DHCP
bootp: 使用BOOTP
rarp: 使用RARP
both: 使用BOOTP和RARP但不使用DHCP (为了向后兼容所保留的旧选项)
如果使用dhcp协议,客户端可以按以下格式使用“ip=dhcp,client-id-type,client-id-value”。默认:any
<dns0-ip> IP地址的第一个命名服务器。从/proc/net/pnp(在嵌入式系统中通常链接到/et/resolv.conf)中获取导出的值。
<dns1-ip> IP地址的第二个命名服务器。同上。
nfsrootdebug
该选项将开启内核输出调试信息。在启动时,管理员可以通过输出的信息来检查传入NFS客户端的NFS挂载选项,服务器地址和根路径等是否正确。
rdinit=<executable file>
管理员可以通过该参数指定包含有系统初始化程序的文件名。默认值是"/init"。如果指定的文件有效,并且内核可以运行,那么根文件系统相关的内核命令行参数(包括'nfsroot=')将被忽略。
[译者注] 该方法已经过时,dracut支持但不推荐使用。更多详情可参考man dracut.cmdline中关于NFS的描述。
关于处理挂载根文件系统的描述可以在该文件中获得:Documentation/early-userspace/README
3.) 引导程序
加载内核程序到内存有很多不同的方法。主要依赖于可供选择的设施:
3.1) 使用syslinux从软盘启动
在编译内核时,使用syslinux来创建一个可启动软盘的简单方式是,使用zdisk或者bzdisk来生成使用zimage或bzimage镜像的目标文件。两种目录文件都可以接收FDARGS参数,该参数可以用于指定内核命令行参数。例如:
make bzdisk FDARGS="root=/dev/nfs"
注意,运行该命令进需要访问磁盘设备/dev/fd0。
关于syslinux的更多详情以及如何创建基于磁盘的预先编译内核可参考http://syslinux.zytor.com/。
注意:以前可以通过dd命令将内核直接写入到软盘,通过rdev管理启动设备,然后使用生成的软盘启动系统。linux不再支持该方法的内核启动。
3.2) 使用isolinux从cdrom启动
当编译内核时,使用isolinux来创建一个可启动cdrom的简单方式是,使用bzimage镜像的isoimage目标文件。与zdisk和bzdisk类似,目录文件可接收FDARGS参数,该参数可以用于指定内核命令行参数。例如:
make isoimage FDARGS="root=/dev/nfs"
生成的iso镜像文件位于arch/<ARCH>/boot/image.iso。可以通过类似cdrecord的工具将iso文件写入到cdrom。例如:
cdrecord dev=ATAPI:,, arch/x86/boot/image.iso
关于isolinux的更多详细信息,以及如何创建基于磁盘的预先编译内核可参考http://syslinux.zytor.com/。
3.3) 使用LILO
当使用LILO时,所有需要的命令行参数可以通过位于LILO配置文件中的'append='项进行设置。
但是,为了使用'root='来指定内核命令行启动参数,仍然需要创建一个临时的root设备,它可以在LILO运行后被删除。
mknod /dev/boot255 c
关于配置LILO的详细信息可以参考其相关的文件。
3.4) 使用GRUB
当使用GRUB时,内核参数可以简单地添加到内核设置的后面:
kernel <kernel> <parameters>
3.5) 使用loadlin
loadin可以用于从一个DOS命令提示符启动Linux,而不需要挂载本地磁盘作为root。虽然该方法没有经过作者的确认,但是它的配置方式应该与LILO相类似。
更多详情请参考loadin的文档。
3.6) 使用启动ROM
这可能是无磁盘启动最优雅的方式。可以使用TFTP协议来加载基于启动ROM的内核。该文档作者不知道任何支持通过网络加载linux的非商业启动ROM。但是,有启动ROM的两种*实现,netboot-nfs和etherboot,两者都位于sunsite.unc.edu并且两者都包含了无磁盘linux客户端启动的所有信息。
3.7) 使用pxelinux
Pxelinux可以通过PXE引导程序(众多现代网卡都包含该功能)启动linux。
当使用pxelinux时,内核镜像可以通过"kernel <relative-path-below /tftpboot>"进行指定。nfsroot参数将通过"append"项被添加到内核中。通常使用串行控制台与pxelinux进行连接,更多详情请参考Documentation/serial-console.txt。
关于pxelinux的更多详情以及如何创建基于磁盘的预先编译内核可参考http://syslinux.zytor.com/。
4.) 致谢
内核中nfsroot代码和RARP的支持已经由 Gero Kuhlmann <gero@gkminix.han.de>编写完成。
剩下的IP层自动配置代码已经由 Martin Mares <mj@atrey.karlin.mff.cuni.cz>编写完成。
为了编写最初版本的nfsroot,作者还要感谢Jens-Uwe Mager <jum@anubis.han.de>的帮助。