一文弄懂操作系统原理算法之--调度算法

第三章:操作系统--调度算法

Tips: 各种调度算法的学习思路

  • 算法思想
  • 算法规则
  • 这种调度算法是用于作业调度还是进程调度?
  • 抢占式?非抢占式?
  • 优缺点
  • 是否会导致饥饿

1、先来先服务(FCFS)

1.1、概述

  • 算法思想:主要从“公平”的角度考虑(类似于我们生活中排队买东西的例子), 先请求 CPU 的进程首先分配到 CPU。当一个进程进入就绪队列时,它的 PCB 会被链接到队列尾部。当 CPU 空闲时,它会分配给位于队列头部的进程,并且这个运行进程从队列中移去。
  • 算法规则:按照作业/进程到达的先后顺序进行服务
  • 用于作业/进程调度:用于作业调度时,考虑的是哪个作业先到达后备队列;用于进程调度时,考虑的是哪个进程先到达就绪队列
  • 是否可抢占?:非抢占式的算法,即一旦 CPU 分配给了一个进程,该进程就会使用 CPU 直到释放 CPU 为止,即程序终止或是请求 I/O。FCFS 算法对于分时系统(每个用户需要定时得到一定的 CPU 时间)是特别麻烦的。允许一个进程使用 CPU 过长将是个严重错误
  • 优缺点
    • 优点:公平、算法实现简单
    • 缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好,比如下面的P3进程,带权周转时间为8s,但是它只需要1s即可运行完成,即FCFS算法对长作业有利,对短作业不利(Eg: 排队买奶茶...)
  • 是否会导致饥饿(某进程/作业长期得不到服务):不会

1.2、举例

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用先来先服务调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。

进程到达时间运行时间
P107
P224
P341
P454

先来先服务调度算法:按照到达的先后顺序调度,事实上就是等待时间越久的越优先得到服务

因此,调度顺序为: P1→P2→P3→P4 ,调度顺序如下所示:P1到达之后运行7个时间之后P2开始调度。。。

image.png

各个进程计算时间:

image.png

2、短作业优先(SJF)

2.1、概述

  • 算法思想:追求最少的平均等待时间,最少的平均周转时间、最少的平均平均带权周转时间
  • 算法规则:按”最短的作业/进程优先得到服务(所谓“最短”,是指要求服务时间最短)
  • 用于作业/进程调度:即可用于作业调度,也可用于进程调度。用于进程调度时称为“短进程优先(SPF, Shortest Process First) 算法”
  • 是否可抢占?:SJF和SPF是非抢占式的算法。但是也有抢占式的版本--最短剩余时间优先算法( SRTN, Shortest Remaining Time Next )
  • 优缺点
    • 优点:“最短的”平均等待时间、平均周转时间
    • 缺点:不公平。对短作业有利,对长作业不利。可能产生饥饿现象。另外,作业/进程的运行时间是由用户提供的, 并不一定真实,不一定能做到真正的短作业优先
  • 是否会导致饥饿(某进程/作业长期得不到服务):会。如果源源不断地有短作业/进程到来,可能使长作业/进程长时间得不到服务,产生“饥饿”现象。如果一直得不到服务,则称为 "饿死"

2.2、举例

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用非抢占式的短作业优先调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。

进程到达时间运行时间
P107
P224
P341
P454

短作业/进程优先调度算法:每次调度时选择当前时刻已到达且运行时间最短的作业/进程。

因此,调度顺序为: P1→P3→P2→P4

即刚开始只有P1到达,所以P1先调度,其次在P1运行时间内,其他线程均已到达,之中是P3运行时间最短,所以P3第二个被调度,最后P2和P4之间由于P2先到达,所以P2第三个被调度。

image.png

各个进程计算时间:

image.png

3、抢占式的短作业优先(SRTN)

3.1、概述

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用抢占式的短作业优先调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。

抢占式的短作业优先算法又称最短剩余时间优先算法SRTN

进程到达时间运行时间
P107
P224
P341
P454

