中间层驱动工作原理

《VxWorks设备驱动开发详解》笔记——第六章 字符设备驱动+第七章 串口驱动 第六章 字符设备驱动 1.字符设备以字节流的方式对数据进行操作,数据只能顺序读写。I2C、SPI、UART等接口类型的设备都可以作为字符设备进行驱动; 2.对于UART设备,建议使用TTY中间层作为缓冲,以提高设备使用率; 3.SPI的4根信号线:数据输出线SDOUT、数据输入线SDIN、片选SCS、时钟SCK。SPI是一种全双工的通信工作模式; 4.底层驱动只能提供一种机制,策略需要由用户自己选择。 第七章 串口驱动 1.串口是一种常用的、典型的字符设备。因其常用,所以VxWorks在IO子系 阅读详情
 作者:noble <noble _shi @21cn.com>
出处:http://www.nsfocus.com
日期:2005-01-06

本文如有错误,请联系作者,谢谢。

(1)注册表常识:
1)、设备数据库所在的注册表健值为:
    HKLM/SYSTEM/CurrentControlSet/Enum/
    ENUM子项中是一个设备数据库,在数据库存放计算机中所有安装的,并且被系统认识到的设备。
    所有的用户(包括管理员)都不能更改ENUM项的内容。这是为了保护操作系统和安装的设备的完整性。为了更改设备的设置,应该使用"设备管理器"。
    为了在设备管理器中现实隐藏的,非即插即用的,以及没有连接到计算机上的所有设备,你应该首先在命令解释器中敲入命令set DEVMGR_SHOW_NONPRESENT_DEVICES=1,然后启动设备管理器,就可以在设备管理器中删除和重新配置这些设备了。

2)、硬件设备类所在的注册表健值为:
    HKLM/SYSTEM/CurrentControlSet/Control/Class/
    Class项下存放硬件设备类的配置信息。在Class项下的每个子项都代表一个设备类,子项的名称使用"唯一全局标识符(GUIS)",这些标识符存放该设备类的配置信息。在每个类标识符下,还会有以4位数命名的子项,他们代表该设备类里的具体设备,其他的配置数据只应用于该具体设备。
    如网卡的设备类是{4D36E972-E325-11CE-BFC1-08002BE10318},并假定我们网卡对应的4为数命名子项名为0005。
    其中
HKLM/SYSTEM/CurrentControlSet/Class/{4D36E972-E325-11CE-BFC1-08002BE10318}/0005/Linkage/ 中:
Export:代表该设备在设备名字空间输出的设备名字。
RootDevice:代表当前设备的GUID。中间层驱动这里有两个GUID,第一个是自己的GUID,第二个是该中间层驱动绑定的下层MINIPORT的GUID。
UpperBind:代表上层绑定它的NDIS协议驱动或NDIS中间层驱动。当某个协议驱动绑定该MINIPORT设备时,则这个协议驱动的名字必须出现在UpperBind健值的字符串中,否则不能进行绑定。也就是说,UpperBind健值的字符串决定了那个协议驱动(当然也包括中间层驱动注册的协议)和当前的MINIPORT设备绑定,即,它决定了NDIS的上下层绑定关系。

注:一般添加中间层驱动后,中间层驱动只插入到真是网卡和相应协议中间,不会插入到虚拟网卡(如安装虚拟机后虚拟出来的网卡设备)和相应协议中间。

3)、驱动程序所在的注册表健值为:
    HKLM/SYSTEM/CurrentControlSet/Services
ENUM子项
    通常如果某个服务下存在ENUM子项,表明该服务是用来控制某个设备或者设备交互的,它的下面存放该设备的实例。用户不要去试图修改该子项的内容,因为每次系统启动时,都会重写该子项的内容。
LINKAGE子项
     值项Bind
        存放该协议所在绑定栈的最低层小端口设备实例(即MINIPORT)。
     值项Export
        存放该服务必须访问的对象,该对象必须已经安装在系统中,并且该服务能够使用。
     值项Route
        指定子项Linkage从那里获取绑定数据。
