RISC-V调试与性能观测实战:从GDB断点到perf火焰图的完整流程

Linux C/C++进阶:从系统调用到实战项目,打通高性能开发路径 系统调用是用户程序与操作系统内核交互的核心接口,它管理着进程、内存、文件等关键资源。理解其原理是构建高性能应用的基础,例如通过减少不必要的系统调用和利用零拷贝技术可以显著提升I/O效率。在Linux环境下,C/C++开发者能够紧密控制系统资源,这种能力对于构建稳定、高效的后端服务至关重要。其技术价值在于能够直接操作底层硬件和系统机制,从而实现极致的性能优化和资源控制。这一特性使得C/C++成为AI基础设施、音视频处理、嵌入式系统等对性能和实时性要求极高领域的首选语言。本文以构建一个简易HTTP服务器为例,深 阅读详情

一、RISC-V调试体系与工具链全景

1.1 硬件调试设施

RISC-V 调试规范的抽象层次如下:调试器(GDB)通过 JTAG 的 DTM(Debug Transport Module) 访问 DMI(Debug Module Interface),进而操作调试模块内的 CSR——包括 DSCR(调试状态与控制)、DPC(调试 PC)、DCSR 等。核心机制是:

  • 暂停请求:调试器可请求任一 hart 进入调试模式,此时该 hart 停止执行并停在 dpc 指向的指令上;
  • 触发模块:实现硬件断点与观察点(数量由实现决定,通常 2-4 个);
  • 抽象命令:调试模块提供访问 GPR/CSR/内存的抽象命令,避免依赖目标运行代理(即不需要 gdbserver 常驻)。

这意味着 RISC-V 的调试路径可以是"纯硬件"的:只要 SoC 暴露了 JTAG 调试口,GDB 就能通过 OpenOCD 直接读写目标,与目标上是否运行操作系统无关。

1.2 软件工具链分工

工具角色典型端口
riscv64-unknown-elf-gdb / riscv64-linux-gnu-gdb调试前端,解释用户命令—
OpenOCDJTAG 传输层,桥接 GDB 与调试模块localhost:3333
QEMU(-s/-S)gdbstub 仿真目标localhost:1234
perf性能采样与统计平台 PMU 驱动

一套典型链路:GDB --(remote :3333)--> OpenOCD --(JTAG DMI)--> 目标 SoC 调试模块。QEMU 场景下则退化为 GDB --(remote :1234)--> QEMU gdbstub,用于验证调试流程与学习指令行为,二者命令完全一致。

1.3 环境验证

以下步骤确认本机调试链路可用:

# QEMU 端:暂停等待调试器
qemu-system-riscv64 -machine virt -smp 4 -m 2G -nographic \
    -kernel vmlinux -append "console=ttyS0" \
    -s -S &
# -s 开放 1234 端口;-S 表示上电即暂停,等待 GDB 连接

# GDB 端
riscv64-linux-gnu-gdb vmlinux
(gdb) target remote :1234
(gdb) info registers pc

若 info registers 能正确输出各 CSR(含 satp、mstatus),说明调试链路已打通。

二、GDB断点与单步实践

2.1 软件断点与硬件断点的选择

GDB 默认在可写内存区域使用软件断点(把目标指令替换为 ebreak),成本低、数量不限,但对只读内存(如 Flash 中的固件)或正在被执行的代码无效——此时必须使用硬件断点:

(gdb) hbreak 0x80200000       # 硬件断点,使用触发模块
(gdb) watch *(int*)0x80002000 # 硬件观察点,监控写访问

触发模块资源有限(通常 2-4 组),超出后会报 Target does not support breakpoints 一类错误,此时应删除无用断点再试。硬件断点数量可通过 info breakpoints 查看。

2.2 优化代码下的调试要点

RISC-V 工程普遍使用 -O2 发布,调试优化代码时注意三点:

  1. 变量可能被优化到寄存器中,print var 报 No symbol 时改用 info locals 观察寄存器内活值;
  2. 函数可能被内联,bt(backtrace)会看到调用栈被压缩——用 set print frame-arguments all 保留更多参数信息;
  3. 汇编级单步(stepi)配合 x/10i $pc 反汇编查看,是确认"编译器做了什么变换"的唯一可靠途径。

