盛夏大餐--水煮多线程

考场安排---图的着色原理之运用 考场安排姓名:杨小华 【问题描述】设学校共有n门课,需要进行期末考试,因为不少学生不止选修一门课程,所以不能把同一个学生选修的两门课程安排在同一场次进行考试,问学期的期末考试最少需多少场次考完?(提示:如果两门课被同一个同学选上,则表示这两门课的顶点之间存在一条边)。试设计一算法,当给定一个图时G=(V,E),|V|=n,(Vi,Vj)ЄE,当且仅当有一个同学选了课程i和课 阅读详情
深度下潜――多线程篇
 
作者:杨小华
 
计算机系统变得越来越复杂,多线程机制给我们带来了能够继续管理它们的希望。
――Andrew Koening and Barbara Moo
一、      线程的基本概念
进程(process)和文件(files)是UNIX/Linux操作系统两个最基本的抽象。进程是处于执行期的程序和它所包含的资源的总和,也就是说一个进程就是处于执行期的程序。一个线程(thread)就是运行在一个进程上下文中的一个逻辑流,不难看出,线程是进程中最基本的活动对象。
在传统的系统中,一个进程只包含一个线程。但在现代操作系统中,允许一个进程里面可以同时运行多个线程,这类程序就被称为多线程程序。所有的程序都有一个主线程(main thread),主线程是进程的控制流或执行线程,见图1。在多线程程序中,主线程可以创建一个或多个对等线程(peer thread),从这个时间点开始,这些线程就开始并发执行,见图2。主线程和对等线程的区别仅在于主线程总是进程中第一个运行的线程。从某种程度上看,线程可以看作是轻量级的进程(lightweight process)。在Linux操作系统中,内核调度的基本对象是线程,而不是进程,所以进程中的多个线程将由内核自动调度。
每个线程都拥有独立的线程上下文(thread context),线程ID(Thread ID,TID),程序计数器(pc),线程栈(stack),一组寄存器(register)和条件码。其中,内核正是通过线程ID(TID)来识别线程,进行线程调度的。
图 1多线程进程的控制流
图 2并发线程执行模型
二、      线程与进程的异同点
线程和进程在很多方面是相似的。相同点主要表现在如下几方面:
1)        比如都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略。
2)        每个进程都有一个进程控制块,线程也拥有一个线程控制块(在Linux内核,线程控制块与进程控制块用同一个结构体描述,即struct task_struct),这个控制块包含线程的一些属性信息,操作系统使用这些属性信息来描述线程。
3)        线程和子进程共享父进程中的资源。
4)        线程和子进程独立于它们的父进程,竞争使用处理器资源。
5)        线程和子进程的创建者可以在线程和子进程上实行某些控制,比如,创建者可以取消、挂起、继续和修改线程和子进程的优先级。
6)        线程和子进程可以改变其属性并创建新的资源
除了这些相同点,在很多方面也存在着差异:
1)        主要区别:每个进程都拥有自己的地址空间,但线程没有自己独立的地址空间,而是运行在一个进程里的所有线程共享该进程的整个虚拟地址空间
2)        线程的上下文切换时间开销比进程上下文切换时间开销要小的多
3)        线程的创建开销远远小于进程的创建
4)        子进程拥有自己的地址空间和数据段的拷贝,因此当子进程修改它的变量和数据时,它不会影响父进程中的数据,但线程可以直接访问它进程中的数据段
5)        进程之间通讯必须使用进程间通讯机制,但线程可以与进程中的其他线程直接通讯
6)        线程可以对同一进程中的其他线程实施大量控制,但进程只能对子进程实施控制
7)        改变主线程的属性可能影响进程中其他的线程,但对父进程的修改不影响子进程
三、      深入剖析线程
3.1    线程优缺点
线程的优点
线程的缺点
上下文切换需要更少的系统资源
并发读/写需要同步
增加了应用程序的吞吐量
很容易破坏它进程的地址空间
任务间的通讯不需要特殊机制
只存在于单个进程中,因此不能被重用
简化了程序结构
 
 表 1线程优缺点对比表
