宿主机与qemu虚拟机互传文件

0 背景
1 宿主机与qemu虚拟机互传文件
2 编写ko demo,做内核测试
推荐阅读

0 背景

当搭建好qemu调试arm64 linux内核的环境(详见同事的文章VSCode+GDB+Qemu调试ARM64 linux内核)后,还有个需求亟待解决,就是宿主机与虚拟机之间互传文件。因为会想写简单的demo,测试代码行为。比如写简单驱动,在宿主机交叉编译,到虚拟机insmod执行。 本文记录该需求实现过程,以及踩过的坑。

linux内核tag :v5.4-rc8
宿主机: WSL Ubuntu20.04

1 宿主机与qemu虚拟机互传文件

搜索了一波发现基本有3类方法:

(1)通过网络。这要求qemu虚拟机配置了网卡。

(2)通过9p VirtFS协议。qemu虚拟机内核需要打开以下配置项

CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_9P_FS=y

(3)挂载伪设备。通过回环设备loop device实现。

因为方案(3)最方便,因此首先尝试的是该方案,参考该文章在qemu环境下,实现宿主机和虚拟机之间的数据传输。但由于WSL不支持loop设备挂载,参考该文章wsl下mount -o loop是出现的权限问题,因此放弃。

接下来尝试方案(2),最终该方案走通。

1> 保证qemu虚拟机内核打开了以下配置项:

CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_9P_FS=y

2> 如果qemu arm64环境搭建参考的是VSCode+GDB+Qemu调试ARM64 linux内核,需要去掉根文件系统 /etc/fstab中的9p挂载,即 kmod_mount /mnt 9p trans=virtio 0 0 , 记得修改完根文件系统的内容后,需要重新编译根文件系统。

3> qemu启动命令行中增加以下内容 -fsdev local,security_model=passthrough,id=fsdev0,path=/home/haonan/workspace/kernel_study/linux_old1/kmodules -device virtio-9p-device,id=fs0,fsdev=fsdev0,mount_tag=hostshare 其中有几点需要解释:path=后的路径名即为待与虚拟机共享的文件路径,请自行指定;-device后不使用virtio-9p-pci,而是virtio-9p-device,这里感谢文章qemu模拟器错误9pnet_virtio: no channels available for device 我的完整qemu启动命令如下:

qemu-system-aarch64 -m 512M -smp 4 -cpu cortex-a57 -machine virt -kernel arch/arm64/boot/Image -append "rdinit=/linuxrc nokaslr console=ttyAMA0 loglevel=8" -nographic -s  -fsdev local,security_model=passthrough,id=fsdev0,path=/home/haonan/workspace/kernel_study/linux_old1/kmodules -device virtio-9p-device,id=fs0,fsdev=fsdev0,mount_tag=hostshare

4>进入虚拟机后,执行以下命令:

mkdir /mnt/host_files

mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/host_files

此时虚拟机中的/mnt/host_files路径中的内容,即与主机的/home/haonan/workspace/kernel_study/linux_old1/kmodules内容一致了。

2 编写ko demo,做内核测试

这部分内容可能写出来的价值不大,不过还是有两个坑值得分享。源文件和makefile文件如下:

//test.c文件
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <asm/io.h>         //含有iomap函数iounmap函数
 #include <asm/uaccess.h>    //含有copy_from_user函数
 #include <linux/device.h>   //含有类相关的处理函数
  
  int init_hello_module(void)
  {
     printk("***************Start***************\n");
     printk("Hello World Init! \n");
      return 0;
  }
  
  void exit_hello_module(void)
  {
     printk("***************End***************\n");
     printk("Hello World Exit! \n");
  }

 module_init(init_hello_module);
 module_exit(exit_hello_module);
 
 MODULE_LICENSE("Dual BSD/GPL");//一般放到最后


#Makefile文件
CROSS_COMPILE:= aarch64-linux-gnu-
ARCH:= arm64
CC:= $(CROSS_COMPILE)gcc
LD:= $(CROSS_COMPILE)ld 
obj-m := test.o

KERNELDIR = /home/haonan/workspace/kernel_study/linux_old1

PWD := $(shell pwd) 

modules: 
     $(MAKE) ARCH=$(ARCH) -C $(KERNELDIR) M=$(PWD) modules 

modules_install: 
     $(MAKE) ARCH=$(ARCH) -C $(KERNELDIR) M=$(PWD) modules_install 

clean:
 rm -f *.o
 rm -f *.symvers
 rm -f *.order
 rm -f *.ko
 rm -f *.mod.c

makefile文件要做点说明,KERNELDIR宏需要根据本地的实际情况,指定到qemu执行的内核源码的路径;()行中一定要加入(MAKE)行中一定要加入ARCH=(MAKE)行中一定要加入ARCH=(ARCH),否则非交叉编译,会遇到奇怪的问题。

make modules编译成功后,将ko文件放到共享文件夹内,在虚拟机内执行:

insmod test.ko

会看到这样的报错:

 

因为该ko不是和内核一起编译出来的,因此过不了kernel的magic number检查。为了本地调试的方便,可调整内核文件如下:

 

重新编译内核后,insmod成功结果如下:

推荐阅读

1.qemu 支持 host 和 guest 中共享目录
2.qemu模拟器错误9pnet_virtio: no channels available for device
3.qemu-kvm虚拟机与宿主机之间简单文件传输方法

posted on   zxddesk  阅读(482)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示