需要完整变量视图时,可为特定模块加 -O0 -g 重编(仅调试单元,不影响整体性能);或使用 -Og(优化调试模式)兼顾代码质量与可调试性。

2.3 异常与中断路径的断点

调试异常处理代码(如缺页、非法指令)时,普通断点难以命中——异常入口由 stvec/mtvec 决定,且多数异常瞬间完成。常用技巧:

# 在陷阱向量处设断点
(gdb) hbreak *$mtvec        # 直接对 CSR 当前值设硬件断点
(gdb) c
# 命中后查看陷阱原因
(gdb) p/x $mcause
(gdb) p/x $mtval           # 出错的虚拟地址或指令编码

若陷阱被频繁触发(如时钟中断),可用条件断点过滤:hbreak *$mtvec if $mcause == 0xc(仅外部中断时暂停)。

三、多核与SMP调试

3.1 hart 与线程的对应关系

RISC-V 的每个 hart 在 GDB 中表现为一个线程。info threads 可列出全部 hart,thread N 切换当前调试目标:

(gdb) info threads
  Id   Target Id         Frame
* 1    Thread 1 (hart 0) ...
  2    Thread 2 (hart 1) ...
(gdb) thread 2            # 切到 hart 1
(gdb) bt

SMP 内核调试中,跨核共享数据的一致性问题(见缓存与一致性篇)往往需要同时观测多个 hart 的寄存器与内存视图——GDB 的 thread apply all bt 可以在一次命令中抓取所有核的调用栈,是定位死锁与活锁的第一手段。

3.2 在 QEMU 多核上模拟

(gdb) target remote :1234
(gdb) info threads
(gdb) thread 1
(gdb) hbreak start_kernel
(gdb) continue

QEMU 的 gdbstub 支持完整的 SMP 视图,包括每个 hart 独立的 PC 与 CSR。需要注意:QEMU 不模拟 JTAG/触发模块的延迟语义,硬件断点在 QEMU 上命中行为与真实芯片可能存在细微差异,涉及触发模块数量的验证仍以真机为准。

四、perf与PMU性能观测

4.1 PMU 事件映射

RISC-V 的性能计数器通过 mhpmcounter* 与 mhpmevent* CSR 暴露,Linux 侧由驱动映射为 perf 事件。不同平台的事件编号定义不同,先查询平台支持的集合:

# 列出平台支持的硬件事件(名称随实现而异)
perf list | grep -i -E "cache|branch|cycle|instruction"

若事件映射不完整,可退回到通用软件事件(task-clock、context-switches)或使用周期计数(cycles)做相对比较。

4.2 perf stat 与 perf record

# 统计模式:快速对比整体指标
perf stat -e cycles,instructions,branches,branch-misses ./bench

# 采样模式:生成热点分布
perf record -F 99 -g ./bench --iter 100
perf report

-F 99(99 Hz 采样)是降低开销的常用配置;-g 启用调用栈采集,是生成火焰图的前提。采样频率过高会显著拖慢被测程序,推荐 50-100 Hz。

4.3 火焰图生成流程

perf record -F 99 -g ./bench
perf script > out.perf
# 使用 FlameGraph 工具集(github.com/brendangregg/FlameGraph)
./stackcollapse-perf.pl out.perf > out.folded
./flamegraph.pl out.folded > flame.svg

火焰图的解读原则:横轴为采样占比(宽度即热度),纵轴为调用栈深度。关注"宽而矮"的栈顶函数——它通常是自耗时热点;"高而窄"的尖塔指向深层递归或锁竞争。

五、内存与二进制诊断

5.1 反汇编与符号核对

优化后代码的行为验证依赖反汇编:

riscv64-linux-gnu-objdump -d vmlinux | less
riscv64-linux-gnu-objdump -S -l vmlinux   # 混排源码,需 -g 编译
llvm-objdump --mattr=+v -d app.elf        # 查看 RVV 指令需显式开启扩展