3.1   线程属性
POSIX线程库定义了线程属性对象,它封装了线程的创建者可以访问和修改的线程属性。线程属性主要包括如下属性:
1)        作用域(scope)
2)        栈尺寸(stack size)
3)        栈地址(stack address)
4)        优先级(priority)
5)        分离的状态(detached state)
6)        调度策略和参数(scheduling policy and parameters)
线程属性对象可以与一个线程或多个线程相关联。当使用线程属性对象时,它是对线程和线程组行为的配置。使用属性对象的所有线程都将具有由属性对象所定义的所有属性。虽然它们共享属性对象,但它们维护各自独立的线程ID和寄存器。
线程可以在两种竞争域内竞争资源:
1)        进程域(process scope):与同一进程内的其他线程
2)        系统域(system scope):与系统中的所有线程
作用域属性描述特定线程将与哪些线程竞争资源。一个具有系统域的线程将与整个系统中所有具有系统域的线程按照优先级竞争处理器资源,进行调度。
分离线程是指不需要和进程中其他线程同步的线程。也就是说,没有线程会等待分离线程退出系统。因此,一旦该线程退出,它的资源(如线程ID)可以立即被重用。
线程的布局嵌入在进程的布局中。进程有代码段、数据段和栈段,而线程与进程中的其他线程共享代码段和数据段,每个线程都有自己的栈段,这个栈段在进程地址空间的栈段中进行分配。线程栈的尺寸在线程创建时设置。如果在创建时没有设置,那么系统将会指定一个默认值,缺省值的大小依赖于具体的系统。
       POSIX线程属性对象中可设置的线程属性及其含义参见表二:
函数
属性
含义
int pthread_attr_setdetachstate
(pthread_attr_t* attr ,int detachstate)
detachstate
detachstate属性控制一个线程是否是可分离的
int pthread_attr_setguardsize
(pthread_attr_t* attr ,size_t guardsize)
guardsize
guardsize属性设置新创建线程栈的保护区大小
int pthread_attr_setinheritsched
(pthread_attr_t* attr, int inheritsched)
inheritsched
inheritsched决定怎样设置新创建线程的调度属性
int pthread_attr_setschedparam
(pthread_attr_t* attr ,
const struct sched_param* restrict param)
param
param用来设置新创建线程的优先级
int pthread_attr_setschedpolicy
(pthread_attr_t* attr, int policy)
policy
Policy用来设置先创建线程的调度策略
int pthread_attr_setscope
(pthread_attr_t* attr ,
int contentionscope)
contentionscope
contentionscope用于设置新创建线程的作用域
int pthread_attr_setstack
(pthread_attr_t* attr, void* stackader,
size_t stacksize)
stackader
stacksize
两者共同决定了线程栈的基地址以及堆栈的最小尺寸(以字节为单位)
int pthread_attr_setstackaddr
(pthread_attr_t* attr , void* stackader)
stackader
stackader决定了新创建线程的栈的基地址
int pthread_attr_setstacksize
(pthread_attr_t* attr, size_t stacksize)
stacksize
stacksize决定了新创建线程的栈的最小尺寸(以字节为单位)
表 2线程属性及其含义
3.2   线程调度和优先级
进程的调度策略和优先级属于主线程,换句话说就是设置进程的调度策略和优先级只会影响主线程的调度策略和优先级,而不会改变对等线程的调度策略和优先级(注:这句话不完全正确)。每个对等线程可以拥有它自己的独立于主线程的调度策略和优先级。
在Linux系统中,进程有三种调度策略:SCHED_FIFO、SCHED_RR和SCHED_OTHER,线程也不例外,也具有这三种策略。
在pthred库中,提供了一个函数,用来设置被创建的线程的调度属性:是从创建者线程继承调度属性,还是从属性对象设置调度属性。该函数就是:
int pthread_attr_setinheritsched (pthread_attr_t *__attr, int __inherit)
其中,inherit的值为下列值中的其一:
enum
{
 PTHREAD_INHERIT_SCHED, //线程调度属性从创建者线程继承
 PTHREAD_EXPLICIT_SCHED //线程调度属性设置为attr设置的属性
};
如果在创建新的线程时,调用该函数将参数设置为PTHREAD_INHERIT_SCHED时,那么当修改进程的优先级时,该进程中继承这个优先级并且还没有改变其优先级的所有线程也将会跟着改变优先级(现在应该明白我刚才为什么说那句话部正确的原因了吧)。
3.3   线程状态
线程具有进程所拥有的相同状态和状态转换。如图3所示:
 
