内存管理:虚拟存储

内存管理——虚拟存储器

虚拟存储器概述

image-20230405203553120

image-20230403220355274

在《内存管理:存储器管理》中介绍的几种存储器管理的方式有一个共同的特点,就是它们都要求将一个将一个作业的全部装入内存中方能运行(多级页表是将部分页表放在磁盘)。于是会出现两种情况:

  1. 有的作业很大,其所要求的内存空间超过了内存总容量,作业不能全部都装入内存,致该作业无法运行
  2. 有大量作业要求运行,但是受内存大小限制,只能将少数作业装入内存让它们先运行

常规存储管理方式的特征和局部性原理

1.常规存储管理方式的特征

传统存储器管理的方式是指《内存管理:存储器管理》中所讲的,它们有以下几个特征

  1. 一次性:指作业必须一次性装入内存后才可以正常运行。
  2. 驻留性:指作业被装入内存后,整个作业都一直驻留在内存中,其中任何部分都不会被换出,直至作业运行结束

2.局部性原理

程序在执行时将呈现出局部性性规律,即在一较短时间内,程序的执行仅局限于某个部分,相应地,它所访问的存储空间也局限于某个区域:

  1. 程序执行时,除少部分的转移和过程调用之另外,在大多数情况下是顺序执行
  2. 过程调用将会使程序的执行轨迹由一部分区域转至另一部分区域
  3. 程序中存在许多循环结构,这些结构虽然只由少数指令构成,但是它们将被多次执行
  4. 程序中包含的许多对数据结构的处理,如对数组进行操作,这些处理往往都局限于很小的范围内

可以将上述的几点归纳为下面两点

  • 时间局部性

如果程序中的某条指令被执行,则不久之后该指令可能再次执行;如果某数据被访问过后,则不久以后该数据可能再次被访问。产生时间局限性的典型原因是在程序中存在着大量的循环操作

  • 空间局部性

一旦程序访问了某个单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址可能集中在一定的范围内,典型的情况是程序的顺序执行

3.虚拟存储器的基本工作情况

根据局部性原理可知,应用程序在运行之前没有必要将之全部装入内存,而仅将那些当前要运行的少数页面或段先装入内存,其余部分暂留在盘上。

程序在运行时,如果它所要访问的页(段)已调入内存,便可继续执行下去;

如果程序所要访问的页(段)尚未调入内存(成为缺页或缺段,便发出缺页(段)中断请求,此时利用OS将利用请求调页(段)功能将它们调入内存,以使程序能继续执行下去;

若此时内存已满,无法再装入新的页(段),OS还要利用页(段)置换功能,将内存中暂时不用的页(段)调至盘上,腾出足够的空间后,再将要访问的页(段)调入内存,使程序能继续执行下去

虚拟存储的定义和特征

1.虚拟存储器的定义

虚拟存储器是指具有调入功能和置换功能,能从逻辑上对内存容量加一扩充的一种存储系统。其逻辑容量由内存容量和外存容量之和所决定,其运行速度接近于内存速度,而每位的成本接近于外存

2.虚拟存储器的特征

  • 多次性。多次性是指一个作业中的程序和数据无需在作业运行时一次性全部转入内存,而是被允许被分成多次调入内存运行

  • 对换性💱。是指一个作业中的程序和数据,无须在作业运行时一直常驻内存,而是允许在作业的运行过程中进行换进、换出。正是对换性才使虚拟存储器得以正常运行

  • 虚拟性。是指能从逻辑上扩充内存容量,使用户所看到的内存容量远大于实际内存容量。不仅能有效地改善内存的利用率,还可以提高程序执行的并发速度,从而可以增加系统的吞吐量

虚拟性是以多次性和对换性为基础的;多次性和对换性必须建立在离散分配的基础上

虚拟存储器的实现方法

在虚拟存储器中,允许将一个作业分多次调入内存。如果采用连续分配的方式,要求必须将作业装入一个连续的内存空间中,则必须事先未作业一次性地申请一个足以容纳整个作业的内存空间,以便能将该作业分先后地多次装入内存。所以,虚拟存储器的实现,都毫不例外地建立在离散分配存储管理方式的基础上

1.分页请求系统

分页请求系统是在分页系统上增加了请求调页功能页面置换功能所形成的页式虚拟存储系统。为实现请求调页功能和页面置换功能,系统必须提供必要的硬件支持和请求分页的软件

1)硬件支持

  1. 请求分页的页表机制。它是在纯分页的页表机制上增加若干项而形成的,作为请求分页的数据结构。
  2. 缺页中断机构。当用户要访问的页面尚未调入内存时,便产生一缺页中断,以请求OS将所缺的页调入内存
  3. 地址变换机构。在纯分页地址变换机构的基础上发展出来的