注意:objdump 默认按 ELF 头中的架构信息反汇编,若二进制由 -march=rv64gcv 生成而 objdump 版本较旧,可能无法识别向量指令——此时用 llvm-objdump 并显式传入 --mattr。

5.2 Core Dump 分析

目标上崩溃后,离线分析 core 文件:

riscv64-linux-gnu-gdb ./app ./core
(gdb) bt full
(gdb) info registers
(gdb) x/8i $pc - 16    # 查看崩溃点附近指令

核心问题是编译选项与崩溃现场的一致性:分析 core 用的可执行文件必须与运行时的二进制完全一致(含相同的 -O 与扩展),否则反汇编与行号信息全部错位。

5.3 内存访问类问题的排查工具

缓存与一致性篇提到的"陈旧数据"类问题,在调试阶段可通过 watch 观察点或 x/ 内存查看辅助定位。若怀疑数据竞争,用 GDB 的 set scheduler-locking on 冻结其他 hart,逐步重现单核执行序,再对比多核自由运行时的差异——这是定位弱内存序问题的经典方法。

六、综合案例:启动挂死的定位过程

6.1 现象

某 RV64GCV 多核 SoC 平台运行 Linux,内核打印完 SMP bring-up 信息后无响应,控制台不再输出。

6.2 排查步骤

  1. 确认卡死位置:通过 OpenOCD 连接,info threads 显示 hart 0 停在 default_idle,hart 1 停在自旋等待——初步判断为核间同步问题;
  2. 抓取全部调用栈:thread apply all bt 显示 hart 1 卡在 arch_spin_lock 的自旋循环内;
  3. 检查锁变量状态:x/wx &lock 显示锁值为 0(未被持有),但持锁方 hart 0 已进入 idle——矛盾出现;
  4. 回查代码:发现 hart 1 的加锁路径缺少 acquire 语义(见缓存与一致性篇 5.1 的同类问题),释放侧也未使用 rl 修饰位;
  5. 修复验证:补上 .aq/.rl 后重新编译,启动流程正常完成。

6.3 案例启示

该案例中调试工具只提供了"卡在哪"的线索,真正的根因在内存模型层。调试与观测的价值在于快速缩小范围,最终判断仍需结合机制知识——这也印证了系列文章之间互相衔接的必要性。

结语

调试与观测是 RISC-V 工程实践的地基:GDB 解决"程序在哪、为什么停",perf 解决"时间去哪了",而二者的正确使用都依赖于对调试规范与 PMU 平台映射的理解。RISC-V 的调试体系仍在演进(Trigger Module 数量、调试规范版本、perf 事件标准化),新平台 bring-up 时建议先花时间确认工具链与硬件调试设施的版本匹配关系。

llvm-project 是什么?深度解析现代编译器基础设施核心架构 llvm-project 是支撑 C/C++、Rust、AI 框架等多语言编译的工业级基础设施,其本质是一套基于 LLVM IR 的模块化编译器框架。它通过统一中间表示(LLVM IR)实现前端与后端解耦,依托 Clang 前端、LLVM Core 优化器、LLD 链接器、LLDB 调试器及 MLIR 多层表示等组件协同工作,提供可定制、可验证、跨架构的代码生成能力。技术价值在于标准化编译流程、保障优化安全性、支持硬件适配与领域专用语言(DSL)开发,广泛应用于芯片设计(如 RISC-V)、嵌入式系统、AI 阅读详情

相关推荐

ARM / RISC-V 芯片设计生成全流程深度报告(2026):工具链、技术栈与制造工艺

从产品定义一路走到量产爬坡:13 个阶段、4 大工程域、全阶段 EDA 工具矩阵、先进制程与封装工艺、成本与周期模型、签核清单与风险登记册,并标注 ARM 与 RISC-V 两条路线的真实差异。

厚积薄发 555

【Linux内核专栏 16】调试与性能

对于gdb 重度用户(stat_snap),本篇是你的 Linux 调试工具箱。从 printk(基础日志)到 ftrace(函数跟踪)、perf(性能剖析)、kprobe(动态插桩)、eBPF(现代神器)、oops/crash(死机分析)、lockdep(死锁检测)。读完能在 Linux 上达到你裸机 gdb 的调试精度,甚至更强。

