qemu分析之 KVM_EXIT_MMIO

news2025/3/16 20:17:28

基于qemu-2.8.1

address_space_rw 函数作用

这是QEMU内存子系统的核心函数,负责分块处理跨MemoryRegion的内存读取操作。主要场景包括:

  1. 处理跨越多个MemoryRegion的连续内存读取
  2. 区分RAM直接访问与MMIO设备模拟
  3. 处理不同位宽(1/2/4/8字节)的访问

代码流程解析

/* 在RCU临界区内调用 */
MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
                                        MemTxAttrs attrs, uint8_t *buf,
                                        int len, hwaddr addr1, hwaddr l,
                                        MemoryRegion *mr)
{
    // 初始化变量...
    for (;;) {
        /* 判断是否为直接内存访问(RAM) */
        if (!memory_access_is_direct(mr, false)) {
            /* I/O设备处理分支 */
            // 准备MMIO访问(可能涉及锁操作)
            release_lock |= prepare_mmio_access(mr); 
            
            // 根据设备限制调整访问长度(对齐要求等)
            l = memory_access_size(mr, l, addr1); 
            
            // 分派不同位宽的读取操作
            switch (l) {
            case 8: // 64位读
                result |= memory_region_dispatch_read(mr, addr1, &val, 8, attrs);
                stq_p(buf, val); // 存储并处理字节序
                break;
            case 4: // 32位读
                result |= memory_region_dispatch_read(mr, addr1, &val, 4, attrs);
                stl_p(buf, val);
                break;
            case 2: // 16位读
                result |= memory_region_dispatch_read(mr, addr1, &val, 2, attrs);
                stw_p(buf, val);
                break;
            case 1: // 8位读
                result |= memory_region_dispatch_read(mr, addr1, &val, 1, attrs);
                stb_p(buf, val);
                break;
            default:
                abort(); // 非法访问长度
            }
        } else {
            /* RAM直接访问分支 */
            // 映射到主机虚拟地址
            ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
            memcpy(buf, ptr, l); // 直接内存拷贝
        }

        // 必要时释放iothread锁
        if (release_lock) {
            qemu_mutex_unlock_iothread();
            release_lock = false;
        }

        // 更新剩余需处理的长度和位置
        len -= l;
        buf += l;
        addr += l;

        if (!len) break; // 完成所有读取

        // 转换到下一个内存区域
        l = len;
        mr = address_space_translate(as, addr, &addr1, &l, false);
    }
    return result;
}

关键机制详解

1. 内存区域类型判断
  • memory_access_is_direct(mr, false)
    • 返回true表示目标为RAM区域,可直接通过memcpy快速访问
    • 返回false表示目标为MMIO设备,需通过设备回调函数处理
2. MMIO访问准备
  • prepare_mmio_access(mr)
    • 必要时释放全局锁(qemu_mutex_unlock_iothread()),防止设备模拟时阻塞其他线程
    • 返回标记用于后续重新加锁
3. 设备访问分派
  • memory_region_dispatch_read()
    • 最终调用MemoryRegionOps中注册的.read回调函数
    • 示例设备操作:
      static const MemoryRegionOps mydev_ops = {
          .read = mydev_read,
          .write = mydev_write,
          .endianness = DEVICE_LITTLE_ENDIAN,
          //...
      };
      
4. 字节序处理
  • stq_p/stl_p/stw_p/stb_p宏:
    • 将主机端数值按目标架构字节序写入缓冲区
    • 例如:设备为Big-Endian时自动进行字节交换
5. 跨区域处理
  • 循环中的address_space_translate
    • 当读取操作跨越多个MemoryRegion时,自动分割为多次访问
    • 更新addr1为当前MemoryRegion内的偏移量

锁机制注意事项

  • RCU(Read-Copy-Update)保护:函数在RCU临界区内调用,确保内存拓扑结构不会在访问期间变化
  • IOThread锁释放:MMIO访问可能涉及长时间设备模拟,临时释放锁避免阻塞其他线程

典型调用链

address_space_read_full()
  → address_space_translate()        // 初始地址转换
  → address_space_read_continue()    // 本函数
    → memory_region_dispatch_read()  // 设备访问
      → mr->ops->read()              // 设备具体实现