2.实现请求分页的软件

包括用于实现请求分页的软件和实现页面置换的软件。它们在硬件的支持下,将程序正在运行时所需的页面调入内存,再将内存中暂时不用的页面从内存置换到的磁盘上

2.请求分段系统

请求分段系统是在分段系统的基础上,增加了请求调段及分段置换功能后所形成的段式虚拟存储系统。它允许用户程序只要装入少数段的程序和数据即可启动运行。

1)硬件支持

  1. 请求分段的段表机制。它是在纯分段表机制上增加若干表项而形成的,作为请求分段的数据结构
  2. 缺段中断机构。当用户程序要访问的段尚未调入内存时,便产生缺段中断,以请求OS将所缺的段调入内存
  3. 地址变换机构。是在纯分段地址变换机构的基础上发展形成的

2.软件支持

这里包括有用于实现请求掉段的软件和实现段置换的软件。它们在硬件的支持下,先将内存中暂时不用的段从内存置换到磁盘上,再将程序正在运行时所需的段调入内存。请求分段系统的换进换出的基本单位是段,其长度可变,分段的分配类似于动态分区方式,它在实现分配和回收上都比较复杂。

目前,有不少虚拟存储器是建立在段页式系统基础上的,通过增加请求调页和页面置换功能形成了段页式虚拟存储器系统。

请求分页存储管理方式

请求分页存储器与基本分页存储管理的主要区别:

在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存(由操作系统提供请求调页的功能),然后继续执行程序

若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存(操作系统提供页面置换的功能,将暂时用不到的页面换出外存)。

请求分页中的硬件支持

image-20230404171147118

1.请求页表机制

请求分页系统中需要的主要数据结构是请求页表,其基本作用是将用户地址空间中的逻辑地址映射为内存空间中的物理地址。为了满足请求分页换进换出的需要,在请求页表中又增加了四个字段。

image-20230404151251984

各字段说明:

  • 状态位(存在位)P🎏:该字段只有一位,用于指示该页是否已经调入内存,供程序访问时参考。
  • 访问字段A:用于记录本页在一段时间内被访问的次数,或是记录本页最近已有多长时间未被访问,提供给置换算法(程序)在选择换出页面时参考
  • 修改位M:标识该页在调入内存后是否被修改过。由于内存中的每页躲在外存上保留一份副本,因此,在置换该页时,若未被修改,就不需要将该页写回到外存上,以保证外存中所保留的副本始终都是最新的
  • 外存地址🏠:用于指出该页在外存上的地址,通常是物理块号,供调入该页时参考
2.缺页中断机构

image-20230404162556828

在请求分页系统中,每当所要访问的页面不在内存时,便产生缺页中断,请求OS将所缺之页调入内存。缺页中断是一种特殊的中断,它与一般的中断相比有着明显的区别,主要体现在:

  1. 在指令执行期间产生和处理中断信号。通常CPU都是在一条指令执行完后,才检查是否有中断请求到达。若有便去访问,否则,继续执行下一条。然而,缺页中断是在指令执行期间,若发现索要访问的指令或数据不在内存时,便立即产生和处理缺页中断信号,以便能及时将所缺页面调入内存
  2. 一条指令在执行期间可能产生多次缺页中断,系统中的硬件机构能保存多次中断的状态,并保证最后能返回到中断前产生缺页中断的指令继续执行。(如copy A to B,可能要发生6次缺页中断)

