You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单个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侧共享内存访问

  1. 加载ivshmem驱动:
    modprobe ivshmem
    
  2. 查看共享内存的物理地址(后续RTOS需要用到):
    cat /sys/bus/pci/devices/0000:00:04.0/resource0
    
  3. 用户空间读写共享内存的示例代码:
    #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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:50:23