图 3线程状态及其转换(摘自《pthread prime》)
  
四、      线程模型
线程的目的就是代表进程执行工作,如果一个进程拥有多个线程,进程就可以根据一定的策略和方法来管理这些线程,并进行相关工作。先辈们通过总结与抽象,创造了线程模型的概念,这里的线程模型就是我们常说的架构,设计模式等,为我们这些后辈们提供了借鉴的意义。
4.1   线程模型总览
经过前人的摸索,总结与抽象,提炼出了一些通用的模型:
1)        委托模型(delegation),又称为boss-worker模型
2)        对等模型(peer-to-peer)
3)        管道模型
4)        生产者-消费者模型(producer-consumer)
各个模型的含义,如表三所示:
线程模型
含义
委托模型
Boss线程创建其他线程(worker线程),并给每个worker线程分配任务。Boss线程可能在每个线程完成它们的任务之前一直等待。
对等模型
所有的线程都具有相同的工作状态。对等线程创建执行任务所需要的所有线程,但不执行委托职责。对等线程可以从单个输入流处理请求,这些输入流被所有线程共享,或者每个线程都有其自己的输入流。
管道模型
类似于装配线流程,分阶段处理输入流,然后传给下一个线程进行处理
生-消模型
生产者线程生产数据给消费者线程使用,数据存储在生产者和消费者共享的存储块中。
表 3线程模型及其含义
4.2    委托模型
Boss线程创建其他线程(worker线程),并给每个worker线程分配任务。Boss线程可能在每个线程完成它们的任务之前一直等待。Boss线程将任务委托给每个worker线程是通过指定一个函数来完成的。由于每个worker线程被分配了任务,所以每个worker线程的职责就是执行指定的任务。
基于以上原理,可以演变出两类委托模型:
浪费型:当系统有请求任务时,boss线程创建worker线程。对每一个请求的处理就能够委托给一个worker线程。在这种情况下,boss线程执行事件循环,当有事件发生时,就创建一个worker线程,并给它们指派职责。如图4所示。
图 4委托模型――浪费型
这类应用实际意义不大,可能常见于试验型或者连接请求不多的情况。因为线程不可能无止境的创建下去,更何况创建太多的线程,势必会影响到系统的性能,这样就造成了性能瓶颈。
节约型:boss线程创建一个线程池,可以为池中的线程指派任务。当有任务到达时,boss线程发信号通知worker线程进行处理。该worker线程处理完成之后,接着处理下一个请求。如果没有请求,那么就挂起自身,直到收到boss的通知或者等待一个特定的时间,再次读取请求。如图5所示。
图 5委托模型――节约型
其中节约型中的boss线程的主要目的就是创建所有的worker线程,将请求放入队列中,然后唤醒worker线程。Worker线程检查队列中的请求,执行指派的任务。如果没有可供处理的任务,便挂起自己。所有的boss线程和worker线程并发执行。
大名鼎鼎的IOCP(IO完成端口)就是这类模型。      
4.3    对等模型
4.4    管道模型
4.5    生产者-消费者模型
  
五、      线程同步机制
5.1    POSIX标准定义的类型
5.2    互斥信号量
5.3    读写锁
5.4    条件变量
5.5    多重条件变量
5.6    面向对象的同步方法
  
六、      线程调试
6.1    调试工具
6.2    调试策略
6.3    关于多线程调试的一些文章
 
七、      参考文献
 正在进行时,待续,敬请关注......
 
