共享内存分配与ARM+DSP核间通信IPC(MessageQ)

SOC-IPC核间通讯 IPC通讯是AUTOSAR体系结构中的核心组成部分,它使得不同的软件组件可以相互通信、协同工作,从而实现整车系统的功能。IPC可以理解为核间通讯在多核处理器系统中,不同的处理器核之间可以通过共享内存、消息传递等方式进行IPC核间通讯。共享内存是指多个处理器核共享同一块物理内存,通过在内存中设置标志位或锁等机制来控制对共享数据的访问。消息传递是指不同处理器核之间通过发送和接收消息来进行通信,其中消息可以是数据、信号等。 阅读详情
AI摘要

本文详细介绍了IPC(Inter-Processor Communication)在多核处理器中的应用,特别是MessageQ模块,它支持可变长度消息的发送和接收。MessageQ允许一个读取器和多个写入器,通过消息队列进行通信。文中还阐述了MessageQ的创建、打开、分配、发送、接收和删除等关键操作,以及如何设置消息优先级和应答队列。此外,还提及了在AM5728核心板上利用共享内存进行数据交换的实践案例。

IPC核间通信

IPC(Inter-Processor Communication)提供与处理器硬件无关的API,可用于多核处理器核间通信、同一处理器进程间通信和设备间通信。对于异构多核处理器,可通过IPC组件进行核间通信。IPC通信中常用的MessageQ——大小可变的消息传递模块。这是一种功能强大但易于使用 MessageQ 的消息传递, 调用MessageQ 模块后,如下图标红部分:MessageQ 模块工作场景图
在MessageQ 模块工作场景图中,灰色的部分并不是不要的,只是在MessageQ中,灰色部分会在应用程序 main ()函数中的 Ipc _ start () API 调用负责配置,我们在只需要关注MessageQ 模块工作场景图的标红部分即可。所有使用 IPC 模块的应用程序都必须调用 IPC _ start () API,该 API 执行以下操作:
1、初始化 IPC 使用的许多对象和模块同步多个处理器,以便它们可以以任何顺序引导。
2、IPC _ start ()使用索引为0(零)的共享区域创建资源管理表,供其他 IPC 模块在内部使用。
所以在调用 Ipc _ attach ()之前,必须在处理器上调用 Ipc _ start ()。
MessageQ 模块支持可变长度消息的结构化发送和接收。它是独立于操作系统的,可以使用任何线程模型。**对于你创建的每个 MessageQ,只有一个读取器,可能有多个写入器。**消息通过消息队列发送和接收。读取器是从消息队列中获取(读取)消息的线程。写入器是一个将消息放入(写入)消息队列的线程。每个消息队列有一个读取器,可以有多个写入器。一个线程可以读取或写入多个消息队列。
单个读线程调用 MessageQ _ create ()、 MessageQ _ get ()、 MessageQ _ free ()和 MessageQ _ delete ()。
Writer 线程调用 MessageQ _ open ()、 MessageQ _ alloc ()、 MessageQ _ put ()和 MessageQ _ close ()。
上述的MessageQ读取和写入流程可以用流程图表示:MessageQ读取和写入流程图
从概念上讲,读线程拥有一个消息队列。读线程创建一个消息队列。然后,Writer 线程打开创建的消息队列以访问它们。

创建 MessageQ 对象MessageQ _ create ()

读线程创建一个消息队列。要动态创建一个 MessageQ 对象,其语法如下:
MessageQ_Handle MessageQ_create(String name,MessageQ_Params *params);
创建队列时,需要指定名称字符串,因为MessageQ _ open ()函数需要此名称。虽然这个名称不是必需的(也就是说,它可以是 NULL) ,但是一个未命名的队列是不能被打开的。如果调用成功,则返回 messageq_handle。如果调用失败,则返回 NULL。
创建 MessageQ 对象

打开消息队列MessageQ _ open ()

Writer 线程打开创建的消息队列来访问它们。为了获得已创建的消息队列的句柄,编写线程必须调用 MessageQ _ open () ,其语法如下。
Int MessageQ_open(String name, MessageQ_QueueId *queueId);
这个函数需要一个名字——String name,必须与创建对象的名字匹配。如果在任何处理器上没有找到匹配的名称, MessageQ_open()将返回MessageQ_E_NOTFOUND,如果 MessageQ open 成功,队列 ID 被填充 MessageQ_S_SUCCESS。打开消息队列

