一致代码段与非一致代码段

【从头开始写操作系统系列】一致代码段与非一致代码段 上几篇文章,我们一直在讨论的都是 GDT 相关的一些问题,现在我们知道在系统在从实模式向保护模式跳转时,GDT 是必须要准备的结构。在介绍这一跳转之前,这篇文章我们来介绍两个概念:一致代码段和非一致代码段。 首先,我们先来看几个问题: 一致代码段和非一致代码段是什么? 为什么要有一致代码段和非一致代码段? 系统提供怎样的机制来使用户程序访问内核数据? 程序如何在段与段之间跳转? 接下来,我们将讨论上 阅读详情

一、一致代码段与非一致代码段

“一致”的意思大约是这样,当转移的目标是一个特权级更高的一致代码段时,当前的特权级会被延续下去,而向特权级更高的非一致代码段的转移则会引起 常规的保护异常,除非使用调用门或者任务门。一致代码段往往是用在内核共享的段,这些段是允许应用程序去访问的,而不需要内核转移到应用程序中来访问这些 共享的资源。对于一致代码段,有以下规则:

  • 特权级高的程序不允许访问特权级低的数据。比如,核心态不允许调用用户态的数据。
  • 特权级低的程序可以访问到特权级高的数据,但是访问程序的特权级不会发生变化。比如,用户态访问内核态共享的资源时,不会变成内核态。

而对于非一致代码段,则有着不同的规则:

  • 只允许同级访问。
  • 绝对禁止不同级程序访问。即内核态不能访问用户态,用户态也不能访问内核态。

之所以这么做是为了系统的安全性考虑,分离内核和用户程序,使内核不能被用户程序干涉,同时避免使用户态程序修改内核态的逻辑,导致在内核态下执行 用户程序的代码。上面所说的是代码段,而数据段则全都是非一致的,这意味着不可能被低特权级的代码访问到。然而,与代码段不同的是,数据段可以被更高特权 级的代码访问到,而不需要使用特定的门。规则总如如下:

 特权级
低->高
特权级
高->低
特权级
同级之间
适用于何种代码
一致代码段YesNoYes不访问受保护的资源和某些类型的异常处理的系统代码
非一致代码段NoNoYes避免低特权级的程序访问而被保护起来的系统代码
数据段
(总是非一致)
NoYesYes 

二、特权级

1.CPL、RPL和DPL

CPL是当前进程的权限级别(Current Privilege Level),是当前正在执行的代码所在的段的特权级,存在于cs寄存器的低两位。

RPL说明的是进程对段访问的请求权限(Request Privilege Level), 是对于段选择子而言的,每个段选择子有自己的RPL,它说明的是进程对段访问的请求权限,有点像函数参数。而且RPL对每个段来说不是固定的,两次访问同 一段时的RPL可以不同。RPL可能会削弱CPL的作用,例如当前CPL=0的进程要访问一个数据段,它把段选择符中的RPL设为3,这样它对该段仍然只 有特权为3的访问权限。处理器通过检查RPL和CPL来确认一下请求是否合法。即便提出访问请求的段有足够的特权级,如果RPL不够也是不行的。

操作系统过程往往用RPL来避免低特权级应用程序访问高特权级段内的数据。当操作系统过程(被调用过程)从一个应用程序 (调用过程)接收到一个选择子时,将会把选择子的RPL设成调用者的特权级。于是,当操作系统用这个选择子去访问相应的段时,处理器将会调用过程的特权级 (已经被存到RPL中),而不是更高的操作过程的特权级(CPL)进行特权检验。这样,RPL就保证了操作系统不会越俎代疱地代表一个应用程序去访问一个 段,除非这个程序本身是有权限的。(可以认为是以CPL来访问段DPL所出示的“证件(RPL)”,如出示的“证件”权级范围在CPL之内且满足DPL的 特权检查规则:DPL >= max{CPL,RPL},就能正常通过DPL;反之则不会通过还会发生错误)