三相维也纳Vienna整流器电流过零畸变消除仿真模型【三种消除方法】(Simulink仿真实现) 内容概要:本文针对三相维也纳(Vienna)整流器在运行过程中存在的交流输入电流过零畸变问题,提出并实现了三种有效的消除方法,并基于Simulink平台构建了完整的仿真模型进行验证。首先深入分析了电流过零畸变的成因,主要包括控制延迟、功率器件的非理想开关特性以及调制策略在零电流切换时刻引发的不连续性。随后,系统阐述了三种核心抑制策略:一是改进电流环控制算法,引入前馈补偿机制以提升动态响应速度,减小因控制滞后导致的畸变;二是优化空间矢量脉宽调制(SVPWM)策略,通过对冗余小矢量作用时间的精确分配,实现中点电位平衡与谐波抑制的协同控制;三是采用死区时间补偿与非线性校正相结合的方法,有效抵消功率器件开关延迟、反向恢复等非线性因素带来的波形失真。仿真结果表明,所提出的复合控制策略能显著改善输入电流波形质量,大幅降低总谐波畸变率(THD),有效提升系统功率因数、电能质量和运行稳定性。该研究为高功率密度、高效率的三电平功率因数校正(PFC)整流器的设计与优化提供了可复现的仿真方案和理论依据。; 适合人群:具备电力电子与电力传动领域扎实的理论基础,熟练掌握Simulink/Matlab仿真工具,从事新能源发电、电动汽车充电、航空航天电源、工业变流器等方向的硕士/博士研究生、研发工程师及科研人员;尤其适合正在开展Vienna整流器拓扑结构、先进调制策略或高性能PFC控制技术相关课题研究与产品开发的专业技术人员。; 使用场景及目标:①深入理解三相Vienna整流器中电流过零畸变的物理机理与数学建模方法;②掌握基于SVPWM的中点电位平衡控制与谐波抑制的协同优化策略;③为设计高效率、低谐波的中大功率PFC整流器提供一套完整的、经过验证的仿真解决方案与参数设计思路,服务于科研项目攻关与工程产品原型开发。; 阅读建议:建议读者结合文中详述的三种消除方法,动手搭建或修改相应的Simulink仿真模型,通过对比不同控制策略下的电流波形、THD分析及中点电位波动情况,深入理解各方法的优劣与适用条件。在实践过程中,应重点关注控制参数(如PI调节器增益、前馈系数)的整定对系统稳定性、动态响应和抗干扰能力的影响。同时,可参考文档中提供的Mathcad计算书与双闭环设计案例,深化对整流器系统级设计与参数匹配的理解,实现理论与实践的深度融合。 立即下载

相关推荐

高校技术转移办公室人员如何快速识别优质专利并推动其转化?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

我的专题文章之三------对多核多线程的总结

    我的专题文章之三------对多核多线程的总结 杨小华      从开发第一个基于多线程的项目已经有四个年头了,一路也是跌跌撞撞,不断的更新自己对多核多线程的认知程度,不断的实践,不断的优化和总结。 在这个过程中,写了不少关于多线程的文章,既是总结,也是鞭策自己更加深入的了解。     写的第一篇多线程的文章,是关于编译方面的,当然这篇文章重点在于介绍autoc

极光 1万+

高校技术转移办公室人员如何高效完成技术需求挖掘与转化对接?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

炉边夜话---多核多线程杂谈

炉边夜话---多核多线程杂谈(精简版)多核多线程已经成为当前一个时髦的话题,早在2005年C++大师Herb Sutter就说过免费的午餐已经结束,并发编程的时代已经来临。从接触第一个多线程项目以来,已经是第四个年头了,一直想把这几年的点点滴滴写成文章,让刚接触的人少走弯路,这便是我写这本书的初衷。很早就有了此想法,一是由于自己懒惰,二是业余时间比较少,三是才疏学浅不敢瞎写,所以一直未能成

极光 1万+

新手避坑指南:HT7036计量芯片SPI读取电压的完整流程(从复位到校准)