分配消息MessageQ _ alloc ()

MessageQ 通过 MessageQ _ alloc ()和 MessageQ _ free ()函数管理消息分配;
MessageQ 使用 Heaps 进行消息分配;
MessageQ_Msg MessageQ_alloc(UInt16 heapId, UInt32 size);
MessageQ _ alloc ()中的分配大小必须包括消息头的大小,也就是32字节。一旦消息被分配,它可以被发送到任何消息队列。一旦读取器接收到消息,它可以释放消息或者重新使用消息。如果应用程序没有使用 MessageQ _ alloc ()分配的消息,则无法通过 MessageQ _ free ()函数释放消息,即使消息由不同的处理器接收。另外,传输可能会在内部调用 MessageQ _ free ()并且遇到错误。分配消息

发送消息MessageQ _ put ()

一旦打开消息队列并分配了消息,就可以通过 MessageQ _ put ()函数将消息发送到 MessageQ。函数语法如下:
Int MessageQ_put(MessageQ_QueueId queueId, MessageQ_Msg msg);
可以通过 MessageQ _ getreplyqueue ()函数“发现”消息队列 ID,
/* 使用嵌入的答复目的地 */

replyMessageQ = MessageQ _ getreplyqueue (msg);
if(replyMessageQ == MessageQ _ invalidmessageq)
{ 
	System _ abort (“ Invalid reply queue n”) ;
}

/* 发送回应 */

Status = MessageQ _ put (replyQueue,msg) ;
if(Status < 0)
{
	System _ abort (“ MessageQ _ put 不成功 n”) ;
}

如果 MessageQ _ put ()成功,则返回 MessageQ _ s _ success。
发送消息
在发送消息之前,可以使用 MessageQ _ setmsgid ()函数为接收线程可以检查的消息分配一个数值。
/* Increment… 远程端将检查这个 */

msgId++;
MessageQ _ setmsgid (msg,msgId);

还可以使用 MessageQ _ setmsgpri ()函数来设置消息的优先级。

接收信息MessageQ _ get ()

为了接收消息,读线程调用MessageQ _ get () API接口,接口函数如下所示:
Int MessageQ_get(MessageQ_Handle handle,
MessageQ_Msg *msg, UInt timeout)

Status = MessageQ _ get (MessageQ,& msg,MessageQ _ forever); if (status < 0)
{
	System _ abort (“不应该发生; 永远超时n”) ;
}

接收信息
如果没有消息出现,也没有错误发生,这个函数会在等待消息到达的超时期间阻塞。如果超时过期,则返回 MessageQ _ e _ fail。如果发生错误,msg 参数将不会改变。收到消息后,可以使用以下 api 从消息头获取有关消息的信息:
1、MessageQ _ getmsgid ()获取 MessageQ _ setmsgid ()设置的 ID 值。例如:
/* 获取 id 并将其递增以发送回 */
msgId = MessageQ _ getmsgid (msg) ;
MessageQ _ setmsgid (msg,msgId) ;
2、Messageq_getmsgpri ()获得 messageq_setmsgpri ()设置的优先级。
3、MessageQ _ getmsgsize ()获取以字节为单位的消息大小。
4、Messageq_getreplyqueue ()获取 messageq_setreplyqueue ()提供的队列 ID。

删除 MessageQ 对象MessageQ _ delete ()

MessageQ _ delete ()释放存储在本地内存中的 MessageQ 对象。如果任何消息仍然在内部链接列表中,它们将被释放。句柄的内容被函数取空,以防止删除后使用。
Void MessageQ _ delete (MessageQ _ handle * handle) ;
一旦消息队列被删除,就不能向它发送任何消息。 MessageQ _ close ()是推荐的,但不是必需的。
删除 MessageQ 对象

消息优先级