peter_pan_study的博客 347

【信息科学与工程学】【数据中心】第三十五篇 云计算数据中心的学科知识04

编号学科(课程)核心知识点在云计算/云存储/云网络/云安全/云MaaS中的作用代表教材/资料/论文 + 数学方程式列表工业界应用D1421​云原生数据库:TiDB​HTAP(混合事务/分析处理)、分布式SQL、水平扩展、强一致(Raft)、自动故障恢复、与MySQL兼容、TiFlash列式引擎提供弹性扩展的分布式数据库;支撑高并发在线交易与实时分析教材:《TiDB in Action》PingCAP(2020) 论文:《TiDB: A Raft-based HTAP Database》(2017)

weixin_49199313的博客 407

RISC-V基础指令集:比较、跳转和寻址

上半部分处理的是数据怎么算、怎么在内存和寄存器之间搬运数据。下办部分处理的是另外一个维度:数据算出来之后,程序怎么根据结果做决定,以及怎么访问CPU内部那些控制寄存器。指令全称中文作用slt / sltu小于则置位比较两个寄存器,rs1 < rs2 则 rd = 1,否则 rd = 0小于立即数则置位寄存器与常数比较,结果写 0 或 1jal跳转并链接跳到目标地址,同时把返回地址保存在 rdjalr寄存器跳转并链接跳到 rs1 + offset,同时保存返回地址beq。

weixin_43903002的博客 269

【信息科学与工程学】计算机科学与自动化——第二十四篇 编译器04 LLVM编译器01

训推一体方案通过整合训练与推理流程,实现资源复用、效率提升和全链路自动化。以下从。

weixin_49199313的博客 1518

【信息科学与工程学】计算机科学与自动化 第二百三十三篇 凤凰架构02

① Firecracker 为每个 microVM 提供极简设备模型:virtio-net, virtio-blk, serial console。:① BB84:Alice 随机选择基矢(+ 或 ×)发送单光子,Bob 随机测量基矢,比对后保留一致位的子集作为原始密钥。:密度 1 EB/mm³;:① Parquet 文件:行组(Row Group)→ 列块(Column Chunk)→ 页(Page)。

weixin_49199313的博客 137

16 倍三角函数加速:MIPS 把机器人关节装进一颗 RISC-V 芯片

这两年谈"物理 AI"的人很多,但真正落到硬件上,最难的不是大模型,而是把 AI 的决策翻译成精准、安全、可预测的物理动作。关节。每个关节必须在空间、重量、功耗和散热的严格约束下,实现平稳且拟人的运动——从肘部到指尖,每一处都是"最后一环"。传统做法是分层堆芯片:一颗跑 AI 推理的 SoC、一颗跑实时控制的 MCU、再来一颗管通信的,通过总线连起来。代价是延迟叠加、链路复杂、功能安全认证碎片化。一颗芯片全包。fill:#333;important;important;fill:none;

嵌入式单片机实验室 314

基于Java17、SpringBoot、vue3、antdv-next、uniapp等主流技术构建的全场景极速开发平台 MDP内置3个web端、1个移动端 重点解决用户中心、开发者平台、管理后台3个应

MDP-主数据平台,后端项目。专注于单点登录解决方案。内置用户中心、开发者平台、管理后台3个应用。包含:单点登录、Oauth2 登录、用户身份管理、应用申请、应用接入、主数据维护、主数据订阅、主数据广播、应用接口调用、接口管理管理和查看、系统配置等功能。

RISC-V 基础软件的工程化与性能优化实践

从软件生态现状、优化方法到在龙蜥社区、如意社区等的开源贡献,这些探索展现了基础软件连接硬件能力与业务价值的作用,也为 RISC-V 生态共建提供了实践参考。

weixin_60347558的博客 411

Win7时间修复(时间错误修复文件)