本文详细介绍了HT7036计量芯片的SPI读取电压完整流程,从硬件准备到校准设置,重点解析了复位引脚处理、SPI通信配置、芯片初始化及数据处理等关键步骤。针对常见问题如晶振焊接、SPI时序错误等提供实用解决方案,帮助开发者高效完成电压测量与校准。

weixin_30070339的博客 327

virtualbox虚拟机里面最顶部没有控制、设置和帮助等选项

无意中操作,导致virtualbox虚拟机里面最顶部没有控制,设置和帮助选项  virtualbox虚拟机窗口显示如下如: 如何设置,窗口显示如下图所示呢: virtualbox虚拟机窗口模式显示设置,切换可以通过如下图所示操作进行切换: PS:一定要是右边的Ctrl+C

WEL测试 8780

调查问卷:测试你对多核多线程的认知程度

测试你对多核多线程的认知程度        目前,多核多线程编程已经成为一种趋势,但大部分程序员还没有从串行程序的思维中走出来。即使有些人对多核多线程的概念有所了解,但也是一知半解,写起多核多线程程序来总是束手束脚。        据Intel预测,到2013年CPU将达到256核。掐指头算一算,也就是还有5年的时间,但留给我们程序员的时间却很少了。这不是危言耸听,现实情况确实如此。如果从现在就开

极光 1万+

从零构建:用Arduino和MCP2515模块搭建你的第一个CAN Bus网络

本文详细介绍了如何使用Arduino和MCP2515模块从零搭建CAN Bus网络,实现温湿度数据的传输与显示。涵盖硬件连接、软件配置、发送端与接收端代码实现,以及系统调试和进阶应用,帮助初学者快速掌握CAN总线通信技术。

d6e7f8的博客 834

你的变量究竟存储在什么地方?

 你的变量究竟存储在什么地方?作者:杨小华       我相信大家都有过这样的经历,在面试过程中,考官通常会给你一道题目,然后问你某个变量存储在什么地方,在内存中是如何存储的等等一系列问题。不仅仅是在面试中,学校里面的考试也会碰到同样的问题。       如果你还不知道答案,请接着往下看。接下来,我们将在Linux操作系统上,以GCC编译器为例来讲解变量的存储。       在计算

极光 1万+

华为2024机考真题集合

2.中位数是指把一组数据从小到大排列,最中间的那个数,如果这组数据的个数是奇数,那最中间那个就是中位数,如果这组数据的个数为偶数,那就把中间的两个数之和除以 2,所得的结果就是中位数。在实际考试中会随机抽三道题目进行考察,其中两道100分卷题和一道200分卷题,总共400分。幼儿园组织活动,老师布置了一个任务:每个小朋友去了解与自己同一个小区的小朋友还有几个。3.查找整型数组中元素的众数并组成一个新的数组,求新数组的中位数。1.众数是指一组数据中出现次数量多的那个数,众数可以是多个。

qq_25360769的博客 5093

RTX6000 PRO BLACKWELL 最优 CUDA 版本选择指南(适配 vLLM/SGLang 大模型推理)

本文针对NVIDIA Blackwell架构RTX6000PRO显卡部署vLLM/SGLang大模型推理引擎时的CUDA版本选择问题,提出专业建议。分析表明,CUDA12.9(需搭配552.06+驱动)是最优选择,因其完全支持BW架构特性,且与vLLM/SGLang最新版本深度适配。文章提供详细的Linux环境部署教程,包括驱动升级、CUDA12.9安装及vLLM/SGLang配置步骤,并指出CUDA13.0目前适配不完善,不推荐新手使用。最后给出常见问题解决方案,强调版本匹配对推理性能和稳定性的重要性。

2501_93651177的博客 682

通过内核源码看函数调用之前世今生

通过内核源码看函数调用之前世今生                                                                             作者:杨小华栈(Stack):一个有序的积累或堆积                                                         

极光 9534

什么是华为OD?怎么才能通过华为OD机试?华为OD机试怎么刷题?(2024最新华为OD机试E卷更新中)