最短剩余时间优先算法:每当有进程加入就绪队列改变时就需要调度,如果新到达的进程剩余时间【剩余运行时间】比当前运行的进程剩余时间更短,则由新进程抢占CPU,而当前运行进程重新回到就绪队列另外,当一个进程完成时也需要根据该调度算法进行调度

需要注意的是,当有新进程到达时就绪队列就会改变,就要按照上述规则进行检查。以下Pn(m)表示当前Pn进程剩余时间为m。各个时刻的情况如下:

  • 0时刻(P1到达) : P1 (7)
  • 2时刻(P2到达) : P1 (5)、P2 (4)
  • 4时刻(P3到达):P1(5)、P2(2)、P3(1)
  • 5时刻(P3完成且P4刚好到达) : P1 (5)、P2 (2)、P4 (4)
  • 7时刻(P2完成) : P1 (5)、P4 (4)
  • 11时刻(P4完成) : P1 (5)

图示调度情况如下:

image.png

各个进程计算时间:

image.png

4、短作业优先算法相关说明

注意几个小细节:

  1. 如果题目中未特别说明,所提到的“短作业/进程优先算法”默认是非抢占式的
  2. 很多书上都会说“SJF调度算法的平均等待时间、平均周转时间最少”
    1. 严格来说,这个表述是错误的,不严谨的。之前的例子表明,最短剩余时间优先算法得到的平均等待时间、平均周转时间还要更少
    2. 应该加上一个条件“在所有进程同时可运行时,采用SJF调度算法的平均等待时间、平均周转时间最少”;
    3. 或者说“在所有进程都几乎同时到达时,采用SJF调度算法的平均等待时间、平均周转时间最少”;
    4. 如果不加上述前提条件,则应该说“抢占式的短作业/进程优先调度算法(最短剩余时间优先,SRNT算法)的平均等待时间、平均周转时间最少”
  3. 虽然严格来说,SJF的平均等待时间、平均周转时间并不一定最少,但相比于其他算法(如FCFS),SJF依然可以获得较少的平均等待时间、平均周转时间
  4. 如果选择题中遇到“SJF算法的平均等待时间、平均周转时间最少”的选项,那最好判断其他选项是不是有很明显的错误,如果没有更合适的选项,那也应该选择该选项。

5、FCFS/SJF算法的思考

  • FCFS算法是在每次调度的时候选择一个等待时间最长的作业(进程)为其服务。但是没有考虑到作业的运行时间,因此导致了对短作业不友好的问题
  • SJF算法是选择一个执行时间最短的作业为其服务。但是又完全不考虑各个作业的等待时间,因此导致了对长作业不友好的问题,甚至还会造成饥饿问题
  • 能不能设计一个算法,即考虑到各个作业的等待时间,也能兼顾运行时间呢?====高响应比优先算法

6、高响应比优先算法(HRRN)

6.1、概述

  • 算法思想:要综合考虑作业/进程的等待时间和要求服务的时间

  • 算法规则:在每次调度时先计算各个作业/进程的响应比,选择响应比最高的作业/进程为其服务【响应比>=1】

    响应比=(等待时间+要求服务时间)/要求服务时间

  • 用于作业/进程调度:即可用于作业调度,也可用于进程调度。

  • 是否可抢占?:非抢占式的算法。因此只有当前运行的作业/进程主动放弃处理机时,才需要调度,才需要计算响应比

  • 优缺点

    • 综合考虑了等待时间和运行时间(要求服务时间)
    • 等待时间相同时,要求服务时间短的优先(SJF 的优点)
    • 要求服务时间相同时,等待时间长的优先(FCFS 的优点)
    • 对于长作业来说,随着等待时间越来越久,其响应比也会越来越大,从而避免了长作业饥饿的问题
  • 是否会导致饥饿(某进程/作业长期得不到服务):不会

6.2、举例

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用高响应比优先调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。

高响应比优先算法:非抢占式的调度算法,只有当前运行的进程主动放弃CPU时(正常/异常完成,或主动阻塞),才需要进行调度,调度时计算所有就绪进程的响应比,选响应比最高的进程上处理机