错误处理

  • MemTxResult的按位或操作(|=):
    • 累积多个子操作的错误状态
    • 常见错误类型:
    typedef enum MemTxResult {
        MEMTX_OK = 0,         // 成功
        MEMTX_DECODE_ERROR,   // 地址无对应设备
        MEMTX_ACCESS_ERROR,   // 权限错误
        MEMTX_BUS_ERROR       // 设备返回错误
    } MemTxResult;
    

性能优化点

  1. RAM快速路径:直接memcpy避免函数调用开销
  2. 访问长度对齐memory_access_size()确保符合设备要求
  3. 锁粒度控制:仅在必要时持有iothread锁

该函数体现了QEMU内存模拟的核心设计思想:在保证正确性的前提下,对RAM和MMIO进行差异化处理以平衡性能与灵活性

2. qemu_map_ram_ptr 函数目标

在保证线程安全(RCU临界区内)的前提下,获取RAMBlock对应的宿主机物理内存指针,专用于QEMU内部对内存的底层操作。

2.1. 参数说明
  • RAMBlock *ram_block:内存块描述符(可为NULL)
  • ram_addr_t addr:全局内存地址空间中的地址
2.2. 关键逻辑流程
void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr)
{
    // Step 1: 自动定位RAMBlock(当未显式指定时)
    RAMBlock *block = ram_block;
    if (block == NULL) {
        block = qemu_get_ram_block(addr); // 根据地址查找所属内存块
        addr -= block->offset;            // 转换为块内偏移量
    }

    // Step 2: Xen特殊内存映射处理
    if (xen_enabled() && block->host == NULL) {
        if (block->offset == 0) {
            // Case 1: 映射地址所在页(避免全量映射)
            return xen_map_cache(addr, 0, 0);
        } else {
            // Case 2: 首次映射时缓存整个块
            block->host = xen_map_cache(block->offset, block->max_length, 1);
        }
    }

    // Step 3: 计算最终指针
    return ramblock_ptr(block, addr);
}
2.3. 关键点说明
  • 自动块定位:当ram_block参数为NULL时,通过qemu_get_ram_block(addr)自动查找地址所属的内存块,并调整地址为块内偏移量
  • Xen支持
    • 若运行在Xen虚拟化环境且内存未映射时:
    • 零偏移块直接映射目标地址所在页(xen_map_cache第三个参数0表示不锁定)
    • 其他块首次映射时会缓存整个块(block->max_length指定长度,第三个参数1表示锁定内存)
  • 指针计算:最终通过ramblock_ptr宏(通常定义为block->host + addr)计算实际指针