运行方法:解压后运行reg文件即可。 支持的Win7版本: 1. Windows 7 Starter(入门版 / 初级版) 2. Windows 7 Home Basic(家庭普通版) 3. Windows 7 Home Premium(家庭高级版) 4. Windows 7 Professional(专业版) 5. Windows 7 Enterprise(企业版) 6. Windows 7 Ultimate(旗舰版) 7. Windows 7 Professional for Embedded Systems(嵌入式专业版) 8. Windows 7 Ultimate for Embedded Systems(嵌入式旗舰版)

YOLO26算法行人行走检测+训练好的模型+102张数据集+pyqt可视化界面.zip

附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[行走的人(person walking)] 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 67 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.8000** mAP50-95 | 0.5620 Precision | 0.5795 Recall | 0.8235 train/box_loss | 0.9538 train/cls_loss | 1.9897 val/box_loss | 0.9034 val/cls_loss | 2.7344 【训练过程分析】 进入训练阶段后,模型一开始的 mAP50 和 mAP50-95 均为 0.8000 和 0.5620,表明在开始阶段模型的收敛情况良好。从第 30 轮起,训练集的 mAP50 值稳定在了 0.8000,这说明模型在这之前能够迅速捕捉到主要目标,但精度提升的余地已然不大。同时,mAP50-95 在训练集上表现略差,从第 50 轮开始慢慢往上走至 0.5620。这反映出模型在检测更小、更远的目标上还存在一定差距,精度成为瓶颈。 随着训练深入,模型在验证集上的表现开始分化。从第 60 轮开始,验证集的 mAP50 和 mAP50-95 值分别为 0.7500 和 0.4500,相比训练集下降明显,表明模型存在一定程度的过拟合现象。训练集上的 box loss 和 cls loss 值分别为 ... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。

RISC-V体系结构-基础指令集

在学具体指令之前,先建立一个认识:一条指令,就是CPU能做的一个“动作”。比如把“两个数加起来”,“从内存读一个树”,“跳到程序另外一个地方”,每一个动作对应一条指令。RISC-V的基础整数指令集叫 RC32I\RV64I(RV是RISC-V,32\64是地址宽度,I是Integer整数)。指令全称中文作用lwLoad Word加载字从内存读 4 字节到寄存器swStore Word存储字把寄存器的 4 字节写入内存lbLoad Byte加载字节从内存读 1 字节,符号扩展。

weixin_43903002的博客 138

科技中介服务机构想要提升服务效率,需要哪些数智工具支持?.docx

科技中介服务机构想要提升服务效率,需要哪些数智工具支持?

基于变频控制的多相交错LLC谐振变换器闭环仿真(Simulink仿真实现)

基于变频控制的多相交错LLC谐振变换器闭环仿真(Simulink仿真实现)内容概要:本文主要介绍了基于Plecs的全桥LLC谐振变换器仿真模型,涵盖变频控制下的多相交错LLC谐振变换器闭环仿真、V2G电动汽车ACDC整流与双向CLLC谐振变换器充放电仿真、LLC谐振变换器的开环与闭环软启动设计,以及储能系统中双向Buck-Boost变换器结合模型预测电流控制和电压下垂控制的仿真研究。同时,文档列举了多种电力电子系统与控制策略的Simulink/Plecs仿真案例,涉及三相交错并联Buck变换器、三电平Buck直流变换器、单相Boost PFC电路等,展示了丰富的电力变换器建模与控制技术。此外,还包括参数设计报告、计算书及相关参考文献,适用于从事电力电子、新能源发电、电动汽车充放电系统等领域的研究人员和技术开发人员。; 适合人群:具备电力电子、自动控制理论基础,从事新能源、电动汽车、电力系统等相关领域研究的研发人员、高校研究生及高年级本科生。; 使用场景及目标:① 学习和掌握LLC谐振变换器及其他典型电力电子变换器的工作原理与建模方法;② 实现闭环控制策略如变频控制、软启动、模型预测控制、下垂控制等的仿真验证;③ 支持科研项目、毕业设计或工程开发中的系统仿真与优化设计。; 阅读建议:建议结合文中提供的仿真模型、设计报告与参考文献,逐步搭建并调试相应系统,重点关注控制策略的实现细节与参数整定过程,以深入理解系统动态响应特性与控制性能。