DPL存储在段描述符中,规定访问该段的权限级别(Descriptor Privilege Level),每个段的DPL固定。当进程访问一个段时,需要进程特权级检查,一般要求DPL >= max {CPL, RPL}。当当前代码段试图访问一个段或者门时,DPL将会和CPL以及段或门选择子的RPL相比较,根据段或者门类型的不同,DPL将会被区别对待,下面介绍一下各种类型的段或者门的情况:

  • 数据段:DPL规定了可以访问此段的最低特权级。比如,一个数据段的DPL是1,那么只有运行在CPL为0或者1的程序才有权访问它。
  • 非一致代码段(不使用调用门的情况下):DPL规定访问此段的特权级。比如,一个非一致代码的特权级为0,那么只有CPL为0的程序才可以访问它。
  • 调用门:DPL规定了当前执行的程序或任务可以访问此调用门的最低特权级(这与数据段的规定是一致的)。
  • 一致代码段:DPL规定了访问此段的最高特权级。比如,一个一致代码段的DPL是2,那么CPL为0和1的程序将无法访问此段。
  • TSS:DPL规定了可以访问此TSS的最低特权级(这与数据段的规定是一致的)。

2.代码间跳转(段间)

普通转跳(没有使用调用门):即JMP或CALL后跟着48位全指针(16位段选择子+32位地址偏移),且其中的段选择子指向代码段描述符,这样的跳转称为直接(普通)跳转。普通跳转不能使特权级发生跃迁,即不会引起CPL的变化,看下面的详细描述:

代码段要求特权变化
一致代码段CPL >= DPL ,RPL不检查,也说是一致代码段描述符中的DPL规定可以转移到一致的代码段的最内层特权级(3级可以转移到0级,而0级只能转移到0级)。一致代码段 描述符内DPL的这种解释,正好与正常的DPL的解释相反。这是为了提供对应用程序的共享支持,而不要求改变特权级。转跳后程序的CPL = 转跳前程序的CPL
非一致代码段CPL = DPL & RPL<= DPL转跳后程序的CPL = 转跳前程序的CPL

通过调用门的跳转:当段间转移指令JMP和段间转移指令CALL后跟着的目 标段选择子指向一个调用门描述符时,该跳转就是利用调用门的跳转。这时如果选择子后跟着32位的地址偏移,也不会被cpu使用,因为调用门描述符已经记录 了目标代码的偏移。使用调门进行的跳转比普通跳转多一个步骤,即在访问调用门描述符时要将描述符当作一个数据段来检查访问权限,要求指示调用门的选择子的 RPL≤门描述符DPL,同时当前代码段CPL≤门描述符DPL,就如同访问数据段一样,要求访问数据段的程序的CPL≤待访问的数据段的DPL,同时选择子的RPL≤待访问的数据段或堆栈段的DPL。只有满足了以上条件,CPU才会进一步从调用门描述符中读取目标代码段的选择子和地址偏移,进行下一步的操作。

从调用门中读取到目标代码的段选择子和地址偏移后,我们当前掌握的信息又回到了先前,和普通跳转站在了同一条起跑线上(普通跳转一开始就得到了目标代码的段选择子和地址偏移),有所不同的是,此时,CPU会将读到的目标代码段选择子中的RPL清0,即忽略了调用门中代码段选择子的RPL的作用。完成这一步后,CPU开始对当前程序的CPL,目标代码段选择子的RPL(事实上它被清0后总能满足要求)以及由目标代码选择子指示的目标代码段描述符中的DPL进行特权级检查,并根据情况进行跳转,具体情况如下:

代码段要求特权变化
一致代码段CPL >= DPL ,RPL不检查因为RPL被清0,所以事实上永远满足RPL <= DPL,这一点与普通跳转一致,适用于JMP和CALL。
转跳后程序的CPL = 转跳前程序的CPL,因此特权级没有发生跃迁。
非一致代码段(JMP)CPL = DPL (RPL被清0,不检查)
,若不满足要求则程序引起异常。
转跳后程序的CPL = DPL,
因为前提是CPL=DPL,所以转跳后程序的CPL = DPL不会改变CPL的值,特权级也没有发生变化。如果访问时不满足前提CPL=DPL,则引发异常。
非一致代码段(CALL)CPL >= DPL(RPL被清0,不检查),若不满足要求则程序引起异常。