MessageQ 支持以下三个消息优先级:
1、MessageQ _ normalpri = 0;
2、MessageQ _ highpri = 1;
3、MessageQ _ urgentpri = 3;
可以在发送消息之前使用 MessageQ _ setmsgpri 函数设置消息的优先级:
Void MessageQ_setMsgPri(MessageQ_Msg msg,
MessageQ_Priority priority);
在内部,MessageQ 对象维护两个链表: 普通链表和高优先级链表。一个普通的优先级消息以 FIFO 的方式放置在“普通”链表中。一个高优先级的消息以 FIFO 的方式被放置到“高优先级”链表中。紧急消息被放置在高链表的开头。
由于在阅读一条信息之前可能会发送多条紧急信息,因此不能保证紧急信息的顺序。
当收到消息时,读者首先查看高优先级链接列表。如果一条消息出现在这个列表中,它就会被返回。如果没有,则检查正常的优先级链接列表。如果一条消息出现在那里,它将被返回;否则同步器的等待函数就会被调用。

应答队列

对于某些应用程序,在队列上执行 messageq_open ()是不现实的。例如,服务器可能不想打开所有客户端的队列来发送响应。为了支持这个用例,消息发送者可以使用 MessageQ _ setreplyqueue ()函数在消息中嵌入一个回复 queueId。
Void MessageQ_setReplyQueue(MessageQ_Handle handle,
MessageQ_Msg msg)
这个 API 将消息队列的 queueId 存储到 MsgHeader 中的字段中。
MessageQ _ getreplyqueue ()函数执行相反的操作。例如:

MessageQ_QueueId replyQueue;
MessageQ_Msg msg;
...
/* Use the embedded reply destination */
replyMessageQ = MessageQ_getReplyQueue(msg);
if (replyMessageQ == MessageQ_INVALIDMESSAGEQ) 
{
	System_abort("Invalid reply queue\n");
}

这个函数返回的 MessageQ _ queueid 值可以在 MessageQ _ put ()调用中使用。
应答队列

共享内存分配

AM5728核心板的Linux 内核预留0xa0000000~0xac000000(192MByte)内存作为 CMEM 共享内存。
AM5728内存
本次实验使用 0xa0000000~0xa0200000(2MByte)作为共享内存进行测试,此 2MByte 内存划分为 4 个 512KByte(0x80000,524288)池空间。设备树修改如下:
共享内存
共享内存分区
更换设备树后重新启动开发板,查询内存分配及空间大小:
查询开发板内存空间
在上述共享内存分区中,id 0池空间用于存放原始的时域数据,id 1池空间用于存放处理后的频域数据,剩余两个池空间先分配出来,不使用。DSP 端(DSP1)对共享内存 dataln 的数据进行 FFT 幅值运算,并把结果存入共享内存 dataOut,ARM 端(Cortex-A15_0)读取共享内存 dataOut 的数据并写入到 FFTData文件。
DSP 端创建一个 message 来传递信息,ARM 端使用 CMEM 创建4个空间用于数据的存储,“msg->dataIn”和“msg->dataOut”分别指向这其中两个空间的首地址。线性调频信号(LFM)模拟数据存入共享内存 dataIn,并发送消息至 DSP 端。DSP 端接收到消息后,读取共享内存 dataIn的数据进行 FFT 幅值运算,并把结果存入共享内存dataOut,同时发送消息至 ARM 端。ARM 端接收到消息后,从共享内存 dataOut 中读取数据并写入 FFTData 文件。最后发送ShutDown 消息到 DSP 端,DSP 端接收到该消息后,将信息回传至 ARM 端,关闭自己并重新初始化。
程序运行结果

实例工程文件下载

资源列表
实例工程文件下载

DSP多核通信——IPC组件 slaver核心也注册了notify,设置了一个信号量,一直等待信号量释放,当master发送event之后,slaver的回调函数cbFxn就会被调用,进入这个回调函数,就可以获取这个共享区域指针同时释放信号量,收到信号量后slaver的主函数会继续往下执行,slaver就通过SharedRegion_getPtr函数将共享区域指针转换成内存地址,slaver就可以读取这个内存地址里面的值。最大的特点就是实时。添加入口有两种方式:一种是静态的(在cfg文件里添加),一种是的动态的(在代码里添加)。 阅读详情

相关推荐

dsp MessageQ消息队列

