如何在单个QEMU实例中启动两个操作系统(多核分核运行场景)
QEMU模拟多核异构系统(Linux+RTOS)及共享内存通信实现
一、多核系统启动配置
要实现3核CPU中2核跑Linux、1核跑RTOS的异构场景,通过QEMU参数指定核心数、隔离核心、加载RTOS镜像并绑定到指定核心:
qemu-system-x86_64 \ -smp 3 \ -kernel ./linux/vmlinuz \ -initrd ./linux/initrd.img \ -append "console=ttyS0 isolcpus=2" \ -object memory-backend-file,id=shmem,size=64M,mem-path=/tmp/qemu_shmem,share=on \ -device ivshmem-plain,memdev=shmem,vectors=1 \ -device loader,file=./rtos/rtos.bin,addr=0x10000000,cpu-num=2 \ -nographic
参数说明:
-smp 3:启用3个CPU核心isolcpus=2:让Linux内核不调度任务到第3个核心(索引从0开始)memory-backend-file:创建64M大小的共享内存文件,用于系统间通信ivshmem-plain:将共享内存暴露为PCI设备,供Linux和RTOS访问loader:将RTOS镜像加载到指定物理地址,并绑定到核心2启动
二、Linux侧共享内存访问
- 加载ivshmem驱动:
modprobe ivshmem - 查看共享内存的物理地址(后续RTOS需要用到):
cat /sys/bus/pci/devices/0000:00:04.0/resource0 - 用户空间读写共享内存的示例代码:
#include <stdio.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #define SHMEM_SIZE (64 * 1024 * 1024) int main() { int fd = open("/dev/ivshmem", O_RDWR); if (fd == -1) { perror("open ivshmem failed"); return 1; } void *shmem = mmap(NULL, SHMEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (shmem == MAP_FAILED) { perror("mmap failed"); close(fd); return 1; } // 向共享内存写入数据 sprintf(shmem, "Message from Linux core 0/1"); // 等待RTOS响应 while (*(char*)(shmem + 64) != 'R'); printf("RTOS response: %s\n", (char*)(shmem + 64)); munmap(shmem, SHMEM_SIZE); close(fd); return 0; }
三、RTOS侧共享内存访问
以FreeRTOS为例,需配置RTOS支持访问共享内存的物理地址,示例代码如下:
#include <stdio.h> #include "FreeRTOS.h" #include "task.h" // 替换为从Linux侧获取的共享内存物理地址 #define SHMEM_BASE 0xFEB00000 #define SHMEM_SIZE (64 * 1024 * 1024) void shmem_comm_task(void *pvParameters) { char *shmem = (char*)SHMEM_BASE; // 读取Linux发送的消息 printf("Received from Linux: %s\n", shmem); // 写入响应到共享内存 sprintf(shmem + 64, "Response from RTOS core 2"); vTaskDelete(NULL); } int main(void) { xTaskCreate(shmem_comm_task, "ShmemComm", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); vTaskStartScheduler(); while(1); }
注意:需根据RTOS架构配置内存映射,确保能直接访问指定物理地址;若RTOS启用MMU,需将共享内存区域映射到虚拟地址空间。
四、通信可靠性优化
- 可在共享内存头部定义控制结构体,包含读写指针、状态标记等,实现环形缓冲区:
typedef struct { volatile uint32_t write_ptr; volatile uint32_t read_ptr; volatile uint8_t buffer[64*1024*1024 - sizeof(uint32_t)*2]; } shmem_comm_t; - 使用原子操作(如Linux的
__sync_fetch_and_add、RTOS的原子API)更新控制标记,避免竞态条件。
内容的提问来源于stack exchange,提问作者segfault
相关产品推荐
相关产品推荐