2.4. 使用限制
  • ✖️ 不适用于通用DMA操作(建议用address_space_map
  • ✖️ 不适用于设备自有内存(建议用memory_region_get_ram_ptr
  • ✔️ 专用于QEMU内部需要直接访问客户机物理内存的场景
2.5. 典型应用场景
  • 虚拟设备模拟时快速访问特定内存区域
  • 调试工具需要直接读取内存内容
  • Xen等特殊虚拟化方案中的内存管理

建议结合QEMU内存管理文档《memory.txt》理解其完整上下文,使用时需严格遵守RCU锁规则和API约束条件。

3.0 memory_region_dispatch_read

memory_region_dispatch_read 是 QEMU 内存管理子系统中的关键函数,用于处理对模拟内存区域的读取操作。其核心作用如下:

3.1 核心功能
  1. 地址路由
    根据目标物理地址,查找对应的 MemoryRegion(可能递归遍历子区域),确定处理该地址的 MemoryRegionOps

  2. 回调触发
    调用目标 MemoryRegion 注册的 read 回调函数(通过 MemoryRegionOps),执行设备特定的读取逻辑(如访问模拟设备寄存器)。

  3. 数据转换
    处理字节序转换(Host与Guest的Endianness差异),确保数据格式正确。

  4. 访问控制
    检查内存区域的读写权限(如 ROM 不可写),触发异常(如访问未实现区域时的 unassigned_access)。

3.2 典型参数
  • addr: 目标地址(相对于MemoryRegion的偏移)
  • pv: 读取数据存储的指针
  • size: 操作大小(1/2/4/8字节)
  • attrs: 内存访问属性(如类型、特权级)
3.3 工作流程
  1. 地址解析
    通过 AddressSpace 和物理地址找到对应的 MemoryRegion
  2. 权限检查
    验证该区域是否支持读操作。
  3. 回调执行
    调用 MemoryRegionOps->read,由设备模型返回数据。
  4. 字节序调整
    根据区域配置转换数据字节序。
  5. 未实现处理
    若区域无回调,可能填充默认值或记录错误。
3.4 应用场景
  • CPU 访问物理内存时(如 ld 指令)
  • 设备模拟代码读取其管理的寄存器/内存
  • 虚拟化场景中处理客户机内存访问

例如,当Guest OS读取PCI设备寄存器时,此函数将路由到PCI设备的read回调,返回设备状态信息。

4.0 地址翻译(EPT 与 IOMMU)与 MMIO Exit 的本质区别

在虚拟化环境中,地址翻译MMIO Exit(MMIO 退出) 是两个不同层次的概念,分别涉及 硬件辅助的地址转换机制虚拟化事件处理流程。以下是详细解析:


4.1. 地址翻译:EPT 与 IOMMU 的作用

(1) EPT(Extended Page Table,扩展页表)
  • 功能
    EPT 是 CPU 硬件虚拟化(如 Intel VT-x)的一部分,负责 虚拟机(Guest)物理地址(GPA)→ 宿主机物理地址(HPA) 的转换。
  • 场景
    当虚拟机内的软件访问内存时(例如执行 mov [eax], ebx),CPU 会通过 EPT 自动完成 GPA 到 HPA 的翻译。
  • 特点
    • 透明于虚拟机操作系统(Guest OS)。
    • 硬件加速,性能高。
(2) IOMMU(如 Intel VT-d、AMD-Vi)
  • 功能
    IOMMU 负责 设备 DMA 请求的地址翻译,将设备发起的 I/O 虚拟地址(IOVA)→ 宿主机物理地址(HPA)
  • 场景
    当 PCIe 设备直接向虚拟机内存发起 DMA 操作时,IOMMU 确保设备只能访问虚拟机被授权的物理内存区域。
  • 特点
    • 防止设备越界访问(安全性)。
    • 支持 DMA 重映射(如 SR-IOV 虚拟化)。
(3) EPT 与 IOMMU 的关系
  • 共同目标:隔离虚拟机内存,保障安全性。
  • 区别
    • EPT:处理 CPU 发起的地址访问(如 Guest 内核或应用程序的内存操作)。
    • IOMMU:处理 设备发起的 DMA 访问(如网卡、GPU 直接读写内存)。

4.2. MMIO Exit(MMIO 退出)的本质

(1) 什么是 MMIO Exit?
  • 定义:当虚拟机尝试访问一个 MMIO 区域(设备寄存器映射的内存地址)时,CPU 触发 VM Exit,将控制权交还给虚拟机监控器(VMM,如 KVM/QEMU),由 VMM 模拟设备行为。
  • 触发条件
    • 虚拟机访问的 GPA 未被映射到真实内存(标记为 MMIO 区域)。
    • 该 GPA 对应虚拟设备的寄存器或显存等需模拟的资源。
(2) MMIO Exit 的处理流程
Guest 执行指令访问 MMIO 地址 
    → CPU 触发 VM Exit(类型为 KVM_EXIT_MMIO) 
        → VMM 根据退出信息(地址、操作类型、数据)调用设备模拟逻辑 
            → QEMU 模拟设备响应(如修改虚拟设备状态) 
                → 恢复 Guest 执行。
(3) MMIO Exit 与 EPT 的关系
  • EPT 不直接导致 MMIO Exit
    EPT 仅负责 GPA→HPA 的地址翻译,但如果目标 HPA 对应的是 宿主机中预留的 MMIO 区域,则访问会进一步触发 MMIO Exit。
    在这里插入图片描述

  • MMIO 区域的标记
    在虚拟化环境中,VMM 会通过 EPT 将某些 GPA 范围标记为 “不可缓存”或“设备内存”,强制对该区域的访问触发 VM Exit。


4.3. 关键区别对比

特性EPTIOMMUMMIO Exit
作用对象CPU 发起的地址访问设备发起的 DMA 访问CPU 访问 MMIO 区域的拦截
硬件支持CPU 虚拟化扩展(VT-x)IOMMU 硬件(VT-d/AMD-Vi)CPU 虚拟化扩展(VT-x)
触发条件所有 Guest 内存访问设备 DMA 请求Guest 访问 MMIO 区域
主要目的内存隔离与地址翻译设备 DMA 安全隔离设备模拟与 I/O 虚拟化

4.4. 协同工作示例(以 PCIe 设备为例)

  1. Guest 访问虚拟 PCIe 设备寄存器

    • Guest 执行 mov [0xfe000000], eax(假设 0xfe000000 是虚拟 PCIe 设备的 MMIO 地址)。
    • EPT 发现该 GPA 映射到宿主机的 MMIO 区域 → 触发 MMIO Exit
    • VMM 调用 QEMU 的 PCIe 设备模拟代码,更新虚拟设备状态。
  2. 虚拟 PCIe 设备发起 DMA

    • 设备模拟逻辑要求向 Guest 内存写入数据(模拟 DMA)。
    • QEMU 通过 IOMMU 将 Guest 的 IOVA(由 Guest 驱动提供)转换为 HPA,确保 DMA 的安全性。

4.5. 总结

  • EPT 和 IOMMU地址翻译机制

    • EPT 服务于 CPU 访问内存的地址翻译。
    • IOMMU 服务于设备 DMA 的地址翻译。
  • MMIO Exit虚拟化事件处理机制

    • 当 Guest 访问 MMIO 区域时,通过 VM Exit 通知 VMM 进行设备模拟。
  • 三者协作
    EPT 和 IOMMU 保障地址隔离与安全,MMIO Exit 实现设备虚拟化的动态响应。

5.0 缺页异常是否会触发 MMIO Exit?

在虚拟化环境中,缺页异常(Page Fault)MMIO Exit 是两个不同层级的机制,分别处理 内存访问异常设备模拟事件。它们的触发条件和处理流程有本质区别,缺页异常通常不会直接触发 MMIO Exit。以下是详细分析:


5.1. 缺页异常的本质

  • 触发条件
    当 CPU 访问某个虚拟地址时,若对应的物理页未分配(未映射、被换出或权限不足),硬件会触发缺页异常(Page Fault)。

    • Guest 内部的缺页异常:由虚拟机(Guest OS)自行处理,例如分配物理页或从磁盘加载数据。
    • EPT 缺页异常:若虚拟机使用 EPT(扩展页表),Guest 物理地址(GPA)到宿主机物理地址(HPA)的映射缺失,可能触发 EPT Violation VM Exit,由 VMM(如 KVM)处理。
  • 处理流程

    Guest 访问虚拟地址 → 触发缺页异常 → Guest OS 分配物理页 → 恢复执行。
    

5.2. MMIO Exit 的本质

  • 触发条件
    当虚拟机访问 内存映射 I/O(MMIO)区域(如虚拟设备寄存器)时,若该地址被标记为需要模拟,CPU 会触发 VM Exit(类型为 KVM_EXIT_MMIO),由 VMM 模拟设备行为。
  • 特点
    • MMIO 区域通常被配置为 “不可缓存”或“设备内存”,不经过常规内存访问流程。
    • 触发 MMIO Exit 的地址在 EPT 中被标记为 需要 VMM 介入

5.3. 缺页异常与 MMIO Exit 的关系

(1) 正常情况:两者独立
  • 缺页异常处理的是 内存映射的缺失或权限问题,由 Guest OS 或 VMM 直接修复。
  • MMIO Exit 处理的是 设备模拟需求,与内存映射无关。

示例

  • Guest 访问普通内存
    若 GPA 未映射到 HPA,触发 EPT Violation(VM Exit),VMM 分配物理页后恢复 Guest。
    → 这是缺页异常,但通过 EPT 触发 VM Exit,与 MMIO Exit 无关
  • Guest 访问 MMIO 区域
    EPT 已将该 GPA 标记为 MMIO,直接触发 MMIO Exit,无需缺页异常流程。
(2) 特殊情况:错误配置

若 VMM 错误地将 MMIO 区域配置为普通内存(未标记为 MMIO),Guest 访问时可能触发缺页异常(如权限错误),但此时仍需 VMM 干预。这种情况属于配置错误,非常规流程


5.4. 关键区别总结

机制触发条件处理方目标
缺页异常内存映射缺失/权限错误Guest OS 或 VMM修复内存映射
MMIO Exit访问 MMIO 区域VMM模拟设备响应

5.5. 协同流程示例

  1. Guest 访问普通内存

    • GPA 未映射 → 触发 EPT Violation VM Exit → VMM 分配 HPA → 恢复 Guest。
      (属于缺页异常,但通过 EPT 触发 VM Exit,非 MMIO Exit)
  2. Guest 访问 MMIO 区域

    • GPA 已标记为 MMIO → 直接触发 MMIO Exit → VMM 模拟设备 → 恢复 Guest。
      (无需缺页异常流程)

5.6 小节

  • 缺页异常通常不会触发 MMIO Exit,两者是独立机制。
  • 例外情况:仅当 MMIO 区域被错误配置为普通内存时,可能同时涉及缺页异常和 VMM 干预,但这是非标准场景。
  • 核心区别
    • 缺页异常解决的是 内存映射问题
    • MMIO Exit 解决的是 设备模拟需求

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2316235.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OSI 七层网络模型

文章目录 OSI 七层模型应用层表示层会话层传输层网络层数据链路层物理层 TCP/IP 四层模型应用层传输层网络层数据链路层 TCP/IP 特点OSI 和 TCP/IP 两者关系通信过程及相关协议常用协议及端口号常用协议分类参考链接 OSI 七层模型 七层模型,亦称OSI(Ope…

虚拟电商-数据库分库分表(二)

本文章介绍:使用Sharding-JDBC实现数据库分库分表,数据库分片策略,实现数据库按月分表 一、Sharding-JDBC使用 1.1.准备环境 步骤一:分库分表sql脚本导入 创建了两个数据库:chongba_schedule0 和chongba_schedule1…

进程间通信--匿名管道

进程间通信介绍 进程间通信目的 数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件&…

C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色

C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色 安装 Install-Package OpenCvSharp4 Install-Package OpenCvSharp4.Windows 普通实现 using System; using System.Collections.Generic; using System.Linq; using OpenCvSharp; // 添加OpenCV引用…

基于SSM + JSP 的图书商城系统

基于SSM的图书商城 网上书城、图书销售系统、图书销售平台 |Java|SSM|HTML|JSP| 项目采用技术: ①:开发环境:IDEA、JDK1.8、Maven、Tomcat ②:技术栈:Java、…

【漫话机器学习系列】133.决定系数(R²:Coefficient of Determination)

决定系数()详解 决定系数()是回归分析中用于评估模型拟合优度的一个重要统计指标。它表示自变量(特征变量)能够解释因变量(目标变量)变异的程度,取值范围为 [0,1] 或 (−…

Machine Learning: 十大基本机器学习算法

机器学习算法分类:监督学习、无监督学习、强化学习 基本的机器学习算法: 线性回归、支持向量机(SVM)、最近邻居(KNN)、逻辑回归、决策树、k平均、随机森林、朴素贝叶斯、降维、梯度增强。 机器学习算法大致可以分为三类: 监督学习算法 (Sup…

【八股文】ArrayList和LinkedList的区别

先讲讲两者是如何实现的 ArrayList public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {transient Object[] elementData; private int size; } 通过源码可以看出&#xff0c;ArrayLis…

汇编语言 | 王爽 | 学习笔记

汇编语言 | 王爽 | 学习笔记 文章目录 汇编语言 | 王爽 | 学习笔记一、基础知识1、指令2、存储器3、总线1、总线2、CPU对存储器的读写3、CPU对外设的控制 4、内存地址空间 二、寄存器1、寄存器2、通用寄存器3、8086CPU给出物理地址的方法4、段寄存器1、CS和IP2、DS 和 [address…

JumpServer基础功能介绍演示

堡垒机可以让运维人员通过统一的平台对设备进行维护&#xff0c;集中的进行权限的管理&#xff0c;同时也会对每个操作进行记录&#xff0c;方便后期的溯源和审查&#xff0c;JumpServer是由飞致云推出的开源堡垒机&#xff0c;通过简单的安装配置即可投入使用&#xff0c;本文…

EDID读取学习

简介 Video BIOS可以被认为是一个具有独立硬件抽象层的操作系统。它不会阻止或监视操作系统、应用程序或设备驱动程序对硬件的直接访问。虽然不推荐,但一些DOS应用程序确实可以改变基本的硬件设置,而根本不需要通过视频BIOS。大多数现代应用程序和操作系统都避免直接使用硬件…

【笔记】深度学习模型训练的 GPU 内存优化之旅:综述篇

开设此专题&#xff0c;目的一是梳理文献&#xff0c;目的二是分享知识。因为笔者读研期间的研究方向是单卡上的显存优化&#xff0c;所以最初思考的专题名称是“显存突围&#xff1a;深度学习模型训练的 GPU 内存优化之旅”&#xff0c;英文缩写是 “MLSys_GPU_Memory_Opt”。…

2024山东大学计算机复试上机真题

2024山东大学计算机复试上机真题 2024山东大学计算机复试机试真题 历年山东大学计算机复试上机真题 历年山东大学计算机复试机试真题 在线评测&#xff1a;传动门&#xff1a;pgcode.cn 最长递减子序列 题目描述 输入数字 n&#xff0c;和 n 个整数&#xff0c;输出该数字…

Vue 计算属性与 Data 属性同名问题深度解析

文章目录 1. 问题背景与核心概念1.1 Vue 响应式系统架构1.2 核心概念定义 2. 同名问题的技术分析2.1 同名场景示例2.2 问题发生机制 3. 底层原理剖析3.1 Vue 初始化流程3.2 响应式系统关键代码 4. 问题解决方案4.1 最佳实践建议4.2 错误处理机制 5. 性能影响分析5.1 递归调用性…

[文献阅读] 可变形卷积DCN - Deformable Convolutional Networks

**文献信息&#xff1a;**Deformable Convolutional Networks arxiv.org/abs/1703.06211 发表于ICCV 2017&#xff0c;提出了可变形卷积DCN&#xff08;Deformable ConvNets&#xff09; 摘要 卷积神经网络&#xff08;CNN&#xff09;由于其构建模块固定的几何结构天然地局限…

【统计学相关笔记】2. 多元正态的Cochran定理

fisher 引理 如何说明一个线性变换和二次型独立&#xff1a; 二次型矩阵和线性变换阵乘积0即可。

蓝桥杯刷题——第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组

一、0握手问题 - 蓝桥云课 算法代码&#xff1a; #include <iostream> using namespace std; int main() {int sum0;for(int i49;i>7;i--)sumi;cout<<sum<<endl;return 0; } 直接暴力&#xff0c;题意很清晰&#xff0c;累加即可。 二、0小球反弹 - 蓝…

Canoe Panel常用控件

文章目录 一、Panel 中控件分类1. 指示类控件2. 功能类控件3. 信号值交互类控件4. 其他类控件 二、控件使用方法1. Group Box 控件2. Input/Output Box控件3. Static Text控件4. Button控件5. Switch/Indicator 控件 提示&#xff1a;Button 和 Switch 的区别参考 一、Panel 中…

【软考-架构】11.3、设计模式-新

✨资料&文章更新✨ GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目录 项目中的应用设计模式创建型设计模式结构型设计模式行为型设计模式 &#x1f4af;考试真题题外话 项目中的应用 在实际项目中&#xff0c;我应用过多种设计模式来解决不同…

【大模型(LLMs)RAG 检索增强生成 面经】

1 RAG 基础面 1.1 为什么大模型需要外挂 (向量) 知识库? 如何将外部知识注入大模型,最直接的方法:利用外部知识对大模型进行微调。 思路: 构建几十万量级的数据,然后利用这些数据 对大模型进行微调,以将 额外知识注入大模型 优点: 简单粗暴 缺点: 这几十万量级的数据…