缺页中断属于内部中断中的故障(fault),可能被故障处理程序修复

3.地址变换机构

请求分页存储管理与基本分页存储管理的主要区别:

在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存(操作系统提供请求调页功能,将缺失页面从外存调入内存),然后继续执行程序

若内存空间不够。由操作系统负责将内存中暂时用不到的信息换出到外存(OS提供页面置换功能,将暂时用不到的页面换出内存)

新增步骤1:请求调页(查到页表项时进行判断)

新增步骤2:页面置换(需要调入页面,但没有空闲内存块时进行)

新增步骤3:需要修改请求页表中新增的表项

image-20230404163211306

上图体现了请求分页系统的一次访问逻辑地址的过程。其中值得注意的是快表中有对应的页面一定是在内存中的。若某个页面被换出外存,则快表中的相应表项也要删除,否则可能访问错误页面。

下图是请求分页中地址变换的过程:

image-20230404164753851

上图中隐含的一些细节:

① 只有“写指令”才需要修改“修改位”。并且,一般来说只需修改快表中的数据,只有将快表项删除时才需要写回内存中的慢表。这样可以减少访存次数。

② 和普通的中断处理一样,缺页中断处理依然需要保留CPU现场

③ 需要某种“页面置换算法”来决定一个换出页面

④ 换入/换出页面都需要启动慢速的I/O操作,可见,如果换入换出操作太频繁,会有很大的开销

⑤ 页面调入内存后,需要修改慢表,同时页需要将其表项复制到快表中。

请求分页中的内存分配

在为进程分配内存时需要考虑三个问题❔:

  1. 为保证进程能正常运行,所需要的最小物理块数的确定
  2. 在为每个进程分配物理块时,应采取什么样的分配策略,即所分配的物理块是固定的还是可变的
  3. 为不同进程所分配的物理块数,是采取平均分配算法,还是根据进程大小按比例分配
1.最小物理块的确定

最小块是指能保证进程运行所需的最小物理块,当系统为进程分配的物理块数小于此值时,进程将无法执行。进程获得的最小物理块数,与计算机的硬件结构有关,取决于指令的格式、功能、和寻址方式。例如对于单地址指令,且采用直接寻址方式,则需要的物理块数为2。

2.内存分配策略

驻留集:指请求分页存储管理中给进程分配的物理块的集合

在采用了虚拟存储技术的系统中,驻留集大小一般小于进程的总大小。若驻留集太小,会导致缺页频繁,就要花大量的时间处理缺页。驻留集太大,又会导致多道程序并发度下降,资源利用率降低。

固定分配:操作系统为每个进程分配一组固定数目的物理块,在进程运行时大小不变

可变分配:先为每个进程分配一定数目的物理块,在进程运行期间,可根据情况做适当的增加或减少,即驻留集大小可变

局部置换:发生缺页时只能选进程自己的物理块进行置换

全局置换:可以将操作系统保留的空闲物理块分配给缺页进程,也可以将别的进程持有的物理块置换

image-20230404222554184

固定和可变是运行时相较于创建时。局部和全局是置换时是否将外部的置换为自己的。

将两种分配策略和两种置换策略进行组合:

  • 固定分配局部置换:系统为每个进程分配一定数量的物理块,在整个运行期间都不改变。若进程在运行中发生缺页,则只能从该进程在内存中的页面中选出一页换出,然后再调入需要的页面。这种策略的缺点是:很难在刚开始就确定应为每个进程分配多少物理块才算合理。(采用这种策略的系统可以根据进程大小、优先级、或者是程序员给出的参数来确定为一个进程分配多少内存)

  • 可变分配全局置换刚开始会为每个进程分配一定数量的物理块。操作系统会保持一个空闲物理块队列。当某个进程发生缺页时,从空闲物理快中取出一块分配给该进程;若已无空闲物理块,则可选择一个未锁定的页面(系统会锁定一些页面,这些页面中的内存不能置换出外存,如重要的内核数据)换出外存,再将物理块分配给缺页进程。采用这种策略,只要某进程发生缺页,都将获得新的物理块,仅当空闲物理块用完时,系统才选择一个未锁定的页面调出。被选择调出的页可能是系统中任何一个进程中的页,因此这个被选中的进程拥有的物理块会减少,缺页率会增加

  • 可变分配局部置换算法:刚开始会为每个进程分配一定数量的物理块。当某进程发生缺页时,只允许从该进程自己的物理块中选出一个进行换出外存。如果进程在运行中频繁缺页,系统会为该进程多分配几个物理块,直至该进程缺页率趋势适当程度;反之,如果进程在缺页率特别低,则可适当减少分配给该进程的物理块