转跳后程序的CPL = DPL,
当条件CPL=DPL时,程序跳转后CPL=DPL,特权级不发生跃迁;当CPL>DPL时,程序跳转后CPL=DPL,特权级发生跃迁,这是我们当目前 位置唯一见到的使程序当前执行优先级(CPL)发生变化的跳转方法,即用CALL指令+调用门方式跳转,且目标代码段是非一致代码段。

一致代码段,非一致代码段
------------------------------------------------------------------------------------------

一致位:在描述符属性中TYPE(包含4个二进制位)字段的第2位。
当 S=1 时TYPE中的4个二进制位情况:
3 2 1 0
执行位 一致位 读写位 访问位
执行位:置1时表示可执行,置0时表示不可执行;
一致位:置1时表示一致码段,置0时表示非一致码段;
读写位:置1时表示可读可写,置0时表示只读;
访问位:置1时表示已访问,置0时表示未访问。

所以一致代码段和非一致代码段的意思就是指这个一致位是否置1,置1就是一致代码段,置0就为非一致代码段。

------------------------------------------------------------------------------------------

特权级
------------------------------------------------------------------------------------------

CPL是当前进程的权限级别(Current Privilege Level),是当前正在执行的代码所在的段的特权级,存在于cs寄存器的低两位。 (个人认为可以看成是段描述符未加载入CS前,该段的DPL,加载入CS后就存入CS的低两位,所以叫做CPL,其值就等于原段DPL的值)

RPL说明的是进程对段访问的请求权限(Request Privilege Level), 是对于段选择子而言的,每个段选择子有自己的RPL,它说明的是进程对段访问的请求权限,有点像函数参数。而且RPL对每个段来说不是固定的,两次访问同 一段时的RPL可以不同。RPL可能会削弱CPL的作用,例如当前CPL=0的进程要访问一个数据段,它把段选择符中的RPL设为3,这样虽然它对该段仍 然只有特权为3的访问权限。 (个人认为是以CPL来访问段DPL所出示的“证件(RPL)”,如出示的“证件”权级范围在CPL之内且满足DPL的特权检查规则:DPL >= max{CPL,RPL},就能正常通过DPL;反之则不会通过还会发生错误)

DPL存储在段描述符中,规定访问该段的权限级别(Descriptor Privilege Level),每个段的DPL固定。当进程访问一个段时,需要进程特权级检查,一般要求DPL >= max {CPL, RPL}

下面打一个比方,中国官员分为6级国家主席1、总理2、省长3、市长4、县长5、乡长6,假设我 是当前进程,级别总理(CPL=2),我去聊城市(DPL=4)考察(呵呵),我用省长的级别(RPL=3 这样也能吓死他们:-))去访问,可以吧,如果我用县长的级别,人家就不理咱了(你看看电视上的微服私访,呵呵),明白了吧!为什么采用RPL,是考虑到 安全的问题,就好像你明明对一个文件用有写权限,为什么用只读打开它呢,还不是为了安全!

------------------------------------------------------------------------------------------

代码间跳转
------------------------------------------------------------------------------------------

普通转跳(没有经过Gate 这东西):即JMP或Call后跟着48位全指针(16位段选择子+32位地址偏移),且其中的段选择子指向代码段描述符,这样的跳转称为直接(普通)跳转。普通跳转不能使特权级发生跃迁,即不会引起CPL的变化,看下面的详细描述:

目标是一致代码段:
要求:CPL >= DPL ,RPL不检查。

转跳后程序的CPL = 转跳前程序的CPL

目标是非一致代码段:
要求:CPL = DPL AND RPL<= DPL

