QEMU 中来宾和主机之间共享内存

问题描述 投票:0回答:1

我一直在尝试在主机上运行的进程和来宾计算机上运行的程序之间设置共享内存IPC。 根据网上找到的信息,我一直在尝试启动 QEMU:

尝试#1: qemu-system-x86_64 -hda disk.qcow2 -m 4096M -nic 用户,ipv6=off,型号=e1000,mac=52:54:98:76:54:34,hostfwd=tcp::10022-:22 -smp 32 -monitor pty -vnc :12 -qmp tcp:localhost:4444,server,wait=off -对象内存后端文件,id=hostmem,大小=4096M,mem-path=/dev/shm/data.dat ,share=on-machine内存后端=hostmem

这已记录在此处:从另一个进程访问 QEMU 仿真系统的 RAM – REDS 博客,并且看起来很有希望。

尝试#2: qemu-system-x86_64 -hda disk.qcow2 -m 4096M -nic 用户,ipv6=off,型号=e1000,mac=52:54:98:76:54:34,hostfwd=tcp::10022-:22 -smp 32 -monitor pty -vnc :12 -qmp tcp:localhost:4444,server,wait=off -设备 ivshmem-plain,memdev=hostmem,master=on -对象内存后端文件,size=256M,share=on ,mem-path=/dev/shm/data.dat,id=hostmem

这在 QEMU 网站上有记录。不确定 ivshmem 是否应该用于此目的,但我认为值得一试:VM 间共享内存设备 — QEMU 文档

尝试#3: 我读过这篇文章:qemu/docs/memory-hotplug.txt at master · qemu/qemu · GitHub,与我已经在做的事情的唯一区别是建议将 slot=3 选项添加到 -m 选项,如下所示:

qemu-system-x86_64 -hda disk.qcow2 -m 4096M,slots=3,maxmem=8G-nic 用户,ipv6=off,model=e1000,mac=52:54:98:76:54:34, hostfwd=tcp::10022-:22 -smp 32 -monitor pty -vnc :12 -qmp tcp:localhost:4444,服务器,等待=关闭-对象内存后端文件,id=hostmem,大小=4096M,mem-路径=/dev/shm/data.dat,共享=在-机器内存后端=hostmem

尝试#4: 我最终尝试采用不同的方法,通过 QEMU Monitor 热插拔共享内存设备,如下所述:QEMU 教程:如何使用 ivshmem-plain - L (liujunming.top)

在所有这些尝试中,后端文件都在主机上的“/dev/shm/data.dat”处正确实例化。 但是,在来宾上的同一位置没有同一文件的踪迹。 因此,在来宾上运行的程序尝试获取该文件的文件描述符,然后由 mmap 使用并启用对共享内存的写入或读取时,就会崩溃。

有谁知道为什么会这样? 是否需要在来宾上显式启用共享内存才能使其工作? 如果是的话,你会怎么做?

如果我在来宾上运行:lspci,我可以看到 IV-SHMEM PCI 设备! 那么为什么没有在 guest 虚拟机上创建 /dev/shm/data.dat 文件?

shared-memory qemu
1个回答
0
投票

我找到了以下解释:

共享内存IPC(进程间通信)是一种使用共享内存区域在进程或虚拟机之间交换数据的方法。 Qemu 是一款模拟各种硬件架构并允许在同一主机上运行不同操作系统的软件。

在 qemu 中启用共享内存 IPC 的一种方法是使用 ivshmem 设备,它是一个 PCI 设备,提供对主机上共享内存区域的访问。 ivshmem 设备可以配置为使用 POSIX 共享内存文件(例如 /dev/shm/data.dat)或内存后端对象(例如 memory-backend-file)作为共享内存的源12。

要使用 ivshmem 设备,您需要在启动 qemu 时指定以下选项:

-device ivshmem-plain,memdev=hostmem 其中 hostmem 是定义共享内存区域的大小、路径和共享模式的内存后端对象的名称。 -object memory-backend-file,size=...,share=on,mem-path=...,id=hostmem 在其中指定内存后端对象的大小、路径和 ID。 share=on 选项对于启用与其他进程或虚拟机共享内存区域非常重要。 例如,以下命令将创建由文件 /dev/shm/data.dat 支持的 256 MB 共享内存区域,并将其作为 ivshmem 设备公开给来宾 VM:

qemu-system-x86_64 -device ivshmem-plain,memdev=hostmem -object内存后端文件,大小=256M,share=on,mem-path=/dev/shm/data.dat,id=hostmem ...

请注意,文件 /dev/shm/data.dat 在来宾虚拟机上不可见,因为它仅由主机用来分配共享内存区域。来宾虚拟机将共享内存区域视为具有映射到共享内存地址空间的 BAR(基地址寄存器)的 PCI 设备。您可以在来宾虚拟机上使用 lspci 命令来验证 ivshmem 设备是否存在并获取其 BAR 地址2。

要从 guest VM 访问共享内存区域,需要使用 mmap 系统调用将 BAR 地址映射到 guest 虚拟地址空间。例如,以下 C 代码片段会将共享内存区域的前 4 KB 映射到指针 shm:

#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>

#define SHM_SIZE 4096 // size of the shared memory region to map
#define SHM_BAR 0xfebf0000 // BAR address of the ivshmem device (obtained from lspci)

int main() {
    int fd = open("/dev/mem", O_RDWR); // open the /dev/mem device file
    if (fd == -1) {
        perror("open");
        return -1;
    }
    void *shm = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SHM_BAR); // map the BAR address to shm
    if (shm == MAP_FAILED) {
        perror("mmap");
        return -1;
    }
    // do something with shm, such as reading or writing data
    munmap(shm, SHM_SIZE); // unmap the shared memory region
    close(fd); // close the /dev/mem device file
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.