image.png

图示调度情况如下:

image.png

综上: 三种算法的比较

image.png

注: 这几种算法主要关心对用户的公平性、平均周转时间、平均等待时间等评价系统整体性能的指标,但是不关心“响应时间”,也并不区分任务的紧急程度,因此对于用户来说,交互性很糟糕。**因此这三种算法一般适合用于早期的批处理系统,**当然,FCFS算法也常结合其他的算法使用,在现在也扮演着很重要的角色。而适合用于交互式系统的调度算法将在下个小节介绍...

7、时间片轮转调度算法RR

7.1、概述

  • 算法思想:公平地、轮流地为各个进程服务,让每个进程在一定时间间隔内都可以得到响应
  • 算法规则:按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片(如100ms)。若进程未在一个时间片内执行完,则剥夺处理机,将进程重新放到就绪队列队尾重新排队。
  • 用于作业/进程调度:用于进程调度(只有作业放入内存建立了相应的进程后,才能被分配处理机时间片)
  • 是否可抢占?:若进程未能在时间片内运行完,将被强行剥夺处理机使用权,因此时间片轮转调度算法属于抢占式的算法。由时钟 装置发出时钟中断来通知CPU时间片已到
  • 优缺点
    • 优点:公平;响应快,适用于分时操作系统;
    • 缺点:缺点:由于高频率的进程切换,因此有一定开销;不区分任务的紧急程度。
  • 是否会导致饥饿(某进程/作业长期得不到服务):不会。

7.2、举例

时间片轮转调度算法:它是随着分时系统的诞生而诞生的,轮流让就绪队列中的进程依次执行个时间片(每次选择的都是排在就绪队列队头的进程)

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用时间片轮转调度算法,分析时间片大小分别是2、5时的进程运行情况。

image.png