转跳后程序的CPL = 转跳前程序的CPL


---------------------------------------------------------------------------------------

通过调用门的跳转:当 段间转移指令JMP和段间转移指令CALL后跟着的目标段选择子指向一个调用门描述符时,该跳转就是利用调用门的跳转。这时如果选择子后跟着32位的地址 偏移,也不会被cpu使用,因为调用门描述符已经记录了目标代码的偏移。使用调门进行的跳转比普通跳转多一个步骤,即在访问调用门描述符时要将描述符当作 一个数据段来检查访问权限,要求指示调用门的选择子的 RPL≤门描述符DPL,同时当前代码段CPL≤门描述符DPL,就如同访问数据段一样,要求访问数据段的程序的CPL≤待访问的数据段的DPL,同时选择子的RPL≤待访问的数据段或堆栈段的DPL。只有满足了以上条件,CPU才会进一步从调用门描述符中读取目标代码段的选择子和地址偏移,进行下一步的操作。

从调用门中读取到目标代码的段选择子和地址偏移后,我们当前掌握的信息又 回到了先前,和普通跳转站在了同一条起跑线上(普通跳转一开始就得到了目标代码的段选择子和地址偏移),有所不同的是,此时,CPU会将读到的目标代码段 选择子中的RPL清0,即忽略了调用门中代码段选择子的RPL的作用。完成这一步后,CPU开始对当前程序的CPL,目标代码段选择子的RPL(事实上它 被清0后总能满足要求)以及由目标代码选择子指示的目标代码段描述符中的DPL进行特权级检查,并根据情况进行跳转,具体情况如下:

目标是一致代码段:
要求:CPL >= DPL ,RPL不检查,因为RPL被清0,所以事实上永远满足RPL <= DPL,这一点与普通跳转一致,适用于JMP和CALL。
转跳后程序的CPL = 转跳前程序的CPL,因此特权级没有发生跃迁。

目标是非一致代码段:

当用JMP指令跳转时:
要求:CPL = DPL (RPL被清0,不检查),若不满足要求则程序引起异常。
转跳后程序的CPL = DPL
因为前提是CPL=DPL,所以转跳后程序的CPL = DPL不会改变CPL的值,特权级也没有发生变化。如果访问时不满足前提CPL=DPL,则引发异常。

当用CALL指令跳转时:

要求:CPL >= DPL(RPL被清0,不检查),若不满足要求则程序引起异常。

转跳后程序的CPL = DPL

当条件CPL=DPL时,程序跳转后CPL=DPL,特权级不发生跃迁;当CPL>DPL时,程序跳转后CPL=DPL,特权级发生跃迁,这是我们当目前位置唯一见到的使程序当前执行优先级(CPL)发生变化的跳转方法,即用CALL指令+调用门方式跳转,且目标代码段是非一致代码段。

Agent本地部署教程详细步骤 在开始之前,你需要明确你要部署的Agent是什么。如果你需要部署其他Agent,请参考其官方文档调整步骤。 阅读详情

相关推荐

Android Framework之Pkms详解

system 用户并没有访问应用程序目录的权限,但是 Installd 服务是以 root 用户启动的,可以访问 /data/data/ 下的目录,Installd 需要完成一些创建应用数据的任务。Installer 服务是 Android 提供的用于安装的服务,Installer 持有 Installd 守护进程对应的 Binder 服务的代理对象,本质上是通过 Binder 通信调用底层的 Installd 服务真正完成 APK 文件格式的优化和转换、建立相关的数据目录、删除文件、安装应用等工作。

门徒07的博客 1839

一致码段、非一致码段、dpl、cpl和rpl简介

一致码段、非一致码段、cpl、dpl、rpl

zdd56789的博客 2683

Blender地形建模实战:5步搞定Gazebo仿真地形(附避坑指南)