可变分配全局置换:只要缺页就会给分配新物理块

可变分配局部置换:要根据发生缺页的频率来动态地增加进程的物理块

3.物理块分配算法

在采用固定分配策略时,如何将系统中的所有物理块分配给各个进程,可采用以下几种方法:

  1. 平均分配算法 将系统中的可提供的物理块平均地分给各个进程
  2. 按比例分配 根据进程的大小按比例分配物理块
  3. 考虑优先权分配 重要的、紧迫的作业应分到更多的物理块。通常采用的方法是把内存中可供分配的所有物理块分成两部分:一部分按比例分给各个进程;另一部分根据各进程的优先权进行分配,为高优先级的进程适当增加其份额。如实时系统可能是完全按照优先权为各个进程分配物理块的。

页面调入策略

何时调入页面
  1. 预调页策略:根据局部性原理,一次调入若干个相邻的页面可能比一次调入一个页面更高效。但如果提前调入的页面中大多数都没被访问过,则又是低效的。因此可以预测不久之后可能访问到的页面,将它们预先调入内存,但目前预测成功率只有50%左右。故这种策略主要用户进程的首次调入运行前调入
  2. 请求调页策略:进程在运行期间发现缺页时才由OS将所缺的页面调入内存。由这种策略调入的页面一定会被访问到,但由于每次只能调入一页,而每次调页都要磁盘I/O操作,因此I/O开销较大
从何处调入页面

将请求分页系统中的外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。通常,对换区采用连续分配,文件区采用离散分配,对换区的的数据存取速度比文件区高

每当发生缺页的时,系统应从何处将缺页调入内存,可分为如下三种情况:

  1. 系统拥有足够的对换区:页面的调入、调出都是在内存与对换区之间进行,这样可以保证页面的调入、调出速度很快。在进程运行前,需将进程的相关数据从文件区复制到对换区

    image-20230405132840902

  2. 系统缺少足够的对换区:凡是不会被修改的数据都直接从文件区调入,由于这些页面不被修改,因此换出时不必写回磁盘,下次需要使用时再从文件区调入即可。对于可能被修改的部分,换出时需写回磁盘对换区,下次需要时再从对换区调入。

    image-20230405133418037

  3. UNIX方式:运行之间进程有关的数据全部全部放在文件区,故未使用过的页面,都可以从文件区调入。若被未使用过的页面需要换出,则写回对换区,下次需要时从对换区调入。由于UNIX系统允许页面共享,因此某进程所请求的页面可能已被其它进程调入内存。

抖动(颠簸)现象

含义:刚刚换出的页面马上就要换入内存,刚刚换入的页面马上又要换出外存,这种频繁的页面调度行为称为抖动,或颠簸。产生抖动的主要原因是进程频繁访问的页面数量高于可用的物理块数(分配给进程的物理块不够)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pEJASyfp-1680703945040)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%A9%E7%94%A8%E7%8E%87.jpg)]

上图中横轴表示的是多道程序的数量,纵轴对应的是处理机的利用率。可以看到随着进程数量的增加,处理机的利用率急剧增加。但是到达N1点的时候就开始下降。最后随着进程数量的增加处理机的利用率开始趋向于0,这是因为系统中发生了抖动。