dsp 重要的通信机制MessageQ: 这个通信机制使用的很广泛,比Notif的优点就是其可以传递大于32bit的数据, 而notify机制只能传递小于32bit的数据。 我们需要对Heapbuf进行初始化并申请Heapbuf内存。 HeapBufMP_Params_init(& heapBufParams); heapBufParams.regionId = headId;

KiranRao的博客 2609

DSP- 6678---------messageQ的使用

MessageQ模块:主核(核0)在将图像文件输入共享内存后,需要将输入图像缓存和输出图像缓存的地址打包成消息,传递给从核。总之,MessageQ是用来传递少量信息的,一般是地址,标志位之类的参数,不是传递大规模数组用的。对于大规模的数组,可以利用messageQ传递其首地址。 MessageQ模块的主要特点: 1. 实现了处理期间变长消息的传递,所需要传递的消息一般超过32bit; 2. 其消息的传递都是通过操作消息队列来实现的; 3. 每个消息队列可以有多个写者,但只能有一个读者,而每个任务(task)

kunkliu的博客 2177

TI AM5728核间通讯实战:手把手教你用MessageQ实现ARM与DSP数据交互

本文详细介绍了在TI AM5728异构多核SoC上使用MessageQ实现ARM与DSP核间通讯的实战方法。从环境搭建、内存配置到MessageQ API调用流程,提供了完整的开发指南和调试技巧,帮助开发者解决异构系统通讯中的常见问题,适用于工业自动化和医疗影像等实时性要求高的领域。

weixin_29197699的博客 117

ARM与DSP异构双核SoC内存管理与协同设计实战解析

在嵌入式系统与高性能计算领域,内存管理是决定系统性能、实时性与稳定性的核心技术。其核心原理在于通过内存管理单元(MMU)、缓存(Cache)及直接内存访问(DMA)等机制,协调处理器对存储资源的访问,解决多核或多主设备间的数据一致性问题。这项技术的价值在于能显著提升数据吞吐效率、降低访问延迟,并确保在复杂任务下的可靠协同。它广泛应用于实时信号处理、音视频编解码、通信基带及工业控制等场景。本文以典型的ARM+DSP异构双核SoC(如OMAP-L138)为例,深入探讨了缓存一致性维护、共享内存区域配置及核间通信

angou6476的博客 329

DSP+ARM+FPGA异构平台开发实战:架构、通信与多核协同

在嵌入式系统与高性能计算领域,异构计算架构通过整合不同架构的处理器核心,如通用CPU、数字信号处理器和可编程逻辑门阵列,旨在实现性能、功耗与灵活性的最优平衡。其核心原理在于根据任务特性进行硬件加速,将控制密集型、计算密集型和高度并行化的任务分别卸载到最擅长的处理单元上执行。这种架构的技术价值在于能够显著提升复杂实时信号处理、图像视觉等应用的吞吐量和能效比。典型的应用场景包括雷达信号处理、软件无线电和高端机器视觉系统,这些场景通常涉及高速数据采集、流式处理和低延迟响应。本文以XQ6657Z45-EVM开发板为

weixin_30755393的博客 394

异构多核SoC架构解析:Arm、DSP与PRU协同设计在工业实时系统中的应用

在嵌入式系统设计中,异构多核片上系统(SoC)通过集成不同类型的处理器内核,实现了通用计算与专用实时任务的高效协同。其核心原理在于将任务按特性分配到最合适的处理单元:通用处理器(如Arm Cortex-A系列)负责运行复杂操作系统和上层应用,而数字信号处理器(DSP)则专注于计算密集型算法,可编程实时单元(PRU)处理微秒级确定性控制。这种架构的技术价值在于同时满足高性能计算、高实时性响应和低功耗需求,尤其适用于工业自动化、汽车电子和专业音频处理等场景。例如,在工业控制系统中,Arm核可运行Linux管理网

banglvfei0870的博客 458

深入解析TI 66AK2L06异构SoC:架构、硬件加速与多核开发实战