本文提供了一份详细的Blender地形建模实战指南,旨在帮助开发者快速创建Gazebo仿真地形。文章通过五个核心步骤,从环境准备、地形雕刻、模型优化导出,到创建Gazebo模型包及问题排错,系统讲解了如何将Blender中的地形模型成功导入Gazebo进行机器人仿真,并重点分享了关键的避坑经验。

weixin_28475533的博客 342

“一致代码段”和“非一致代码段”解惑!

自己在学习的过程中,发现对“一致”和“非一致”代码段的定义不是太清晰,所以在网上荡了一圈,总结一下加深印象!呵呵       1. 所谓的“一致代码段”,目的是为了共享,比如说该一致代码段的特权级是2,那么即使是特权级是3的代码,也可以访问该一致代码。也就是允许低权限的代码访问高权限的代码,而成功访问之后,当前的特权级并不是目标代码的特权级,而是原来代码的特权级。也就是说,跳转之后,CPL不

yu_chenglong的专栏 959

OWASP 2025版AI大模型攻击安全风险汇总(攻击方法种类)

提示词注入是大模型最基础、最常见的核心漏洞,攻击者通过构造直接或间接的恶意自然语言输入,篡改大模型原本的正常行为与输出结果。哪怕这类恶意内容对人类是隐藏、不可见的,只要模型能够正常解析读取,就会触发漏洞。它和大家常说的模型“越狱”相关,但并不等同:越狱是提示词注入的极端形式,会直接让模型彻底无视所有内置安全协议,完全脱离管控;而普通提示词注入,更多是针对性篡改模型行为、诱导执行特定操作。

墨痕诉清风的博客 513

游戏引擎定制化:大厂如何玩转性能极限(大白话生动有趣版)

游戏大厂如何深度定制游戏引擎?本文系统解析了商业引擎的局限性及大厂定制化的核心诉求。主要内容包括: 大厂定制引擎的根本原因:性能瓶颈、差异化需求、自有生态整合等 主流引擎的优劣势对比及适用场景 定制化重点领域:渲染管线优化、物理系统重构、网络架构改造等 全流程定制方案:从需求分析到模块重构再到工具链开发 典型案例:如腾讯CF手游的渲染优化、原神的热更新系统等 文章指出,顶级游戏产品必须对引擎核心模块动刀,通过深度定制实现性能突破和创新功能开发。同时提供了风险规避建议和技术演进趋势,为游戏开发者提供了宝贵的实

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 634

关于[特权级],[一致/非一致] 代码段 [内核栈] 的思考

逻辑上应该是这样: - 为什么要有特权级概念? “现实”的需要,导致了硬件设计中包括了所谓特权级的概念,我们对现实问题的分析和认识,发现了特权级的思想应该存在于OS设计中,这种思想的物理表现 形式就是硬件寄存器中的CPL,DPL,RPL位以及一整套实现特权级审查逻辑的电路; - 为什么要有所谓一致和非一致代码段的概念呢? 还是因为“现实”的需要,由于OS设计时的需要,OS无疑应该

imgodor的专栏 560

【回答问题】ChatGPT上线了!如何安装python-ipopt?python-ipopt有哪些用法?

python-ipopt是一种基于Python语言的求解非线性最优化问题的软件包。它使用了Interior Point Optimizer(IPOPT)算法来求解最优化问题。这段代码使用python-ipopt求解了一个无约束的非线性最小化问题,其目标函数为(x[0] - 1) ** 2 + (x[1] - 2) ** 2,求解结果为x_opt。求解线性规划问题、二次规划问题、二次范数最小化问题等类型的最优化问题。对于给定的最优化问题,可以设置不同的求解参数来控制求解的精度和效率。

源代码杀手的博客 2144

一致代码段和非一致代码段

之所以出现这个定义是因为系统要安全:内核要和用户程序分开..内核一定要安全.不能被用户程序干涉.但是有时候用户程序也需要读取内核的某些数据,怎么办呢?操作系统就引入了访问特权等级(0-3)的机制.这些特权等级,通过三个符号来体现CPL/DPL/RPL.其中CPL是存寄存器如CS中,RPL是代码中根据不同段跳转而确定,以动态刷新CS里的CPL.DPL是在GDT/LDT描述符表中,