为进程分配的物理块太少,会使进程发生抖动现象。为进程分配的物理块太多,又会降低系统整体的并发度,降低某些资源的利用率。为了研究应该为每个进程分配多少个物理块,提出了工作集的概念

下图展示了进程获得的块数和缺页率之间的关系,可以看到缺页率随着分配到到的物理块的数量明显地减少,当物理块数超过某个数目时,再为进程增加一物理块,对缺页率的改善已不明显

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pO7TFq79-1680703945040)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/%E7%BC%BA%E9%A1%B5%E7%8E%87%E4%B8%8E%E7%89%A9%E7%90%86%E5%9D%97%E4%B9%8B%E9%97%B4%E7%9A%84%E5%85%B3%E7%B3%BB.png)]

工作集

驻留集:指请求分页存储管理中给进程分配的内存块的集合

工作集:只在某段时间间隔里,进程实际访问页面的集合

操作系统根据“窗口尺寸”来计算出工作集。例如:

image-20230405142905155

工作集大小可能小于窗口尺寸,实际应用中,操作系统可以统计进程的工作集大小,根据工作集大小给进程分配若干内存块。如:窗口尺寸为5,经过一段时间的监测发现某进程的工作集最大为3,那么说明该进程有很好的局部性,可以给这个进程分配3个及以上的内存块即可满足进程的运行需要。一般来说,驻留集大小不能小于工作集大小,否则进程运行过程中将频繁缺页

拓展:基于局部性原理可知,进程在一段时间内访问的页面的与不久之后会访问的页面是有相关性的。因此,可以根据进程近期访问的页面集合(工作集)来设计一种页面置换算法——选择一个不在工作集中的页面进行淘汰。

小结

image-20230405145350884

页面置换算法

请求分页存储管理与基本分页存储管理的主要区别:

在程序执行过程总,当所访问的信息不再内存时,由操作系统负责将所需信息从外存调入内存,然后是继续执行程序

若内存空间不足,由操作系统负责将内存中暂时不用的信息换出到外存

最佳置换算法(OPT)

最佳置换算法(OPT,Optimal):每次选择淘汰的页面将是以后永不使用,或在最长时间内不在被访问的页面,这样可以保证最低的缺页率,但实际是上,只有进程执行过程中才知道接下来会访问到的是哪个页面。操作系统无法提前预判页面访问序列。因此,最佳置换算法是无法实现的

image-20230405155510681

注意: 缺页时未必发生页面置换,若还有可用的空闲内存块,就不用进行页面置换

先进先出置换算法(FIFO)

先进先出置换算法(FIFO)::每次选择淘汰的页面最早进入内存的页面

实现方法:把内存的页面根据调入的先后顺序排成一个队列,需要换出页面时选择对头页面即可。队列的最大长度取决于系统为进程分配了多少个内存块

Belady异常——当为进程分配的物理块数增大时,缺页次数不减反增的异常现象

只有FIFO算法会产生Belady异常。另外,FIFO算法虽然实现简单,但是该算法与实际运行时的规律不适应,因为先进入的页面也有可能最经常被访问、。因此算法性能差

image-20230405160116080

image-20230405160408519

最近最久未使用置换算法(LRU)

最近最久未使用置换算法(LRU,least recently used):每次淘汰的页面是最近最久未使用的页面。

实现方法:赋予每个页面对应的页表中,用访问字段记录该页面自上次访问以来所经历的时间t。当需要淘汰一个页面的时候,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰。该算法的实现需要专门的硬件支持,虽然算法性能好(最接近OPT算法),但是实现困难,开销大。

image-20230405201410974

时钟置换算法(CLOCK)