usb 扩容盘检测修复工具源码,编译产物

usb 扩容盘检测修复工具源码,编译产物

融合UWB和IMU割草机定位EKF研究(Matlab代码实现)

内容概要:本文主要介绍了一个名为“Plecs全桥LLC谐振变换器仿真模型”的技术资源,该资源聚焦于电力电子领域中的LLC谐振变换器建模与仿真,涵盖开环、闭环控制、软启动设计及参数优化等核心内容。文档不仅提供了LLC变换器的详细建模方法与仿真案例,还系统梳理了其在高效电源转换系统中的应用,包括隔离型全桥拓扑结构的设计与性能分析。此外,资源汇总了大量Matlab/Simulink仿真模型及相关科研方向,涉及新能源并网、储能控制、电机驱动等多个前沿领域,全面展示LLC谐振变换器在现代电力系统中的关键技术实现路径。同时,文档附带多种学习资料获取途径,如网盘链接和公众号资源,便于研究人员深入实践与拓展研究。; 适合人群:具备扎实的电力电子、自动控制理论基础,从事新能源发电、开关电源设计、电力系统仿真等相关领域的研究生、工程师及科研人员。; 使用场景及目标:①深入理解LLC谐振变换器的工作原理、建模方法与控制策略;②开展电力电子变换器的仿真验证与参数优化设计;③支撑科研项目、学位论文或工程项目的系统仿真与方案验证; 阅读建议:建议结合所提供的仿真模型与参考文献,使用Plecs或Simulink软件进行动手实践,重点掌握LLC谐振变换器的建模流程、闭环控制设计、软启动机制及参数调试技巧,以全面提升在实际工程中的应用与创新能力。

独立储能的现货电能量与调频辅助服务市场出清协调机制(Matlab代码实现)

内容概要:本文标题为“Plecs全桥LLC谐振变换器仿真模型”,但实际内容严重偏离主题,文档中混杂了大量来自优快云博客平台的无关信息,涵盖多个不同领域的Matlab/Simulink仿真项目,如电力系统优化、无人机路径规划、机器学习预测、微电网调度、卡尔曼滤波、无线能量传输等,导致核心内容缺失。文档未能提供关于Plecs平台下全桥LLC谐振变换器的建模方法、电路结构、参数设计、控制策略或仿真结果等关键技术细节,实质信息与标题完全不符,不具备作为该主题参考资料的有效性。; 适合人群:从事电力电子变换器研究、电源系统设计及相关领域的工程师、高校研究生与科研人员,尤其是希望掌握LLC谐振变换器建模与仿真的专业技术人员。; 使用场景及目标:① 学习并掌握全桥LLC谐振变换器的工作原理与Plecs仿真建模技术;② 开展高效电源转换器的研发与性能优化;③ 作为教学或科研项目中电力电子电路仿真的参考资料。; 阅读建议:鉴于文档内容与标题严重不符,建议读者谨慎甄别,优先选择专业书籍、学术论文或官方仿真软件教程等权威资源进行学习,避免被无效信息误导。

人形机器人系列——硬件介绍

人形机器人是多领域交叉技术的产物,主要由三大系统组成:感知系统、决策系统和执行系统。感知系统感知系统是人形机器人获取外界信息的途径,主要由各种传感器组成。其中,视觉传感器用于获取图像信息,如摄像头、激光雷达等;触觉传感器用于感知触碰和压力,如力/力矩传感器、声学传感器等。这些传感器收集到的信息为机器人的决策和执行提供基础。决策系统决策系统是人形机器人的大脑,负责处理和决策各种信息。它由芯片和算法组成。芯片是硬件基础,提供计算能力;算法是软件基础,用于处理和分析传感器收集到的信息,并做出相应的决策。执行系统。

liangwqi的博客 1万+
上一篇: RISC-V编译优化实战:从-march/-mtune到RVV自动向量化的完整流程
下一篇: RISC-V平台安全实战:从PMP物理内存保护到Smepmp与安全启动的完整流程
RISCV_Explorer
博客等级 码龄99天 6粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值