feijj2002_的专栏 1万+

【Coppeliasim|轨迹规划(三)】机械臂逆解

文章目录一些设置导航点设置添加连接用于碰撞的设置代码实现终端输出 一些设置 导航点设置 关于如何添加设置 dummy 的细节建议参考官方手册,这里不再赘述。 添加连接用于碰撞的设置 按照序号点击(一个是机械臂,一个是所有的物体除了机械臂): 代码实现 getMatrixShiftedAlongZ=function(matrix,localZShift) local m={} for i=1,12,1 do m[i]=matrix[i] end

【人工智障 | 计算鸡视觉 | 机器孩】 1万+

华为OD机试2025C卷-双十一最大花费金额[100分](Java_Python3_C++_C语言_JsNode_Go)实现100%通过率

双十一最大花费金额 - 动态规划解法 摘要:本文介绍了华为OD机试中"双十一最大花费金额"问题的动态规划解法。该问题要求在给定N件商品价格和优惠券面额X的情况下,选择若干商品使总花费不超过X且尽可能大。核心解法采用布尔型动态规划数组,记录每个金额是否可被拼出。算法时间复杂度为O(N*X),空间复杂度为O(X)。通过倒序遍历避免重复选择同一商品,最后从X向下查找第一个可达金额作为答案。文中提供了C++和Java的实现代码,并解释了与经典0-1背包问题的关系。 关键点: 问题本质是0-1背包/子集和问题的变体

2503_91057718的博客 46

一致代码段,非一致代码段的本意和详细测试

不知道有没有人尝试过mov cs,ax这样的指令结果肯定挂,因为不能直接修改cs段寄存器的值,不能直接修改,那肯定可以间接咯,cs段寄存器和其他的段寄存器不太一样,它能加载的段描述符有:代码段描述符,调用门,TSS任务段,任务门,如果加载数据段描述符直接挂,(用数据段加载代码段描述符的时候,直接过,访问内存的时候才挂),而用cs加载数据段描述符直接挂。 这篇帖子只讲代码段描述符(调用门,任务门这些系统段描述符会后面会讲) 代码段描述符S=1时TYPE>=8 此时这个段描述符...

taolaodawho的博客 899

VSCode 配置 Claude Code 插件的 4 步安装法与 3 类常见报错解决方案

介绍 VSCode 中 Claude Code 插件的 4 步可靠安装流程与 3 类高频报错(上下文丢失、认证失败、加载卡死)的根因分析和精准修复方案,聚焦文件上下文捕获机制、请求头注入要求及缓存失效逻辑,提供可验证的命令行操作与日志定位方法。

weixin_28728443的博客 492

orange's学习--一致代码段和非一致代码段

参考资料https://blog.youkuaiyun.com/KLKFL/article/details/80650023 一、为什么要定义一致代码段与非一致代码段? 操作系统保护模式下把代码段分为一致代码段和非一致代码段的原因是:内核程序和用户程序要分开,内核程序不能被用户程序干扰。但是有时候用户程序也需要读取内核的某些数据,于是操作系统就从内核程序中分配一些可以供用户程序访问的段,但是不允许用户程序写...

交换ab:a=a^b;b=a^b;a=a^b; 365

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【转】一致代码段和非一致代码段

原文地址: http://blog.youkuaiyun.com/feijj2002_/article/details/4597174 之所以出现这个定义是因为系统要安全:内核要和用户程序分开..内核一定要安全.不能被用户程序干涉. 但是有时候用户程序也需要读取内核的某些数据,怎么办呢? 操作系统就引入了访问特权等级(0-3)的机制. 这些特权等级,通过三个符号来体现CPL/DPL/RPL. 其中

用小弟弟思考的程序员 437

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: delpi中的RTTI初试
下一篇: 函数可重入性
OSReact
博客等级 码龄14年 34粉丝 47原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值