时钟置换算法是一种性能和开销较均衡的算法,又称为CLOCK算法,或最近未使用(NRU,Not Recently Used

简单的CLOCK算法实现方法:

为每个页面设置一个访问位,当某页首次被装入内存时,其访问位被置为1.替换算法将内存中的页面都通过链接指针链接一个循环队列,并且有一个替换指针与之相关联,当某页被替换时,该指针被设置指向被替换页面的下一页(替换指针移动的唯一条件)。当某页被访问时,其访问位置为1。当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出:如果是1,则将它置为0,暂不换出,继续检查下一个页面,若第一轮扫描中所有页面都是1,则将这些页面的访问位依次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描

IMG_20230405_190225_edit_541726680488171

关键的几个要点:

  1. 替换指针只在页面被替换时指向下一页。可以设想这样做这个新被替换上去的页面,会在这轮扫描中最后被扫描到,也就印证了最近未使用
  2. 当扫描到访问位为1的块时要将其置为0,再扫描下一块。
  3. 当访问的块未缺页时,不要忘记将这个块的访问位置为1。不修改替换指针!!

改进型时钟置换算法

简单的时钟置换算法仅考虑到一个页面最近是否被访问过。事实上,如果被淘汰的页面没有被修改过就不需要执行IO操作写回外存。只有被淘汰的页面被修改过时,才需要写回外存

因此,除了考虑一个页面最近有没有被访问过外,操作系统还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面,避免IO操作。这及时改进型的时钟置换算法的思想。

修改位=0,表示页面没有被修改过:修改位=1,表示页面被修改过。

下面用(访问位,修改位)的形式表示各页面状态。如(1,1)表示一个页面近期被访问过且修改过

算法规则:将所有可能被置换的页面排成一个循环队列

第一轮:从当前位置开始扫描到第一个(0,0)的帧用于替换。本轮扫描不修改任何标志位。(第一优先级:最近没访问且没修改页面

第二轮:若第一轮扫描失败,则重新扫描,朝朝第一个(0,1)的帧用于替换。本轮将所有扫描过的帧访问位设位0。(第二优先级:最近没访问,但修改过页面

第三轮:若第二轮扫描失败,则重新扫描,查找第一个(0,0)的帧用于替换。本轮扫描不修改任何标志位。(第三优先级:最近访问过,但没修改的页面

第四轮:若第三轮扫描失败,则重新扫描,查找第一个(0,1)的帧用于替换。(第四优先级:最近访问过,且修改过的页面

由于第二轮中已将所有帧的访问位设为0,因此经过第三轮、第四轮扫描一定会有一个帧被选中,因此改进型CLOCK置换算法选择一个淘汰页面最多会进行四轮扫描

小结

image-20230405182915936

内存映射文件

image-20230405212411833

内存映射文件——操作系统向上层程序员提供的功能(系统调用):

  • 方便程序员访问文件数据
  • 方便多个进程共享同一个文件

采用虚拟内存技术,将文件IO作为常规内存访问。这种方法称为内存映射文件,允许一部分虚拟内存与文件进行逻辑关联(但是不调入内存)。

内存映射文件的写

内存文件的写入不一定时对磁盘文件的即时(同步)写入。有的操作系统定期检查文件的内存映射页面是否已经被修改,以便选择是否更新到物理文件。当关闭文件时,所有内存映射的数据会写道磁盘,并从进程虚拟内存中删除。

传统的文件访问方式

传统文件访问的方式:

  • open 系统调用——打开文件
  • seek系统调用——将读写指针移到某个位置
  • read系统调用——从读写指针所指位置读入若干数据(从磁盘读入内存)
  • write系统调用——将内存中的指定数据,写回磁盘(根据读写指针确定要写回什么位置)

image-20230405213850754

内存映射文件访问方式

内存映射文件的访问方式:

  • open系统调用——打开文件
  • mmap系统调用——将文件映射到进程的虚拟地址空间

和传统文件的访问方式不同的是,是否将文件数据是否读入内存。(传统文件操作需要将文件数据读入内存,而内存映射文件不需要将文件数据读入内存)。由于内存映射文件对应的文件在内存中是没有数据的(没有进行实质的数据拷贝),所以当访问文件数据的时候,就会产生缺页中断,将文件的操作交由操作系统来实现。

image-20230405214701938

关于传统文件读取和内存映射文件读取效率不同的原因,如下图。

image-20230405220641649

小结

image-20230405215328277

参考

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值