华为OD是Outsourcing Dispacth模式,是华为和外企德科联合招聘的简称。目前华为大多数是OD招聘。OD模式也是华为提出的一种新的用工形式,每年都会从OD项目挑优秀员工转为正编。所有OD和正式员工一样对待,没有差别,部门平时开会、评审等活动都是一起参加的,是同薪同酬,都是由华为的HR直接定的薪资,看的是我们技术能力。华为是大企业,能到华为上班也是有能力的,每个部门都有好多职位,是金子,在哪都会发光。

KJ.JK 11万+

我的专题文章之一 --对变量的总结

我的专题文章之一 --对变量的总结 三篇文章总算完成了。可以说在6月8号就完成了。主要是由于工作的原因,比较忙,贴上来还要排版,所以最后一篇文章放上来的时间晚了点。在我word文档里面有很多箭头,而优快云的Blog里面不支持箭头,所以要花不少时间来排版。之所以要排版,是为了以后自己看的舒服一点,这样才有心情看下去。当我写完这三篇文章之后,自己觉得收获很大。在写这三篇文章的过程

极光 7766

【施磊】C++课程笔记目录

【C++编程】施磊老师C++笔记目录

GeniusAng的博客 4124

基于深度学习的CT图像肺结节分割与检测系统[完整代码数据分享]

基于深度学习的CT图像肺结节分割与检测系统[完整代码数据分享]

270

深入变量的“案发”现场

深入变量的“案发”现场 作者:杨小华       当《绝对能够测试你的C语言功力的几个问题》第一次出现在优快云首页时,我就进入了张老师Blog。客观上说,出的题目比较基础,但每一题都说出一个所以然来,恐怕不是很简单。过了几天就贴出了《语言测试题的讲解分析》,我怀着好奇的心情进去看了看。发现里面赞扬的也有,诋毁的也有。韩愈《师说》里面讲过:闻道有先后,术业有专攻。张老师自然有他的可取之处,

极光 5540

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

免费的午餐已经结束,你准备好了吗?

免费的午餐已经结束,你准备好了吗?作者:杨小华引子2005年3月,C++大师Herb Sutter在Dr.Dobb’s Journal上发表了一篇名为《免费的午餐已经结束》的文章,一石激起千层浪,该文引起了社区广大程序员的热烈讨论。文章指出:现在的程序员对效率、伸缩性、吞吐量等一系列性能指标相当忽视,很多性能问题都依仗越来越快的CPU来解决。但CPU的速度很快将偏离摩尔定律的轨迹,并达

极光 3550

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

二分查找算法

二分查找算法是基于已经排好序的数列。这是它的实现:#include #include #include //二分法查找int find(int *result,int key,int len){ int first,end,mid; first=0; end=len-1; while(first {  mid=(first+end)/2;  if(result[mid]==key)  

极光 3077

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

构造函数浅析

构造函数浅析作者:normalnotebook    构造函数把一堆无逻辑联系的存储单元单位转换成一个活生生的对象.它可能用于初始化该对象的内部数据成员,也可能用于分配资源(内存、文件、信号量等等).构造函数是与类同名的成员函数.构造函数是在创建类的对象时自动调用的.其一般表现形式为:X::X();class X{public:       X();       X(i

极光 2231

冒泡和选择排序

#include <stdio.h> #include <stdlib.h> #include <string.h> //冒泡排序 void bubbleSort(int *a,int len) {      int i,j,temp;      for(i = 0;i<len-1;i++)      {           for(j=0;j<l...

极光 2101

快速排序

//快速排序,主要思想是通过一趟排序将待排序的记录分割成相邻的两个区域, //其中一个区域中的关键字均比另一区域中记录的关键字要小,在分别对这两个 //区域进行排序,以达到整个序列有序。一般情况是O(logn),最坏情况是O(n)   #include <stdio.h> #define N 10 int QSorting(int *a, int start, int end)...

极光 1883
上一篇: 我的专题文章之一 --对变量的总结
下一篇: 难道我们的祖先都是这样写程序的?
normalnotebook
博客等级 码龄24年 647粉丝 38原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值