在嵌入式系统与信号处理领域,异构计算架构通过集成不同类型的处理器核心(如DSP与ARM)和专用硬件加速单元,实现了性能与能效的显著提升。其核心原理在于将通用控制任务与高强度数学运算合理分工,并利用硬件协处理器卸载特定算法负载。这种设计带来了巨大的技术价值:它能够有效应对无线通信、医疗影像等场景中海量数据的实时处理需求,同时降低系统复杂度与功耗。具体到应用层面,此类SoC常用于5G物理层、雷达波束成形等需要同时处理高速数据流与复杂协议栈的场合。本文聚焦于德州仪器(TI)的66AK2L06芯片,它集成了C66x

weixin_33749131的博客 344

TI OMAP-L138双核异构SoC:ARM+DSP协同设计在嵌入式实时系统中的应用

在嵌入式系统开发中,异构计算架构通过集成不同特性的处理器核心,如通用处理器与数字信号处理器,实现了控制与计算任务的优化分工。其核心原理在于利用共享内存与高效总线互联,让擅长复杂控制流和操作系统管理的ARM核心与专为数学密集型任务设计的DSP核心协同工作。这种架构的技术价值在于平衡了系统通用性、实时性与计算效能,有效解决了工业自动化、音频处理等领域对算力与实时性的双重需求。具体到应用场景,例如在需要人机交互和实时信号分析的智能设备中,ARM端可运行Linux处理协议栈与UI,而DSP端则专注执行滤波、FFT等

dbp5156的博客 388

深入解析TI AM571x异构处理器:架构、外设与硬件设计实战

异构多核处理器是现代嵌入式系统实现高性能与实时性平衡的关键技术。其核心原理在于将不同类型的计算任务(如通用计算、实时控制、信号处理)分配到最合适的专用处理单元上执行,从而在单一芯片上实现高效的任务并行与隔离。这种架构的技术价值在于能够显著提升系统整体效率、降低功耗,并满足工业自动化、机器视觉、智能网关等复杂应用场景对实时响应和多功能集成的严苛要求。本文聚焦于TI Sitara AM571x这款典型的“全集成混合处理器”,它集成了Arm Cortex-A15、C66x DSP、Cortex-M4 IPU及可编

weixin_34072458的博客 414

C6678多核DSP实战:共享内存IPC配置全流程详解(附完整代码)

本文详细解析了C6678多核DSP中共享内存IPC的配置全流程。通过实战视角,从共享内存模型理解、工程环境搭建、配置文件编写,到发送方与接收方的完整代码实现,系统阐述了如何配置多核间的低延迟、高带宽通信,并提供了关键的调试技巧与常见问题排查方法,助力开发者高效解决核间通信难题。

a0b1c2d3的专栏 330

深入解析OMAP-L138异构多核架构:内存映射与双核通信实战

在嵌入式系统开发中,异构多核架构通过集成不同特长的处理器核心(如通用CPU与专用DSP)来提升系统性能与能效。其核心原理在于合理的任务划分与高效协同,而实现协同的关键基础技术之一是内存映射——它定义了系统中各主控单元对物理存储资源的访问规则与权限。这项技术的工程价值在于确保多核间数据交换的安全性、实时性与一致性,是构建稳定可靠嵌入式系统的基石。典型应用场景包括音视频处理、通信基站和工业控制等对实时计算要求高的领域。本文聚焦于德州仪器OMAP-L138平台,深入探讨其ARM与DSP的异构设计,并详细解析其内存

weixin_34160277的博客 428

CCS3.3迁移到CCS10:嵌入式开发范式跃迁实战指南

嵌入式开发中,IDE迁移不仅是工具更换,更是底层构建体系、硬件抽象机制与调试范式的系统性升级。从传统裸机寄存器操作到标准化外设驱动库(PDK),从手工Makefile到CMake自动化构建,从JTAG单步调试到全栈Trace分析,本质是向可移植、可验证、可扩展的现代嵌入式工程实践演进。尤其在TI C6000系列和AMx平台开发中,printf重定向、中断向量管理、HAL封装等关键环节直接决定迁移成败。本文聚焦CCS3.3到CCS10的真实迁移路径,覆盖编译器差异、RTOS集成、多核同步及真机验证等核心挑战,

weixin_33812433的博客 312

IPC的MessageQ与Notify例程

IPC官方例程,包换MessageQ与Notify例程,已调试成功。

(多核DSP快速入门)8、利用MessageQ模块的多核灰度转换程序