Parameters/ Adapters/子项
    这里,我们只解释中间层驱动中该子项的意义。为此,我们假设当前我们讨论的HKLM/SYSTEM/CurrentControlSet/Services/XXXX中的XXXX为中间层驱动。
    对于中间层驱动,该子项下含有一个子项,是以我们当前中间层驱动绑定的下层MINIPORT设备的GUID命名的,在我的系统中,健值如下:
{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}
在{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项有个健,名称为UpperBindings,该健的健值是当前中间层驱动的MINIPORT设备名称,在我的系统中为如下健值:
/Device/ {5BF5A311-13E4-4746-8865-339DDD6C73AF}

(2)中间层驱动
在我们的函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()中,会调用一系列函数(如NdisOpenProtocolConfiguration、NdisReadConfiguration)来访问注册表,其实都是访问Parameters/Adapters/{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项。
    注意,函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()的倒数第二个参数是SystemSpecific1,如果我们安装的是XPASSTHRU,则其具体指的是如下字符串:
    xfilter/Parameters/Adapters/{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}
    其中xfilter 是XPASSTHRU的,而{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同。
    函数NdisOpenProtocolConfiguration()其实只是构造一个查询注册表的RTL_QUERY
_REGISTRY_TABLE结构(该结构在利用函数RtlQueryRegistryValues()查询注册表是使用)。并将这个结构封装到NDIS_WRAPPER_CONFIGURATION_HANDLE结构中,然后作为NdisOpenProtocolConfiguration()的第二个参数返回。
    其实NdisOpenProtocolConfiguration()构造的RTL_QUERY_REGISTRY_TABLE结构的含义也就是查询HKLM/SYSTEM/CurrentControlSet/Services/ xfilter/Parameters/Adapters/{
102454C2-9DB3-42A1-B4CF-6A8B67A516C0}/下的健值(xfilter 会随着安装不同的中间层驱动而不同,{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同,下面均省略这些注释)。
    函数NdisReadConfiguration()有两个作用,它首先修改在函数NdisOpenProtocolConf
iguration()构造的RTL_QUERY_REGISTRY_TABLE结构。也就是在查询HKLM/SYSTEM
/CurrentControlSet/Services/ xfilter/Parameters/Adapters/{102454C2-9DB3-42A1-B4CF-6A8B6
7A516C0}/的基础上加上了一个健,将其变成HKLM/SYSTEM/CurrentControlSet/Services/ xfilter/Parameters/Adapters/{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}/UpperBindings。然后函数NdisReadConfiguration()会调用函数RtlQueryRegistryValues()查询新构造的这个注册表,并将结果存储在调用函数NdisReadConfiguration()时的第二个参数中。在我的系统中,RtlQueryRegistryValues()读出的这个新构造的这个注册表的健值是:/Device/ {5BF5A311-13E4-4746-8865-339DDD6C73AF}(后面我们称为RESULT1),它其实是我们注册的中间层驱动(XPASSTHRU)的设备输出(其构造是/Device+/GUID)。
    其实我们读出的这个中间层驱动(XPASSTHRU)的设备(即我们刚才读出的那个健值RESULT1)只在后面的函数NdisIMInitializeDeviceInstanceEx()中才用得着,并且RESULT1是作为函数NdisIMInitializeDeviceInstanceEx()的第二个参数的。
这里有个地方让人感到迷惑,即在函数BindAdapterHandler()我们一旦调用了函数NdisOpenAdapter()绑定了一个下层的MINIPORT,为什么还要调用函数NdisIMInitializeDeviceInstanceEx()初始化我们中间层驱动自己的MINIPORT(因为函数NdisIMInitializeDeviceInstanceEx()的参数是RESULT1,而RESULT1代表我们中间层驱动的MINIPORT)。为了解释这个原因,我们先做如下假设。



我们假设我们系统安装了一个中间层驱动(假设为XPASSTRHU),在上图中,PROT-IM和MINIPORT-IM分别代表我们中间层驱动的协议驱动程序和小端口驱动程序,PROT-TCPIP代表真正的协议驱动程序,MINIPORT-NIC代表真是网卡的小端口驱动程序。
    当PROT-TCPIP需要发送数据时,会调用函数NdisSend(),其实它会调用MINIPORT-IM中的发送数据函数,但是MINIPORT-IM和MINIPORT-NIC没联系,按照常规是不能发送数据到MINIPORT-NIC的。但是我们可以看到PROT-IM是可以和MINIPORT-NIC互相发送数据的,所以我们必须将MINIPORT-IM和PROT-IM联系起来。
    另外当MINIPORT-NIC需要将数据提交给PROT-TCPIP时,只能首先将数据提交给PROT-IM,PROT-IM也只能通过MINIPORT-IM才能和PROT-TCPIP联系起来。
    所以必须将PROT-IM和MINIPORT-IM联系起来。有人说这两个东西都是我们中间层驱动注册得,难道还联系不起来吗?不错,但是不管怎样你都得通过你得代码才能将他们联系起来呀!下面我们就介绍联系得方法。
    我们以XPASSTHRU为例,在其函数ProtocolBindAdapter()中,先分配了一个ADAPT结构(这个结构是自己定义的,可根据用户的需要定义)。当调用函数ProtocolBindAdapter()调用函数NdisOpenAdapter()进行绑定时,是以&Adapt->BindingHandle作为函数NdisOpenAdapter()的第三个参数的,这样Adapt->BindingHandle就指向了NDIS_OPEN_BLOCK1(注意,调用函数NdisOpenAdapter()时的第三个参数会返回指向绑定以后的NDIS_OPEN_BLOCK指针)。然后函数ProtocolBindAdapter()会调用函数NdisIMInitializeDeviceInstanceEx(),该函数会进一步调用XPASSTHRU的NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数。上面我们讨论过,NdisIMInitializeDeviceInstanceEx()中的第二个参数就是XPASSTHRU注册的小端口驱动的设备实例(即上面的RESULT1)。在函数NdisIMInitializeDeviceInstanceEx()中会根据设备名称(RESULT1),找到对应的MINIPORT结构,并将其指针作为参数传递给NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数(以后简称InitializeHandler()函数)。在InitializeHandler()函数中,会进一步将MINIPORT结构指针赋值给ADAPT->MiniportHandle(ADAPT就是上面在函数ProtocolBindAdapter()中分配的那个结构)。
    这样数据结构ADAPT中就含有了两个指针,一个指向NDIS_OPEN_BLOCK1,另一个指向MINIPORT-IM,而NDIS_OPEN_BLOCK1和PROT-IM是密切联系的,所以ADAPT就将PROT-IM和MINIPORT-IM紧密的联系起来了。
    另外注意,NDIS_MINIPORT_BLOCK->DeviceContext是指向我们的ADAPT结构的,这个赋值在函数NdisIMInitializeDeviceInstanceEx()中完成。上面谈到了也是在函数NdisIMInitializeDeviceInstanceEx()中完成了从ADAPT-> MiniportHandle到MINIPORT的绑定,所以在函数NdisIMInitializeDeviceInstanceEx()中完成了ADAPT和MINIPORT的互相连接(即指针互相指向)。
函数InitializeHandler()中可以利用句柄MINIPORT的句柄得到我们的ADAPT结构,具体实现这个功能的函数是NdisIMGetDeviceContext(),这个函数的参数是个NDIS_HANDLE类型,但是在该函数内部,会将这个参数转换成NDIS_MINIPORT_BLOCK结构,并返回NDIS_MINIPORT_BLOCK->DeviceContext。
在函数NdisOpenAdapter()中,除了上面提到的完成了由Adapt->BindingHandle到NDIS_OPEN_BLOCK1的指向外,还完成了我们没有提到的由NDIS_OPEN_BLOCK1-> ProtocolBindingContext到ADAPT的指向,所以函数NdisOpenAdapter()完成了ADAPT和NDIS_OPEN_BLOCK1的互相连接(即指针互相指向)。
    讲到这里,我们上图完善为下图:



    下面大家也许就可以做一些HOOK了,例如对OPEN_BLOCK结构的HOOK,对ADAPT的HOOK等,这里就不作介绍了,呵呵。
NDIS驱动开发实战指南:从基础到中间层驱动程序 网络驱动程序接口规范(NDIS)是微软和3Com公司共同开发的一种标准API集合。它的目的是为网络适配器的驱动程序提供一个统一的接口,以便在不同的网络硬件和上层协议之间提供一致的通信方式。NDIS简化了网络驱动程序的开发,并支持即插即用设备,使得网络适配器可以轻松地被操作系统所识别和配置。微型端口驱动程序(Miniport Driver)是在网络适配器驱动程序层次中最低层的组件。它主要负责与硬件通信,执行数据的接收和发送操作。 阅读详情

相关推荐

中间层驱动程序详解(带源码)

详细讲解了中间层驱动程序的结构和应用,并带有源码演示。实用性强

内核模式下的注册表操作

VOID RegTest() { WCHAR* pKey=L"\\Registry\\Machine\\SOFTWARE\\Yjz"; // 查找项 if (!NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE,pKey))) { KdPrint(("注册表项不存在\r\n")); // 创建项 if (NT_SUCCESS

yjz1409276的专栏 4377

自动驾驶中的多传感器融合实战:用卡尔曼滤波搞定毫米波雷达与摄像头航迹对齐

本文深入探讨了自动驾驶中多传感器融合的实战技术,重点介绍了如何使用卡尔曼滤波实现毫米波雷达与摄像头的航迹对齐。通过分析传感器特性差异、时空同步挑战及工程化实现步骤,提供了包括状态向量定义、观测矩阵设计和故障检测机制在内的完整解决方案,最终实现0.15米以内的高精度航迹对齐。

weixin_28728495的博客 411

(转载)中间层驱动工作原理

中间层驱动工作原理转自:http://www.nsfocus.net/作者:noble 出处:http://www.nsfocus.com日期:2005-01-06本文如有错误,请联系作者,谢谢。(1)注册表常识:1)、设备数据库所在的注册表健值为:    HKLM/SYSTEM/CurrentControlSet/Enum/    ENUM子项中是一个设备数据库,在数据库存放计算机中所有安装的,

Kendiv's Box 2851

从零理解域随机化:通过Isaac Lab的events.py掌握Sim-to-Real关键技术

本文深入解析域随机化技术如何通过Isaac Lab的events.py实现Sim-to-Real迁移,提升机器人策略在真实世界的鲁棒性。从刚体属性到环境条件的系统级随机化,详细介绍了工程实践中的关键参数配置与调试技巧,帮助开发者有效缩小仿真与现实的差距。

weixin_29062613的博客 261

Unity游戏接入穿山甲广告SDK全攻略:从零到上线的避坑指南

本文为Unity开发者提供了接入穿山甲广告SDK的完整实战指南。详细解析了从账号注册、应用创建到Unity插件集成、安卓与iOS平台打包配置的全流程,并重点分享了广告加载失败、展示异常等常见问题的排查与解决方案,帮助开发者高效实现游戏广告变现。

weixin_29015899的博客 536

六、 在驱动中操作注册表

六、 在驱动中操作注册表 注册表是Windows的核心,日常的许多操作其实最终都是转化成了对注册表的操作,我们经常需要利用注册表达到一些特殊的效果,例如实现自启动等。 Windows 下设备驱动程序的开发方法 2120080411 计算机应用 赖锡盛 19 6.1 创建、打开注册表 和文件操作类似,在操作注册表之前需要首先打开注册表,获得一个句柄,这可以通过函数ZwCreateKey完

autumn20080101的专栏 2165

AWR射频仿真基本操作(一)

这里只讲述一个基本的操作: 软件是AWR 14版本

钢丝 2万+

0、系统架构设计

1.系统架构 系统划分为三层,即业务层(应用层),中间件层和驱动层. 应用层:专注于业务逻辑功能实现. 中间层:为应用层服务,为应用层提供相关服务接口,也具有少量的业务逻辑. 驱动层:提供硬件底层驱动程序. 架构框图 分层思想优点: (1).最大程度隐藏驱动代码,保护了代码的安全性。 (2).接口统一,方便应用层开发。 (3).方便代码管理,同步开发。 2.接口标准化 标准接口分为三部分:驱动层接口、中间件统一接口、应用层接口 驱动接口:由官方提供的统一接口,操作芯片相关寄存器实现某一功.

beArobot的博客 3288

项目管理-(补充)七种基本质量工具

七种基本质量工具,用于PDCA循环的架构内 解决与质量相关的问题,分为老七工具和新七工具。 1)老七种:刘英只点劣质茶(流程图、因果图、直方图、散点图、帕累托图、控制图、核查表)2)新七种:锯树联亲测动优(矩阵图、树形图、关联图、亲和图、过程决策程序图、活动网络图、优先矩阵)

weixin_42081167的博客 4604

300Kg载重履带式无人车底盘定制开发技术详解

通过精准的需求分析、科学的方案设计、严格的研发与测试以及完善的交付与培训流程,可以打造出符合客户需求的优质产品。300Kg载重履带式无人车底盘的定制开发,旨在打造一款承载能力强、行驶稳定、适应复杂地形的无人运输平台。根据应用场景选择合适的动力源,并进行性能优化,确保无人车在载重情况下仍能保持稳定的行驶速度和动力输出。根据需求分析结果,设计无人车底盘的总体方案,包括动力系统选择、结构设计、负载管理策略等。进行详细的研发工作,包括零部件的选型与采购、样机的制作与调试等。

专注多旋翼、复合翼无人机技术研究,从事低空经济行业。 960

驱动开发之访问注册表

访问注册表 Windows NT和Windows 98把配置信息和其它重要信息都记录到注册表(registry)中。WDM驱动程序可以使用表3-9列出的函数访问注册表。如果你在用户模式编程中曾涉及过注册表访问,你可能会猜出如何在驱动程序中使用这些函数。然而这些内核模式中的支持函数确有些不同,我想有必要描述一下它们的用法。 表3-9. 注册表访问函数 服务函数 描述  IoOpenDev

Lydia的博客 2697

VBOX 3iS实战:如何用GNSS+IMU搞定车辆动态坡度测量(附避坑指南)

本文详细介绍了VBOX 3iS在车辆动态坡度测量中的高阶应用,通过GNSS+IMU融合技术和卡尔曼滤波算法,有效解决了传统测量方法在动态环境中的局限性。文章提供了设备配置、实战策略和数据后处理的实用指南,帮助工程师提升测量精度和效率。

weixin_42520796的博客 322

中间层

中间层中科永联高级技术培训中心(www.itisedu.com)      中间层 (Middle Tier)也称作“应用程序服务器层或应用服务层”,是用户接口或 Web 客户端与数据库之间的逻辑层。典型情况下 Web 服务器位于该层,业务对象在此实例化。中间层是生成并操作接收信息的业务规则和函数的集合。它们通过业务规则(可以频繁更改)完成该任务,并由此被封装到在物理上与应用程

赢在执行 971

信贷风控实战指南:Vintage分析表从数据建模到风险洞察

本文是一份信贷风控实战指南,详细阐述了Vintage分析从数据建模到风险洞察的全流程。文章深入解析了Vintage分析作为信贷资产“体检报告”的核心价值,并提供了从借据表与还款计划表设计、账龄计算、逾期口径判定到风险暴露计算与最终可视化透视的完整SQL实现方案,旨在帮助风控从业者构建精准的风险监控体系。

nft7creator的博客 321

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

转发三层结构之中间层

中间层中科永联高级技术培训中心(www.itisedu.com)      中间层 (Middle Tier)也称作“应用程序服务器层或应用服务层”,是用户接口或 Web 客户端与数据库之间的逻辑层。典型情况下 Web 服务器位于该层,业务对象在此实例化。中间层是生成并操作接收信息的业务规则和函数的集合。它们通过业务规则(可以频繁更改)完成该任务,并由此被封装到在物理上与应用程

zlb01的专栏 1414

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

中间层驱动学习笔记《寒江》

 NDIS驱动对上次协议驱动来说像是一个小端口驱动,但是对小端口驱动来说又像是一个协议驱动,所以在中间层驱动中是不停的从小端口驱动跳到协议驱动中去,有点复杂  一个协议驱动,是可以接受本机接受到的所有包的,但是不能拦截。这个是和中间层驱动的一个很大的差别。 首先介绍的是NDIS包描述符的一些结构/**The NDIS_PACKET structure defines

爱杀之爪的矩阵 1675

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

【转帖】NAT在NDIS中间层驱动中的实现

 1.概要     相信在IPv6的时代到来之前,NAT仍然是解决大多数人上网的主要途径,而且它在企业内网Intranet中也扮演着十分重要的角色.     NAT的全称是Network Address Translator(网络地址转换),其主要作用是把内网IP地址转换成为全球唯一的可定位的外部IP地址,从而使得局域网内的所有用户可以通过一个或者少数几个IP地址与全球的Internet通信,不仅

floweronwarmbed的专栏 1028

寒江独钓NDIS驱动学习总结

第一部分:NDIS协议驱动 协议驱动框架上层与应用层交互,下层与小端口驱动绑定(可能有中间层),主要功能是处理应用层请求发包和接收以太网包的作用。 1.协议驱动DriverEntry编写步骤: (1)定义需要用到的变量 (2)生成控制设备:针对不同操作系统调用IoCreateDeviceSecure或IoCreateDevice函数; 生成该设备的符号链接:为了应用层调用该设备对象备用,通过IoCreateSymbolicLink这个API调用; 设置控制设备对象的Flags:主要是设置其为直接

苞米地里捉小鸡的博客 1461

Gsensor的整个系统架构

Email:wei7758@126.com Blog:http://blog.youkuaiyun.com/yinwei520 Author: Yww Time:2011-8-22 一、首先建立这样一个全局的观念:     Android中sensor在Android系统架构中的位置及其工作。方框图如下: 从以上方框图中,可以看出Android中sensor在系统分为四层:驱动层(Sensor D

冰水寒SG的专栏 786

TDI, NDIS 驱动的学习

最近,因为项目的需要,想加入防火墙的功能模块,故开始了对这方面知识的学习。。。。<img style="margin: 2px;" title="名称: AFD.jpg查看次数: 271文件大小: 14.4 KB" src="mhtml:file://C:/Documents and Settings/Administrator/桌面/技术专题 【原创】Windows网络体系结构总

xum2008的专栏 1117

内核模式驱动程序的网络结构

转载请标明是引用于 http://blog.youkuaiyun.com/chenyujing1234  欢迎大家拍砖!   1、Windows 2000 网络结构和OSI模型   Windows 2000网络结构是以国际标准化组织(ISO)制定的七层网络模型为基础的,1978年,ISO制定的开放式系统(OSI)参考模型,将网络描述为一系列的协议层,在每个协议层中完成一系列的特定功能。每一层都向上一

bobopeng 683

SCSI工作原理

SCSI 工作原理 SCSI 实现了一种客户机/服务器风格的通信架构。发起者向目标设备发送命令请求。该目标处理此请求并向发起者返回响应。发起者可以是托管计算机中的一个 SCSI 设备,而 SCSI 目标则可以是一个磁盘、光盘和磁带设备或特殊设备(比如箱体设备)。 回页首 SCSI 命令 SCSI 传输所采用的协议已经时过境迁,SCSI 命令却保持了最初的元素。SCS

raindaysps的专栏 5884
上一篇: 粗糙的Ring0弹Box代码
下一篇: 如何使用 WinInet 提供下载 / 限上载进度信息
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值