新闻详情

新闻详情

首页 / 资讯中心 / 详情

ctf-wiki:QEMU 内存管理全景解析——MemoryRegion、FlatView、AddressSpace 与 RAMBlock 的双视角模型

发布时间:2026/9/25 5:55:00来源:尧图网络
ctf-wiki:QEMU 内存管理全景解析——MemoryRegion、FlatView、AddressSpace 与 RAMBlock 的双视角模型
文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载本篇基于 ctf-wiki 仓库中 QEMU 虚拟化基础篇的内存管理章节系统讲解 QEMU 如何从 Guest 视角GPA与 Host VMM 视角HVA管理一台虚拟机的内存Guest 侧的MemoryRegion树、FlatView扁平化视图与AddressSpace统一访问入口以及 Host 侧承载实际内存的RAMBlock。读完本文你将理解 QEMU 内存子系统各核心结构体的字段含义与相互关系并能解释为什么 CTF QEMU Pwn 题目普遍围绕“自定义设备 MMIO/PMIO 回调”设计为后续阅读 QEMU 设备模拟 与 QEMU 逃逸入门 打下基础。总体模型GPA 与 HVA 的双视角QEMU 内存管理的核心任务是同时维护两套“地图”Guest VM 视角GPAGuest Physical AddressGuest 操作系统看到的物理地址空间。QEMU 用一棵嵌套的MemoryRegionMR树来描述它并通过AddressSpaceFlatView将其转换为线性的、可直接做地址翻译的结构。Host VMM 视角HVAHost Virtual AddressQEMU 进程在宿主机上实际占用的虚拟内存。每个实体 MR 背后的真实内存由一个RAMBlock描述通常通过mmap()获得。下面先深入 Guest 侧的四个核心结构体再切换到 Host 侧的RAMBlock最后讨论这套模型在 CTF QEMU Pwn 中的意义。Guest VM 视角GPAMemoryRegionGuest 视角的一块“内存”在 QEMU 当中使用MemoryRegion结构体类型来表示一块具体的 Guest 物理内存区域该结构体定义于 QEMU 源码include/exec/memory.h当中/** MemoryRegion: * * 表示一块内存区域的一个结构体. */ struct MemoryRegion { Object parent_obj; /* private: */ /* The following fields should fit in a cache line */ bool romd_mode; bool ram; bool subpage; bool readonly; /* For RAM regions */ bool nonvolatile; bool rom_device; bool flush_coalesced_mmio; bool global_locking; uint8_t dirty_log_mask; bool is_iommu; RAMBlock *ram_block; Object *owner; const MemoryRegionOps *ops; void *opaque; MemoryRegion *container; // 指向父 MemoryRegion Int128 size; // 内存区域大小 hwaddr addr; // 在父 MR 中的偏移量 void (*destructor)(MemoryRegion *mr); uint64_t align; bool terminates; bool ram_device; bool enabled; bool warning_printed; /* For reservations */ uint8_t vga_logging_count; MemoryRegion *alias; // 仅在 alias MR 中指向实际的 MR hwaddr alias_offset; int32_t priority; QTAILQ_HEAD(, MemoryRegion) subregions; QTAILQ_ENTRY(MemoryRegion) subregions_link; QTAILQ_HEAD(, CoalescedMemoryRange) coalesced; const char *name; unsigned ioeventfd_nb; MemoryRegionIoeventfd *ioeventfds; };几个对理解后续内容至关重要的成员container/subregions/subregions_link三者共同构成 MR 树的父子关系。container指向父 MRsubregions是该节点的子 MR 双向链表头size与addrsize是该 MR 覆盖的范围大小addr是它在父 MR 坐标系内的偏移量二者是后续地址翻译的基本参数ram、readonly、rom_device、is_iommu等布尔标志区分这块区域是实体 RAM、只读区域、设备寄存器还是 IOMMUops与opaque回调函数表指针及其“this 指针”MMIO 设备读写的实现入口alias与alias_offset仅在别名aliasMR 中非空指向它真正代理的那块实体 MRram_block实体 RAM MR 指向其背后的RAMBlock是连接 Guest 视角与 Host 视角的桥梁字段。在 QEMU 当中有三类最基本的 MemoryRegionMemoryRegion 根container通过memory_region_init()进行初始化其用以表示与管理由多个 sub-MemoryRegion 组成的一段内存区域并不实际指向一块内存区域例如system_memoryMemoryRegion 实体通过memory_region_init_ram()初始化表示具体的一块大小为size的内存空间指向一块真实的内存MemoryRegion 别名alias通过memory_region_init_alias()初始化作为另一个 MemoryRegion 实体的别名而存在不指向一块实际内存。MR 容器与 MR 实体间构成树形结构其中容器为根节点而实体为子节点struct MemoryRegion ------------------------ |name | | (const char *) | ------------------------ |addr | | (hwaddr) | ------------------------ |size | | (Int128) | ------------------------ |subregions | | QTAILQ_HEAD() | ------------------------ | | ------------------------------------------------ | | | | | | struct MemoryRegion struct MemoryRegion ------------------------ ------------------------ |name | |name | | (const char *) | | (const char *) | ------------------------ ------------------------ |addr | |addr | | (hwaddr) | | (hwaddr) | ------------------------ ------------------------ |size | |size | | (Int128) | | (Int128) | ------------------------ ------------------------ |subregions | |subregions | | QTAILQ_HEAD() | | QTAILQ_HEAD() | ------------------------ ------------------------补充一点若按 QEMU 官方文档的分类口径仓库中简体中文版 QEMU 内存管理 亦收录了该分类上述三类可以进一步细分为八种基本覆盖 Guest 常见的内存访问需求RAM MRmemory_region_init_ram()代表分配给 Guest 的 Host 内存、ROM MRmemory_region_init_rom()只读、禁止写操作、MMIO MRmemory_region_init_io()每次读写都会调用 QEMU 中注册的回调、ROM device MRmemory_region_init_rom_device()读走 RAM 式的直接内存访问、写走回调、IOMMU MRmemory_region_init_iommu()访问时进行地址转换并转发到其他目标区域、container MR将多个 MR 组合为一个单元管理如 PCI BAR 可能由一个 RAM MR 和一个 MMIO MR 组成、alias MR另一 MR 的别名、以及 reservation MR向memory_region_init_io()传NULL回调占用的 I/O 空间不由 QEMU 本身处理典型用途是跟踪启用 KVM 时由主机内核处理的地址空间部分。对做 QEMU Pwn 的读者而言最常打交道的是 MMIO MR 与 container MR前者是设备寄存器的载体后者是 PCI BAR 这类“组合区域”的载体。MemoryRegionOps以函数表实现的“成员函数”相应地基于 OOP 的思想MemoryRegion 的“成员函数”被封装在函数表MemoryRegionOps当中/* * Memory region callbacks */ struct MemoryRegionOps { /* 从内存区域上读. addr 与 mr 有关; size 单位为字节. */ uint64_t (*read)(void *opaque, hwaddr addr, unsigned size); /* 往内存区域上写. addr 与 mr 有关; size 单位为字节. */ void (*write)(void *opaque, hwaddr addr, uint64_t data, unsigned size); MemTxResult (*read_with_attrs)(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs); MemTxResult (*write_with_attrs)(void *opaque, hwaddr addr, uint64_t data, unsigned size, MemTxAttrs attrs); enum device_endian endianness; /* Guest可见约束: */ struct { /* 若非 0则指定了超出机器检查范围的访问大小界限 */ unsigned min_access_size; unsigned max_access_size; /* If true, unaligned accesses are supported. Otherwise unaligned * accesses throw machine checks. */ bool unaligned; /* * 若存在且 #false, 则该事务不会被设备所接受 * (并导致机器的相关行为例如机器检查异常). */ bool (*accepts)(void *opaque, hwaddr addr, unsigned size, bool is_write, MemTxAttrs attrs); } valid; /* 内部应用约束: */ struct { /* 若非 0则决定了最小的实现的 size . * 更小的 size 将被向上回绕且将返回部分结果. */ unsigned min_access_size; /* 若非 0则决定了最大的实现的 size . * 更大的 size 将被作为一系列的更小的 size 的访问而完成. */ unsigned max_access_size; /* 若为 true, 支持非对齐的访问. * 否则所有的访问都将被转换为可能多种对齐的访问. */ bool unaligned; } impl; };这张函数表里有两组很容易混淆的约束字段值得单独说明valid是Guest 可见约束描述该设备“对外宣称”的访问能力例如min_access_size/max_access_size指定了超出机器检查范围的访问大小界限unaligned表明是否支持非对齐访问accepts回调若存在且返回false则该事务不会被设备接受并触发机器检查异常等行为。设备若违反自己声明的约束比如声明了unaligned false却收到了非对齐访问QEMU 会主动报错impl是内部实现约束描述回调实现自身能处理的最小/最大 size。更大的访问会被 QEMU 自动拆分为一系列更小的访问来完成因此impl与valid不一致时是允许且常见的例如设备按字节实现回调但对 Guest 宣称只支持 4 字节对齐访问。endianness字段则决定设备寄存器采用大端还是小端解释。对逆向与漏洞分析而言read/write或read_with_attrs/write_with_attrs这组函数指针就是设备寄存器逻辑的落点——绝大多数 MMIO 漏洞越界读、UAF、堆溢出等都发生在这些回调内部。统一访问入口address_space_rw()当 Guest 要读写虚拟机上的内存时在 QEMU 内部实际上会调用address_space_rw()对于一般的 RAM 内存而言直接对 MR 对应的 Host 内存进行读写对于 MMIO 而言则最终调用到对应的MR-ops-read()或MR-ops-write()。同一仓库的 QEMU 设备模拟 章节给出了这条调用链在 KVM 路径下的具体形态kvm_cpu_exec()中kvm_vcpu_ioctl(cpu, KVM_RUN, 0)返回后根据 VM-exit 原因分发——KVM_EXIT_MMIO直接调用address_space_rw(address_space_memory, ...)KVM_EXIT_IO则调用kvm_handle_io()。而address_space_rw()的实现QEMU 源码softmmu/physmem.c会先在 RCU 读保护下把地址空间展开为FlatView再由flatview_read()/flatview_write()通过flatview_translate()定位到目标 MR随后检查flatview_access_allowed()并继续执行读写MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, void *buf, hwaddr len, bool is_write) { if (is_write) { return address_space_write(as, addr, attrs, buf, len); } else { return address_space_read_full(as, addr, attrs, buf, len); } }/* Called from RCU critical section. */ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs, const void *buf, hwaddr len) { hwaddr l; hwaddr addr1; MemoryRegion *mr; l len; mr flatview_translate(fv, addr, addr1, l, true, attrs); if (!flatview_access_allowed(mr, attrs, addr, len)) { return MEMTX_ACCESS_ERROR; } return flatview_write_continue(fv, addr, attrs, buf, len, addr1, l, mr); }注意两个关键细节其一每次访问都要经过flatview_translate()这一步“GPA → 具体 MR MR 内偏移”的翻译addr1就是翻译后的 MR 内地址其二翻译结果还要通过flatview_access_allowed()的权限检查不通过会返回MEMTX_ACCESS_ERROR。同样地为了统一接口在 QEMU 当中PMIO端口 I/O的实现也是通过 MemoryRegion 来完成的——可以把一组端口理解为 QEMU 视角的一块 Guest 内存kvm_handle_io()只是对address_space_rw()的封装只不过用的是端口地址空间address_space_io最终同样落到对应 MR 函数表中的读写函数。几乎所有的 CTF QEMU Pwn 题都是自定义一个设备并定义相应的 MMIO/PMIO 操作。理解上面的调用链后就能明白题目的可利用面本质上就是这些ops回调及其背后的状态结构。FlatViewMR 树对应的 Guest 视角物理地址空间QEMU 通过树状结构的 MemoryRegion 管理 Guest 的物理地址空间天然支持动态调整如热插拔设备、动态修改 BAR。但这种嵌套、重叠的复杂结构不适合直接与 KVM 等内核模块交互——内核需要明确的线性物理内存布局来配置 EPTExtended Page Table。因此 QEMU 使用FlatView表示一棵 MemoryRegion 树所展平后的 Guest 地址空间将树状结构“展平”为有序列表每个条目记录连续内存区域的起始地址GPA、大小与属性如 RAM/MMIO消除嵌套关系。FlatView使用一个FlatRange结构体数组来存储不同MemoryRegion对应的地址信息每个FlatRange表示单个MemoryRegion在 Guest 视角的一块物理地址空间以及只读等特性信息FlatRange之间所表示的地址范围不会重叠。/* Range of memory in the global map. Addresses are absolute. */ struct FlatRange { MemoryRegion *mr; hwaddr offset_in_region; AddrRange addr; uint8_t dirty_log_mask; bool romd_mode; bool readonly; bool nonvolatile; }; //... /* Flattened global view of current active memory hierarchy. Kept in sorted * order. */ struct FlatView { struct rcu_head rcu; unsigned ref; FlatRange *ranges; unsigned nr; unsigned nr_allocated; struct AddressSpaceDispatch *dispatch; MemoryRegion *root; };字段解读FlatRange.mroffset_in_region该段地址最终归属的 MR 及其在 MR 内部的偏移两者配合即可把绝对 GPA 还原为(mr, mr 内偏移)FlatRange.addr该段在全局地址空间中的绝对范围AddrRange为“基址 长度”类型readonly、dirty_log_mask、nonvolatile该段的访问属性快照readonly即上文权限检查的依据之一FlatView.ranges/nr按地址排序的FlatRange数组与条目数“sorted”特性使地址翻译可以二分查找rcu/refFlatView采用 RCU 机制发布——MR 树变化时重建新的 FlatView读侧address_space_to_flatview()在 RCU 读锁内安全取用当前版本这正是前面调用链中RCU_READ_LOCK_GUARD()的原因root指向本视图所展平的 MR 树根节点用于检测“树是否已变化、是否需要重新展平”。可以推断FlatView 是一个“按需重建、多版本共存”的缓存任何 MR 增删如设备 realize/unrealize都会触发对应地址空间的重新展平而 Guest 正在执行的翻译操作不会被打断。AddressSpace不同类型的 Guest 地址空间AddressSpace结构体用以表示Guest 视角不同类型的地址空间。在 x86 下其实只有两种address_space_memory内存空间MMIO 走这里与address_space_io端口空间PMIO 走这里。单个AddressSpace结构体与一棵 MemoryRegion 树的根节点相关联并使用一个FlatView结构体建立该树的平坦化内存空间/** * struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects */ struct AddressSpace { /* private: */ struct rcu_head rcu; char *name; MemoryRegion *root; /* Accessed via RCU. */ struct FlatView *current_map; int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; QTAILQ_HEAD(, MemoryListener) listeners; QTAILQ_ENTRY(AddressSpace) address_spaces_link; };其中current_map就是当前生效的FlatView“Accessed via RCU”即要求读侧持 RCU 读锁访问listeners链表挂载MemoryListener回调当 MR 拓扑变化时逐一通知KVM 等加速器正是借此同步内存布局ioeventfds则用于 ioeventfd 优化——Guest 对特定 MMIO 地址的写可以直接通过事件 fd 通知后端典型如 virtio 的 kick 队列省去一次 VM-exit 到用户态的完整路径。至此Guest 视角的三层抽象关系可以概括为AddressSpace地址空间类型→ 1 棵 MR 树的rootMR 树嵌套、可动态变化→ 通过展平生成FlatView线性、有序、不可变快照每次 Guest 访问AddressSpace→ 取当前FlatView→flatview_translate()定位到具体 MR → RAM 直读直写 / MMIO 走ops回调。Host VMM 视角HVARAMBlockMR 对应的 Host 虚拟内存前述的 RAM MR 只是 Guest 侧的“描述”真正的内存存放在 Host 上。RAMBlock结构体用来表示单个实体 MemoryRegion 所占用的 Host 虚拟内存信息多个RAMBlock结构体之间构成单向链表struct RAMBlock { struct rcu_head rcu; struct MemoryRegion *mr; uint8_t *host; uint8_t *colo_cache; /* For colo, VMs ram cache */ ram_addr_t offset; ram_addr_t used_length; ram_addr_t max_length; void (*resized)(const char*, uint64_t length, void *host); uint32_t flags; /* Protected by iothread lock. */ char idstr[256]; /* RCU-enabled, writes protected by the ramlist lock */ QLIST_ENTRY(RAMBlock) next; QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers; int fd; size_t page_size; /* dirty bitmap used during migration */ unsigned long *bmap; /* bitmap of already received pages in postcopy */ unsigned long *receivedmap; /* * bitmap to track already cleared dirty bitmap. When the bit is * set, it means the corresponding memory chunk needs a log-clear. * Set this up to non-NULL to enable the capability to postpone * and split clearing of dirty bitmap on the remote node (e.g., * KVM). The bitmap will be set only when doing global sync. * * It is only used during src side of ram migration, and it is * protected by the global ram_state.bitmap_mutex. * * NOTE: this bitmap is different comparing to the other bitmaps * in that one bit can represent multiple guest pages (which is * decided by the clear_bmap_shift variable below). On * destination side, this should always be NULL, and the variable * clear_bmap_shift is meaningless. */ unsigned long *clear_bmap; uint8_t clear_bmap_shift; /* * RAM block length that corresponds to the used_length on the migration * source (after RAM block sizes were synchronized). Especially, after * starting to run the guest, used_length and postcopy_length can differ. * Used to register/unregister uffd handlers and as the size of the received * bitmap. Receiving any page beyond this length will bail out, as it * could not have been valid on the source. */ ram_addr_t postcopy_length; };比较重要的成员mr该 RAMBlock 对应的 MemoryRegion即建立 HVA → GPA 的反向索引MemoryRegion.ram_block与RAMBlock.mr互指host该块在 Host 上的虚拟地址基址通常由 QEMU 通过mmap()获得若未使用 KVMoffset/used_length/max_length该块在 QEMU 内部 RAM 地址空间中的偏移、当前使用长度与最大长度支持运行时 resizeidstr块的名字256 字节与 QOM 对象命名一致便于按名称查找fd块对应的文件描述符如内存后端文件、hugetlbfs 等bmap/receivedmap/clear_bmap热迁移相关的脏页位图、postcopy 已接收页位图、延迟清除脏位图与 CTF 单题场景关系不大但说明 RAMBlock 同时是迁移子系统的记账单元next所有 RAMBlock 串成的全局单向链表ramlist。RAM 访问的完整路径因此是Guest 物理地址 GPA →FlatView翻译到某个 RAM MR 的offset_in_region→ram_block-host offset_in_region得到 HVA → 直接内存访问KVM 场景下这一步由 EPT 在硬件上完成QEMU 只在缺页/迁移等场景介入。MR、子区域与 RAMBlock 的对应关系如下所示一个容易踩坑的细节是一个 RAMBlock 通常对应一整块连续 Host 内存而 MR 树上的 RAM 实体 MR 可以是这块内存的一个子区域subregion。因此在 Host 侧做内存取证或理解内存布局时不能假设“MR 边界 RAMBlock 边界”而要以ram_block指针 偏移为准。对 CTF QEMU Pwn 的意义把上面的模型放回 CTF 场景整条攻击面链条就非常清晰了题目通过-device xxx加载一个自定义设备如 QEMU 逃逸入门 中的 BlizzzardCTF2017 Strng 设备其启动命令为./qemu-system-x86_64 -m 1G -device strng ...设备 realize 阶段调用memory_region_init_io()注册 MMIO/PMIO 区域ops函数表指向回调MMIO MR 通过pci_register_bar()挂到 PCI BAR一个 container MR下最终并入address_space_memory的 MR 树Guest 内程序对 BAR 地址的每次读写触发 VM-exit经address_space_rw()→flatview_translate()落到这些回调利用点就在回调内部对设备状态结构opaque指向的对象的越界读写、UAF 等最终效果是攻击 QEMU 进程自身的堆内存——这正是 越界读写 等逃逸章节讨论的前提。也就是说读题时“找设备 → 找memory_region_init_io→ 读ops回调”的三步法本质上就是在 MR 树上定位可利用的叶子节点并用 FlatView 视角确认其 GPA 映射。延伸阅读仓库内QEMU 内存管理本文源文档QEMU 设备模拟IO 处理与 PCI 设备QEMU 逃逸入门以 Strng 为例简体中文对照版QEMU 内存管理含按 QEMU 官方文档细化的八类 MemoryRegion 说明源文档另列有 QEMU 官方文档memory 篇、understanding qemu 系列、《QEMU内存分析》系列博客等参考资料作为扩展阅读本文按仓库规范不再外链。赞分享文档网络安全教程【免费下载链接】ctf-wikiCome and join us, we need you!项目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki点击查看免费下载相关推荐QEMU 内存模型深度解析MemoryRegion 与 AddressSpace 内存 API 完全指南QEMU 内存模型深度解析MemoryRegion 与 AddressSpace 内存 API 完全指南 导读 QEMU 的 memory API内存 AP虚拟化硬件仿真QEMU 設備模擬原理解析從 VM-exit 到 MemoryRegion 的 MMIO/PMIO 處理鏈路ctf-wikiQEMU 設備模擬原理解析從 VM exit 到 MemoryRegion 的 MMIO/PMIO 處理鏈路ctf wiki 本篇基於 ctf wiki文档网络安全教程mercur内存模型JavaScript内存管理深度解析mercur内存模型JavaScript内存管理深度解析 前言为什么需要关注内存管理 在现代JavaScript应用中内存管理往往是开发者最容易忽视却又上一篇探索React Image Gallery构建高效图片画廊的利器下一篇passpie终端密码管理神器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Claude Code + TaoToken + GLM-4.1V-Thinking:视觉Agent评测环境搭建实战 2026/9/25 7:35:48

Claude Code + TaoToken + GLM-4.1V-Thinking:视觉Agent评测环境搭建实战

1. 为什么我要折腾这套视觉 Agent 评测环境先说清楚这套东西到底在干什么。Claude Code是 Anthropic 推出的命令行编程助手,能在终端里直接读写文件、跑命令、调工具,本质上是一个带工具调用能力的 Agent 运行时。TaoToken在这里扮演的是模型接入层&…

阅读更多 →
FPGA MicroBlaze Bootloader实现指南:从启动原理到Flash固化与OTA升级 2026/9/25 7:35:47

FPGA MicroBlaze Bootloader实现指南:从启动原理到Flash固化与OTA升级

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Design Compiler:Topographical Workshop Lab4 2026/9/25 7:35:40

Design Compiler:Topographical Workshop Lab4

相关阅读 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 目录 实验四、拥塞(实验时长:30分钟) 学习目标 任务一、将已编译的网表读取到DC-T中 任务二、使用文本报告分析拥塞 任务三…

阅读更多 →
Python采集中国天气网天气数据:JSON接口与城市ID实战 2026/9/25 7:35:39

Python采集中国天气网天气数据:JSON接口与城市ID实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Python入门实战:猜数字游戏完整开发教程 2026/9/25 7:35:38

Python入门实战:猜数字游戏完整开发教程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
PaddleSpeech Wav2Vec2ASR 在 LibriSpeech 上的微调实践与结果解读(asr3 示例) 2026/9/25 7:35:25

PaddleSpeech Wav2Vec2ASR 在 LibriSpeech 上的微调实践与结果解读(asr3 示例)

人工智能语音音频NLP媒体生成 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