原创文章 转载请注册来源http://blog.youkuaiyun.com/tostq        第3节我们介绍了一个单核的图像灰度转换程序,这一节我们将这个单核的图像灰度转换程序改成多核程序。        这个多核程序的主要原理非常简单,将整张图片分块,每一块的处理对应一核,这里需要涉及的是IPC的三个模块:        (1)SharedRegion模块:通过SharedRegi

tostq的专栏 1万+

Windows 10/11 下用 Docker 一键部署 CVAT 标注工具(附 WSL2 配置指南)

本文详细指导如何在Windows 10/11系统上,通过配置WSL2和Docker Desktop,实现CVAT标注工具的一键部署。内容涵盖从环境准备、Docker安装、CVAT服务启动到性能优化与安全配置的全流程,为计算机视觉开发者提供稳定高效的本地标注平台解决方案。

weixin_28839601的博客 462

Word毕业论文排版:图片和表格题注的终极指南(含自动编号技巧)

本文是Word毕业论文排版中图片和表格题注的终极指南,详细讲解了如何利用题注功能实现自动编号,告别繁琐易错的手动操作。核心内容包括创建定制标签、配置带章节的编号格式、插入交叉引用以及一键更新全文编号的技巧,旨在帮助学生构建自动化文档体系,提升排版效率和论文严谨性。

weixin_29211309的博客 1094

IPC用户指南/MessageQ模块的使用

IPC Users Guide/MessageQ Module MessageQ API Reference: http://downloads.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/ipc/latest/docs/doxygen/html/_message_q_8h.html Contents  [h

waterhawk的专栏 6475

Windows防火墙服务异常修复指南:0x80070422与0x6D9报错实战处理

本文针对Windows防火墙服务异常导致的0x80070422与0x6D9报错,提供了从基础到进阶的实战修复指南。核心是通过services.msc服务管理器检查并修复Windows Firewall服务,包括设置启动类型、检查依赖服务等关键步骤。同时介绍了当基础方法失效时,如何使用命令行工具、系统文件检查器(SFC/DISM)以及排查组策略与第三方软件冲突等深度解决方案,帮助用户彻底解决防火墙服务无法启动或访问的问题。

m9n0o的博客 542

核间通信(IPC)的两种解决方案

共享内存在核间通信方案中,一个核可以将数据写入共享内存,Mailbox可以将内存指针传递到另一个核上,另一个核可以拿到内存指针后,直接从Share Memory读取数据,这一个过程不需要经过数据的拷贝,因此,非常高效,适合大数据量的传输。同时,同一种类型的多个核心又可以运行在不同的模式,比如A72可以运行的SMP模式,双核R5F可以运行在Lockstep或Split Mode上,因此,核间通信方案要充分利用硬件提供的机制,实现高效的核间通信,从而充分发挥Soc的整体性能。这就是Mailbox的工作方式。

lyd0813的博客 2万+

PostGIS 小白入门详细指南

PostGIS 是 PostgreSQL 的一个扩展,它将 PostgreSQL 转变为一个功能强大的空间数据库,使其能够存储、查询和分析地理空间数据。PostGIS 遵循开放地理空间联盟(OGC)的标准,支持各种空间数据类型和操作,如点、线、多边形、缓冲区、空间连接等。存储各种空间数据类型(如几何类型和地理类型)空间索引,提高查询性能丰富的空间函数和操作支持投影和坐标系统转换城市规划与管理环境监测与分析物流与运输优化地图制作与可视化位置服务与导航。

落魄书生的职业学习生涯 1万+

八戒留档之宝塔部署edusoho

1.安装好基础的服务 2.上传你下载的代码到www/wwwroot文件3、配置网站 4.编辑创建的网站修改nginx文件 NGINX配置如下 server { listen 80; server_name 你的域名; root /www/wwwroot/项目文件名称/web/; location / { try_files $uri /app_dev.php$is_args$args; } ...

wolf23151269的博客 2540
上一篇: DSP库互相关算法实现与MATLAB互相关算法比较
下一篇: 麦克风阵列声源定位四通道麦克风数据库及TDOA双曲交汇定位算法实验
SlaveOpen
博客等级 码龄5年 3607粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值