PVE宿主机与windows虚拟机通过qemu-guest-agent通信原理

一、背景

在之前的分享中测试了pve宿主机与linux虚拟机通过串口通信的原理,通过启动命令发现了关联文件/var/run/qemu-server/104.qga和org.qemu.guest_agent.0设备通信,然而在windows虚拟机中无法识别串口设备。

-chardev socket,path=/var/run/qemu-server/104.qga,server=on,wait=off,id=qga0

-device virtio-serial,id=qga0,bus=pci.0,addr=0x8

-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0

二、分析过程

观察串口设备发现,我们配置的虚拟串口在设备管理器中无法观察到,编写程序也无法读取到(特意通过go语言测试)。

添加了一个串行端口的硬件后发现多了对应的通信端口,由此可以断定虚拟串口和硬件串口在虚拟机中是有区别的。

 之后通过查阅资料,发现windows的虚拟串口是通过虚拟机内的管道和宿主机进行通信的,为了验证这一假设特意执行了guest-agent的启动文件。

由于以普通用户身份运行,因此无打开管道权限因此报错,  \\.\Global\org.qemu.guest_agent.0 这个管道就是咱们之前配置的串口设备的名称。

三、验证猜想

将编写好的go代码编译成exe文件放入虚拟机中运行

func main() {
	pipePath := `\\.\Global\org.qemu.guest_agent.0`

	// 将管道路径转换为UTF-16编码
	pipePathUTF16, err := syscall.UTF16PtrFromString(pipePath)
	if err != nil {
		fmt.Println("Error converting string to UTF-16:", err)
		return
	}

	// 调用CreateFile函数打开命名管道
	handle, err := syscall.CreateFile(
		pipePathUTF16,
		syscall.GENERIC_READ|syscall.GENERIC_WRITE,
		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
		nil,
		syscall.OPEN_EXISTING,
		0,
		0,
	)
	if err != nil {
		fmt.Println("Error opening named pipe:", err)
		return
	}
	fmt.Println("连接成功")

	defer syscall.CloseHandle(handle)

	// 读取数据
	var buf [1024]byte
	var bytesRead uint32
	for {

		err = syscall.ReadFile(handle, buf[:], &bytesRead, nil)
		if err != nil {
			fmt.Println(err)
			time.Sleep(500 * time.Millisecond)
		} else {
			fmt.Printf("Read %d bytes from named pipe: %s\n", bytesRead, buf[:bytesRead])
		}
	}
}

再通过之前的socket链接命令,链接宿主机上的串口文件。

socat - UNIX-CONNECT:/var/run/qemu-server/104.qga

打开传入虚拟机的exe文件(管理员身份打开) 

宿主机上的终端输入随意字符

在windows虚拟机中都可以收到

由此可以断定,宿主机通过虚拟串口的方式和windows虚拟机机中的管道通信,实现虚拟串口通信。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值