时间片大小为2 (注:以下括号内表示当前时刻就绪队列中的进程、进程的剩余运行时间)

  • 0时刻(P1(5)):0时刻只有P1到达就绪队列,让P1上处理机运行一个时间片
  • 2时刻(P2(4)→P1(3)):2时刻P2到达就绪队列,P1运行完一个时间片,被剥夺处理机,重新放到队尾。此时P2排在队头,因此让P2上处理机。(注意: 2时刻,P1下处理机,同一时刻新进程P2到达,如果在题目中遇到这种情况,默认新到达的进程先进入就绪队列)
  • 4时刻(P1(3)→P3(1)→P2(2)):4时刻,P3到达,先插到就绪队尾,紧接着,P2下处理机也插到队尾
  • 5时刻(P3(1)→P2(2)→P4(6)):5时刻,P4到达插到就绪队尾(注意:由于P1的时间片还没用完,因此暂时不调度。另外,此时P1处于运行态,并不在就绪队列中)
  • 6时刻(P3(1)→P2(2)→P4(6)→P1(1)): 6时刻,P1时间片用完,下处理机,重新放回就绪队尾,发生调度
  • 7时刻(P2(2)→P4(6)→P1(1)):虽然P3的时间片没用完,但是由于P3只需运行1个单位的时间,运行完了会主动放弃处理机,因此也会发生调度。队头进程P2上处理机。
  • 9时刻(P4(6)→P1(1):进程P2时间片用完,并刚好运行完,发生调度,P4上处理机
  • 11时刻(P1(1)→P4(4)): P4时间片用完,重新回到就绪队列。P1上处理机
  • 12时刻(P4(4)) : P1运行完,主动放弃处理机,此时就绪队列中只剩P4,P4上处理机
  • 14时刻() :就绪队列为空,因此让P4接着运行一个时间片。
  • 16时刻:所有进程运行结束

image.png

时间片大小为5 (注:以下括号内表示当前时刻就绪队列中的进程、进程的剩余运行时间)

  • 0时刻(P1(5)) :只有P1到达,P1上处理机。
  • 2时刻(P2(4)) : P2到达,但P1时间片尚未结束,因此暂不调度
  • 4时刻(P2(4) →P3(1) : P3到达,但P1时间片尚未结束,因此暂不调度
  • 5时刻(P2(4)→P3(1)→P4(6) ) : P4到达,同时,P1运行结束。发生调度,P2上处理机。
  • 9时刻(P3(1)→P4(6)) : P2运行结束,虽然时间片没用完,但是会主动放弃处理机。发生调度。
  • 10时刻(P4(6)) : P3运行结束,虽然时间片没用完,但是会主动放弃处理机。发生调度。
  • 15时刻( ) : P4时间片用完,但就绪队列为空,因此会让P4继续执行一个时间片。
  • 16时刻( ) : P4运行完,主动放弃处理机。所有进程运行完。

image.png

7.3、算法评价

若按照先来先服务调度算法...,则时间片为5 的时候情况和先来先服务FCFS算法结果一样

image.png

如果时间片太大,使得每个进程都可以在一个时间片内就完成,则时间片轮转调度算法退化为先来先服务调度算法,并且会增大进程响应时间。因此时间片不能太大。比如:系统中有10个进程在并发执行,如果时间片为1秒,则一个进程被响应可能需要等9秒..也就是说,如果用户在自已进程的时间片外通过键盘发出调试命令,可能需要等待9秒才能被系统响应

另一方面,进程调度、切换是有时间代价的(保存、恢复运行环境),因此如果时间片太小,会导致进程切换过于频繁【一般来说,设计时间片时要让切换进程的开销占比不超过1%】,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比例减少。可见时间片也不能太小。

8、优先级调度算法

8.1、概述

  • 算法思想:随着计算机的发展,特别是实时操作系统的出现,越来越多的应用场景需要根据任务的紧急程度来决定处理顺序

  • 算法规则:调度时选择优先级最高的作业/进程

  • 用于作业/进程调度:既可用于作业调度,也可用于进程调度。甚至,还会用于在之后会学习的I/O调度中

  • 是否可抢占?:抢占式、非抢占式都有。做题时的区别在于:非抢占式只需在进程主动放弃处理机时进行调度即可,而抢占式还需 在就绪队列变化时,检查是否会发生抢占。

  • 优缺点

    • 优点:用优先级区分紧急程度、重要程度,适用于实时操作系统。可灵活地调整对各种作业/进程的偏好程度。
    • 缺点:若源源不断地有高优先级进程到来,则可能导致饥饿
  • 是否会导致饥饿(某进程/作业长期得不到服务)

8.2、举例

非抢占式的优先级调度算法

例题:各进程到达就绪队列的时间、需要的运行时间、进程优先数如”下表所示。使用非抢占式的优先级调度算法,分析进程运行情况。(注: 优先数越大,优先级越高)

非抢占式的优先级调度算法:每次调度时选择当前已到达且优先级最高的进程。当前进程主动放弃处理机时发生调度。

注:以下括号内表示当前处于就绪队列的进程

  • 0时刻(P1) :只有P1到达,P1上处理机。
  • 7时刻(P2、 P3、P4) : P1运行完成主动放弃处理机,其余进程都已到达,P3优先级最高,P3 上处理机。
  • 8时刻( P2、P4) : P3完成,P2、P4优先级相同,由于P2先到达,因此P2优先上处理机
  • 12时刻( P4) : P2完成,就绪队列只剩P4,P4. 上处理机。
  • 16时刻( ) : P4完成,所有进程都结束

image.png

抢占式的优先级调度算法

例题:各进程到达就绪队列的时间、需要的运行时间、进程优先数如”下表所示。使用抢占式的优先级调度算法,分析进程运行情况。(注: 优先数越大,优先级越高)

抢占式的优先级调度算法:每次调度时选择当前已到达且优先级最高的进程。当前进程主动放弃处理机时发生调度。另外,当就绪队列发生改变时也需要检查是会发生抢占。

注:以下括号内表示当前处于就绪队列的进程

  • 0时刻(P1) :只有P1到达,P1 上处理机。
  • 2时刻(P2) : P2到达就绪队列,优先级比P1更高,发生抢占。P1回到就绪队列,P2 上处理机。
  • 4时刻(P1、 P3) : P3到达,优先级比P2更高,P2回到就绪队列,P3抢占处理机。
  • 5时刻(P1、 P2、P4) : P3完成,主动释放处理机,同时,P4也到达,由于P2比P4更先进入就绪队列,因此选择P2上处理机
  • 7时刻(P1、 P4) : P2完成,就绪队列只剩P1、P4,P4上处理机。
  • 11时刻(P1 ) : P4完成,P1上处理机

image.png

8.3、算法补充

就绪队列未必只有一个,可以按照不同优先级来组织。另外,也可以把优先级高的进程排在更靠近队头的位置

根据优先级是否可以动态改变,可将优先级分为静态优先级和动态优先级两种。

  • 静态优先级:创建进程时确定,之后一直不变。
  • 动态优先级:创建进程时有一个初始值,之后会根据情况动态地调整优先级。

思考

  1. 如何合理地设置各类进程的优先级?
    1. 通常:系统进程优先级高于用户进程,前台进程优先级高于后台进程,操作系统更偏好I/O型进程(或称I/O繁忙型进程) 注:与I/O型进程相对的是计算型进程(或称CPU繁忙型进程)
    2. 【I/O设备和CPU可以并行工作。如果优先让:I/O繁忙型进程优先运行的话,则越有可能让:I/O设备尽早地投入工作,则资源利用率、系统吞吐量都会得到提升】
  2. 如果采用的是动态优先级,什么时候应该调整?
    1. 可以从追求公平、提升资源利用率等角度考虑
    2. 如果某进程在就绪队列中等待了很长时间,则可以适当提升其优先级
    3. 如果某进程占用处理机运行了很长时间,则可适当降低其优先级
    4. 如果发现一个进程频繁地进行I/0操作,则可适当提升其优先级

9、多级反馈队列调度算法【重点】

9.1、上面三种算法评价

  • FCFS算法的优点是公平
  • SJF算法的优点是能尽快处理完短作业,平均等待/周转时间等参数很优秀
  • 时间片轮转调度算法可以让各个进程得到及时的响应
  • 优先级调度算法可以灵活地调整各种进程被服务的机会
  • 能否对其他算法做个折中权衡?得到一个综合表现优秀平衡的算法呢?
  • 多级反馈队列调度算法

9.2、多级反馈队列调度算法

9.2.1、概述

  • 算法思想:对其他调度算法的折中权衡

  • 算法规则

    • 设置多级就绪队列,各级队列优先级从高到低,时间片从小到大
    • 新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。
    • 如果此时已经是在最下级的队列,则重新放回该队列队尾
    1. 只有第k级队列为空时,才会为k+1级队头的进程分配时间片
  • 用于作业/进程调度:用于进程调度。

  • 是否可抢占?抢占式的算法。在k级队列的进程运行过程中,若更上级的队列(1~k-1级)中进入了一个新进程,则由于新进程处于优先级更高的队列中,因此新进程会抢占处理机,原来运行的进程放回k级队列队尾。

  • 优缺点

    • 对各类型进程相对公平(FCFS的优点) ;
    • 每个新到达的进程都可以很快就得到响应(RR的优点);
    • 短进程只用较少的时间就可完成(SPF的优点) ;
    • 不必实现估计进程的运行时间(避免用户作假) ;
    • 可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/O密集型进程(拓展:可以将因I/O而阻塞的进程重新放回原队列,这样I/O型进程就可以保持较高优先级)
  • 是否会导致饥饿(某进程/作业长期得不到服务):会

9.2.2、算法原理

多级反馈队列调度( multilevel fedback queue schduling )算法采用多就绪队列结构,如图所示。多个就绪队列是这样组织的:每个就绪队列的优先级按序递减,而时间片的长度则按序递增。亦即处于序数较小的就绪队列中的就绪进程的优先级要比处于序数较大的队列中的就绪进程的优先级高,但它获得的CPU时间片要比后者短。对于每个具有一定优先级的就绪队列中的进程则以先后次序排列。

image.png

进程从等待状态进入就绪队列时,首先进人序数较小的队列中;当某进程分到处理机时,就给它一个与就绪队列对应的时间片;该时间片用完时,它被迫释放处理机,并进入到下一级(序数增加1,对应时间片也增加1倍)的就绪队列中:虽然它重新执行的时间被推迟了一些,但在下次得到处理机时,时间片却增加了倍;当处于最大的序数就绪队列时,时间片可以无限大,即一旦分得处理机就一直运行结束。

当CPU空闲时,首先从序号最小的就绪队列查找,取队列首元素去运行,若该就绪队列为空,则从字号递增的下一个就绪队列选进程运行。如此类推,序号最大的就绪队列中的进程只有在其上所有队列都为空时,才有机会被调度。

由此可见,这种算法可以先用较小的时间片处理完那些用时较短的进程,而给那些用时较长的进程分配较大的时间片,以免较长的进程频繁被中断而影响处理机的效率。

多级反馈队列调度是较通用的CPU调度算法,但它也是较复杂的算法。

9.2.3、举例

image.png

10、调度算法总结

image.png

注:比起早期的批处理操作系统来说,由于计算机造价大幅降低,因此之后出现的交互式操作系统(包括分时操作系统、实时操作系统等)更注重系统的响应时间、公平性、平衡性等指标。而这几种算法恰好也能较好地满足交互式系统的需求。因此这三种算法适合用于交互式系统。( 比如UNIX使用的就是多级反馈队列调度算法)


 

1. 实验目的 调度的实质是操作系统按照某种预定的策略来分配资源。进程调度的目的是分配CPU资源。由于进程调度程序执行的频率很高,因此调度算法的好坏直接影响到操作系统的性能。本实验的目的是编程模拟实现几种常用的进程调度算法,通过对几组进程分别使用不同的调度算法,计算进程的平均周转时间和平均带权周转时间,比较各种算法的性能优劣。 2. 实验原理 [1]. 进程调度算法描述 进程调度算法包括先来先服务调度算法、最短作业时间优先(抢占抢占)、最高响应比调度算法4种。(每个人必须做FCFS,然后在后面的三种中任选一种,即每个人必须做2种调度算法的模拟。) [2]. 衡量算法性能的参数 计算进程的平均周转时间和平均带权周转时间。 3. 实验内容 (1)编程实现本实验的程序,要求: [1]. 建立进程的进程控制块,进程控制块至少包括: a) 进程名称; b) 进程需要执行时间; c) 进入就绪队列时间; d) 进程执行开始时间 e) 进程执行结束时间 [2]. 编程实现调度算法。 [3]. 进程及相关信息的输入。这些信息可以直接从键盘上输入,也可以从文件读取。 [4]. 时间片与时间流逝的模拟。本实验需要对算法的执行计时,程序应该提供计算时间的方法。一种最简单的方法是使用键盘,比如每敲一次空格代表一个时间片的流逝。另一种方法是使用系统时钟。 [5]. 一组进程序列执行完毕,打印出结果信息。程序需要计算出每个进程的开始执行时间、结束时间、周转时间和带权周转时间,并为整个进程序列计算平均周转时间和平均带权周转时间。程序将计算结果按一定的格显示在计算机屏幕上或输出到文件中。打印出进程调度顺序图。 [6]. 实现数据在磁盘文件上的存取功能。 (2)对下列就绪进程序列分别使用上面的几种算法进行调度,计算每种算法下的平均周转时间和平均带权周转时间。 进程号 到达时间 要求执行时间 0 0 1 1 1 35 2 2 10 3 3 5 4 6 9 5 7 21 6 9 35 7 11 23 8 12 42 9 13 1 10 14 7 11 20 5 12 23 3 13 24 22 14 25 31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值