TL;DR:我尝试告诉 Qemu 机器上的内核从 NFS 服务器启动 /sbin/init,但出现内核恐慌(未同步:VFS:无法在未知块 (2,0) 上挂载根文件系统)。我为此使用了以下命令:
kvm \
-netdev tap,id=totou,ifname=tap1 -device e1000,netdev=totou,mac=52:54:00:12:34:57 \
-kernel /tmp/bzImage \
-append "root=/dev/nfs rw nfsroot=10.0.2.3:/serverNFS ip=dhcp" \
-m 6G
更详细的解释:
我编译了一个内核(linux-4.8.6):
make defconfig
make -j8
cp arch/x86/boot/bzImage /tmp
我还有一个mydisk.qcow2
由创建的磁盘qemu-img
,它有一个 ext4 分区,其中只有 /sbin/init。其中 init 是结果gcc -static -o init init.c
,而 init.c 是:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("Hello init\n");
while(1)
sleep(100);
return 0;
}
然后我运行 qemu (kvm):
kvm \
-kernel /tmp/bzImage \
-append "root=/dev/sda1 rw" \
-hda mydisk.qcow2 \
-m 6G
一切按预期工作:内核启动并启动init。
然后我在另一台虚拟机上添加了 dhcp 和 nfs 服务器:
qemu-DHCP-and-NFS-server ------- (tap0)[ 主机桥 (br0) ](tap1) --------- qemu 客户端
主机桥 br0 包含两个接口:tap0 连接到 qemu 服务器,tap1 连接到客户端。桥接 ip 为 10.0.2.2/24,mac=5e:50:67:79:96:f0 qemu-DHCP-and-NFS-server ip 为 10.0.2.3/24,mac=52:54:00:12:34:56
在 qemu-DHCP-and-NFS-server 上,
init
二进制文件位于 /serverNFS/sbin/init 中,且 /etc/export 如下所示:/serverNFS *(rw,no_root_squash,async,insecure)
只是为了测试,我在 qemu 客户端上运行了 ubuntu live cd:
kvm \
-netdev tap,id=totou,ifname=tap1 -device e1000,netdev=totou,mac=52:54:00:12:34:57 \
-cdrom ubuntu-16.04-desktop-amd64.iso \
-m 6G
并尝试挂载 nfs 分区:
# mkdir /tmp/nfs
# mount.nfs 10.0.2.3:/serverNFS /tmp/nfs
# ls /tmp/nfs/sbin
init
好的,DHCP 和 NFS 可以工作了!
现在我停止 qemu 客户端并使用以下命令重新启动它:
kvm \
-netdev tap,id=totou,ifname=tap1 -device e1000,netdev=totou,mac=52:54:00:12:34:57 \
-kernel /tmp/bzImage \
-append "root=/dev/nfs rw nfsroot=10.0.2.3:/serverNFS ip=dhcp" \
-m 6G
在启动时,内核启动,我可以看到如下内容:
...
Sending DHCP requests ;, OK
IP-Config : Got DHCP answer from 10.0.2.3, my address is 10.0.2.19
IP-Config : Complete:
device=eth0,hwaddr=52:54:00:12:34:57, ipaddr=10.0.2.19, mask=255.255.255.0, gw=10.0.2.2
host=10.0.2.19, domain=, nis-domain=(none)
bootserver=10.0.2.3, rootserver=10.0.2.3, rootpath=/serverNFS
...
但最后我出现了内核恐慌——“未同步:VFS:无法挂载根文件系统
我的 nfs 服务器似乎有问题,但我找不到原因。您有什么想法吗?
再补充一点:我不想添加“-initrd”(或者解释为什么它是绝对必要的)。内核配置中的文件系统 -> 网络文件系统中的所有内容都被选中(不是作为模块)。此外,CONFIG_ROOT_NFS、CONFIG_IP_PNP、CONFIG_IP_PNP_BOOTP、CONFIG_IP_PNP_RARP、CONFIG_IP_PNP_DHCP 都被选中。
如果您需要其他精度,请告诉我。
答案1
这个问题实际上很容易解决,我很惭愧在发帖之前没有想到这一点(很抱歉!)
wireshark 跟踪让我知道内核正在使用 NFSv2(即使内核中编译了 NFSv3 和 NFSv4)。(它使用 NFS 和 RPC over UDP)但我的服务器只接受 nfsv3 或 nfsv4。因此,解决方案是接受 nfsv2:
需要支持使用 NFSv2(例如 U-Boot)的客户端的用户应在 /etc/sysconfig/nfs 中设置 RPCNFSDARGS="-V 2"。(来自https://wiki.archlinux.org/index.php/NFS#NFSv2_compatibility)
顺便说一句,如果你知道如何强制使用 NFSv3 或 NFSv4,请告诉我