计算机系统大作业

(直接复制粘贴好像不带图片欸)

计算机系统

大作业

题 目 程序人生-Hello’s P2P
专 业 微电子
学   号 1182100212
班   级 1821201
学 生 胡聪    
指 导 教 师 史先俊

计算机科学与技术学院
2020年3月
摘 要

本文以一个C语言源程序hello.c为例,详细介绍了它由一个源代码预处理、编译、汇编、链接,加载运行,结束的过程。以此对计算机系统的运行机制进行了介绍,并包括了进程管理、内存管理、系统级I/O等内容。
关键词:计算机系统 P2P O2O C语言程序

(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)

目 录

第1章 概述 - 4 -
1.1 HELLO简介 - 4 -
1.2 环境与工具 - 4 -
1.3 中间结果 - 4 -
1.4 本章小结 - 4 -
第2章 预处理 - 5 -
2.1 预处理的概念与作用 - 5 -
2.2在UBUNTU下预处理的命令 - 5 -
2.3 HELLO的预处理结果解析 - 5 -
2.4 本章小结 - 5 -
第3章 编译 - 6 -
3.1 编译的概念与作用 - 6 -
3.2 在UBUNTU下编译的命令 - 6 -
3.3 HELLO的编译结果解析 - 6 -
3.4 本章小结 - 6 -
第4章 汇编 - 7 -
4.1 汇编的概念与作用 - 7 -
4.2 在UBUNTU下汇编的命令 - 7 -
4.3 可重定位目标ELF格式 - 7 -
4.4 HELLO.O的结果解析 - 7 -
4.5 本章小结 - 7 -
第5章 链接 - 8 -
5.1 链接的概念与作用 - 8 -
5.2 在UBUNTU下链接的命令 - 8 -
5.3 可执行目标文件HELLO的格式 - 8 -
5.4 HELLO的虚拟地址空间 - 8 -
5.5 链接的重定位过程分析 - 8 -
5.6 HELLO的执行流程 - 8 -
5.7 HELLO的动态链接分析 - 8 -
5.8 本章小结 - 9 -
第6章 HELLO进程管理 - 10 -
6.1 进程的概念与作用 - 10 -
6.2 简述壳SHELL-BASH的作用与处理流程 - 10 -
6.3 HELLO的FORK进程创建过程 - 10 -
6.4 HELLO的EXECVE过程 - 10 -
6.5 HELLO的进程执行 - 10 -
6.6 HELLO的异常与信号处理 - 10 -
6.7本章小结 - 10 -
第7章 HELLO的存储管理 - 11 -
7.1 HELLO的存储器地址空间 - 11 -
7.2 INTEL逻辑地址到线性地址的变换-段式管理 - 11 -
7.3 HELLO的线性地址到物理地址的变换-页式管理 - 11 -
7.4 TLB与四级页表支持下的VA到PA的变换 - 11 -
7.5 三级CACHE支持下的物理内存访问 - 11 -
7.6 HELLO进程FORK时的内存映射 - 11 -
7.7 HELLO进程EXECVE时的内存映射 - 11 -
7.8 缺页故障与缺页中断处理 - 11 -
7.9动态存储分配管理 - 11 -
7.10本章小结 - 12 -
第8章 HELLO的IO管理 - 13 -
8.1 LINUX的IO设备管理方法 - 13 -
8.2 简述UNIX IO接口及其函数 - 13 -
8.3 PRINTF的实现分析 - 13 -
8.4 GETCHAR的实现分析 - 13 -
8.5本章小结 - 13 -
结论 - 14 -
附件 - 15 -
参考文献 - 16 -

第1章 概述
1.1 Hello简介
P2P:(From Program to Process):从程序员所编写的C语言源程序,到经历预处理、编译、汇编、链接一系列过程得到可执行目标程序。
O2O:(From Zero-0 to Zero-0):
程序执行结束后,子进程被回收,相关内存被释放,系统恢复到原来的状态。

1.2 环境与工具
硬件环境:
X64 CPU;2GHz;2G RAM;256GHD Disk 以上
软件环境:
Windows10 64位;Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位;
开发与调试工具:
Visual Studio 2019 64位,gdb , edb , objdump , readelf

1.3 中间结果
hello.i:预处理后的文件
hello.s:编译后的文件
hello.o:汇编后的文件
hello.o_obj:hello.o的反汇编文件
hello_o.elf:hello.o的ELF文件格式
hello.txt:hello的反汇编文件
hello_o.txt:hello.o的反汇编文件
hello.elf:hello的ELF文件格式

1.4 本章小结
本章介绍了P2P,O2O的的概念,并对本文所使用的环境与工具及分析过程所生成的中间文件进行了介绍。
(第1章0.5分)

第2章 预处理
2.1 预处理的概念与作用
源程序经预处理器处理后由.c文件输出.i文件,是源程序翻译成可执行目标程序的第一步。作用有:
根据以字母#开头的命令,修改原始的C语言程序。(如:将宏定义进行删除替换,将头文件插入到程序文本中,根据条件编译指令#if,#else等进行操作的选择性执行等。

2.2在Ubuntu下预处理的命令
gcc -no-pie -fno-PIC -E hello.c -o hello.i

2.2.1Ubuntu下预处理的命令
2.3 Hello的预处理结果解析

预处理(cpp)根据以字母#开头的命令,修改原始的C程序,输出文件扩展名为.i的C语言程序。

2.3.1Hello的预处理结果解析
预处理结果main函数以外内容占据了文本文件的大部分内容。将程序调用的头文件插入了程序文本,包含了调用内容的位置。
2.4 本章小结
本章介绍了以一个hello程序为例介绍了预处理的概念与作用,在Ubuntu下预处理的命令,并展示了Hello的预处理结果。
第3章 编译
3.1 编译的概念与作用
概念:编译是指将一个由高级语言程序格式的文本文件通过词法分析,语法分析,语义分析并优化等步骤,翻译成一个执行相同操作的包含一个汇编语言程序的文本文件,将hello.i翻译成hello.s
作用:翻译出汇编语言程序,汇编语言是不同高级语言的不同编译器的通用的输出语言,为下一步操作做准备。

3.2 在Ubuntu下编译的命令
gcc -no-pie -fno-PIC -S hello.i -o hello.s

3.2.1Ubuntu下编译的命令
3.3 Hello的编译结果解析

3.3.1.hello的编译结果

3.3.1数据:
(1)常量:
数字常量直接使用,字符串常量储存在代码的前段,标记为.rodata, .text节,访问时通过间接寻址访问。
(2)变量
局部变量储存在堆栈区,通过基址寄存器和栈指针指示对其进行操作。
3.3.2赋值:通过mov来实现赋值操作,movq a,b, movl a,b将a的赋值给b

3.3.2.赋值操作
3.3.3算术运算:
通过加法器进行相加,减法器相减
代码中的操作如图所示;

3.3.3算术运算

3.3.4关系比较:
利用条件转移指令来实现程序中的>,<等关系比较:
条件转移指令前cmpl:a,b进行a与b的比较
文件中包括je:比较量相等时跳转,jle:小于等于时跳转
条件转移指令后是要跳转的命令所在的地址。
3.3.5函数操作:
调用函数的指令为call, ret结束函数运行,返回函数的返回值,或是调用exit结束函数执行。

3.3.4函数操作
上图主函数中进行了参数传递,函数参数储存在寄存器中。
3.4 本章小结

本章介绍了编译的概念与作用,Ubuntu下编译的命令,以hello.s为例,介绍了汇编语言中常量变量的操作,函数参数的调用以及如何按表达式进行操作。

第4章 汇编
4.1 汇编的概念与作用
汇编器将hello.s中的指令进一步翻译成机器语言指令,将指令打包为可重定位目标文件,结果保存在一个二进制文件hello.o中,这一过程成为汇编。
作用:把汇编语言翻译为机器语言,得到机器可以分析的机器语言指令。
4.2 在Ubuntu下汇编的命令
gcc -no-pie -fno-PIC -c hello.s -o hello.o

4.2.1Ubuntu下汇编的命令
4.3 可重定位目标elf格式
hello.o的ELF格式:
用readelf等列出其各节的基本信息,特别是重定位项目分析。

4.3.1.生成hello.o的ELF格式
ELF头:

节头表:

重定位节:

4.4 Hello.o的结果解析
objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。

说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等
hello.s中的操作数是10进制形式,而hello.o的反汇编中是16进制形式。
函数调用:hello.s中call后跟函数名进行函数调用,而反汇编中通过main+地址偏移量
分支转移函数调用过程中:反汇编代码中使用的是相对地址值,hello.s使用的是字符表示。
4.5 本章小结
本章介绍了汇编的概念与作用,在Ubuntu下汇编的指令,分析了hello.o的ELF格式,并通过objdump对hello.o进行反汇编来分析hello.o的结果,同时与hello.s进行了对照分析。

第5章 链接
5.1 链接的概念与作用
注意:这儿的链接是指从 hello.o 到hello生成过程。
概念:链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。链接可执行于编译时,也就是源代码被翻译成机器代码时;也可以执行于加载时,也就是程序被加载器加载到内存并执行时,甚至执行于运算时,也就是由应用程序来执行。
作用:使文件可被加载到内存中并执行,使分离编译成为可能。
5.2 在Ubuntu下链接的命令

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbegin.o hello.o -lc /usr/lib/gcc/x86_64-linux-gnu/8/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o -z relro -o hello

5.2.1.Ubuntu下链接的命令

5.3 可执行目标文件hello的格式
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。

5.3.1生成hello的ELF格式文件

ELF头:

节头:

程序头:

符号表:

重定位节:

5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
下图为虚拟地址空间,对应于5.3中代码段

5.5 链接的重定位过程分析
objdump -d -r hello

分析hello与hello.o的不同,说明链接的过程,
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
hello与hello.s相比增加了许多节,函数数目也增加了。hello中代码前地址为虚拟地址,hello.o为相对偏移地址。
5.6 hello的执行流程
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。
main函数前:
_start
_libc_start_main
_cxa_atexit
_libc_csu_init
_setjmp

main
main函数后:
puts@plt
puts
exit@plt

5.7 Hello的动态链接分析

分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变化。要截图标识说明。
dl_init前:

该部分采取了延迟绑定,dl_init执行前,GOT保存下一命令的地址。dl_init执行后,重定位确定函数地址。

5.8 本章小结
本章介绍了链接的概念与作用,在Ubuntu下链接的指令,用readelf分析了hello的ELF格式,分析了hello的虚拟地址空间,链接的重定位过程,用edb调试分析了hello的执行流程与dl_init前后动态链接项目内容的变化。
(第5章1分)

第6章 hello进程管理
6.1 进程的概念与作用
概念:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。
作用:提供一个假象,程序彷佛独占处理器与内存。
6.2 简述壳Shell-bash的作用与处理流程
Shell是一种脚本语言,是操作系统(内核)与用户之间的桥梁,充当命令解释器的作用,将用户输入的命令翻译给系统执行。
处理流程:
1.Shell首先从命令行中找出特殊字符(元字符),在将元字符翻译成间隔符号。元字符将命令行划分成小块tokens。Shell中的元字符如下所示:
SPACE , TAB , NEWLINE , & , ; , ( , ) ,< , > , |
2. 程序块tokens被处理,检查看他们是否是shell中所引用到的关键字。
3. 当程序块tokens被确定以后,shell根据aliases文件中的列表来检查命令的第一个单词。如果这个单词出现在aliases表中,执行替换操作并且处理过程回到第一步重新分割程序块tokens。
4.Shell对~符号进行替换。
5.Shell对所有前面带有 符 号 的 变 量 进 行 替 换 。 6 . S h e l l 将 命 令 行 中 的 内 嵌 命 令 表 达 式 替 换 成 命 令 ; 他 们 一 般 都 采 用 符号的变量进行替换。 6.Shell将命令行中的内嵌命令表达式替换成命令;他们一般都采用 6Shell(command)标记法。
7.Shell计算采用$(expression)标记的算术表达式。
8.Shell将命令字符串重新划分为新的块tokens。这次划分的依据是栏位分割符号,称为IFS。缺省的IFS变量包含有:SPACE , TAB 和换行符号。
9.Shell执行通配符* ? [ ]的替换。
10.shell把所有预处理的结果中用到的注释删除,并且按照下面的顺序实行命令的检查:
A. 内建的命令
B. shell函数(由用户自己定义的)
C. 可执行的脚本文件(需要寻找文件和PATH路径)
11.在执行前的最后一步是初始化所有的输入输出重定向。
12.最后,执行命令

6.3 Hello的fork进程创建过程
父进程通过调用fork函数创建一个新的运行的子进程
int fork(void)
子进程返回0,父进程返回子进程的PID
新创建的子进程几乎但不完全与父进程相同:子进程得到与父进程虚拟地址空间相同的(但是独立的)一份副本(代码、数据段、堆、共享库以及用户栈),子进程获得与父进程任何打开文件描述符相同的副本,子进程有不同于父进程的PID。
fork函数:被调用一次,却返回两次
6.4 Hello的execve过程
int execve(char *filename, char *argv[], char *envp[])
在当前进程中载入并运行程序:
filename:可执行文件。目标文件或脚本(用#!指明解释器,如 #!/bin/bash)
argv:参数列表,惯例:argv[0]==filename
envp:环境变量列表,“name=value” strings (e.g., USER=droh),getenv, setenv, unsetenv, printenv
Loader删除子进程现有的虚拟内存段,创建一组新的段(栈与堆初始化为0),并将虚拟地址空间中的页映射到可执行文件的页大小的片chunk,新的代码与数据段被初始化为可执行文件的内容,然后跳到_start。 除了一些头部信息实际没读文件,直到缺页中断
覆盖当前进程的代码、数据、栈
保留:有相同的PID,继承已打开的文件描述符和信号上下文
调用一次并从不返回,除非有错误,例如:指定的文件不存在
6.5 Hello的进程执行
任何给定的时间,系统中都有多个活动进程
但是,在单个内核上,一个时刻只能有一个进程执行
每个进程似乎完全拥有处理器和私有内存空间(的控制)
6.6 hello的异常与信号处理
(1)不停乱按,包括回车

将控制权转移到操作系统内核,进程发生了中断
(2)Ctrl-Z

指令停止执行
(3)Ctrl-C

指令停止执行
ps:

监视后台进程
jobs:

查看暂停的进程
pstree:

树状图显示所有进程
fg:

使停止的进程继续运行

Kill:强行杀死进程
6.7本章小结
本章介绍了进程的概念与作用,壳Shell-bash的作用与处理流程,Hello的fork进程创建过程,Hello的execve过程,Hello的进程执行与hello的异常与信号处理。
(第6章1分)

第7章 hello的存储管理
7.1 hello的存储器地址空间
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
逻辑地址是指由程序产生的和段相关的偏移地址部分。
线性地址是逻辑地址到物理地址变换之间的中间层,线性地址空间中的整数是连续的。
虚拟地址空间: N = 2n 个虚拟地址的集合 ===线性地址空间{0, 1, 2, 3, …, N-1}
物理地址:真实的地址空间

7.2 Intel逻辑地址到线性地址的变换-段式管理

	7.2.1.段选择符格式
Tl=0表示选择全局描述符,	Tl=0表示选择局部描述符。PRL用来定义当前程序段的特权等级,若PRL=00,则为第0级,是最高级的内核态,若PRL=11,则为第3级,是最低级的用户态。高13位的索引值用来确定当前使用的段描述符在描述表中的位置。

段选择符放在段寄存器中。
逻辑地址向线性变化的过程如图所示

                    7.2.2逻辑地址向线性地址变化的过程

被选中的段描述符先被送至描述符cache,每次从描述符cache中取32位段基址,与32位段内偏移量(有效地址)相加得到线性地址.
7.3 Hello的线性地址到物理地址的变换-页式管理

7.3.1线性地址向物理地址转换的过程
采取了两级页表的形式,线性地址由三个字段表示,分别为10位页目录索引(DIR),10位页表索引(PAGE),和12位页内偏移量(OFFSET)。页目录表和页表项格式如下图所示。

7.3.2页目录表和页表项格式
首先找到根据页目录表首地址找到页目录表,然后根据页目录索引找到对应的页目录项,根据页目录项中指出的基地址指出的页表首地址找到对应的页表,根据页表索引找到页表中的页表项,最后,将页表项中的20位基地址和线性地址中12位页内偏移地址组成32位物理地址。
7.4 TLB与四级页表支持下的VA到PA的变换
TLB是一个内存管理单元,用于改进虚拟地址到物理地址转换速度的缓存,里面存放记录了虚拟地址到物理地址的转换表页表文件。因而取数据不需要进行两次访问内存,查页表获得物理地址和取数据。

7.4.1.四级页表支持下的VA到PA的变换
36位VPN被划分为4个9位的片,每个片被用作一个页表的偏移量。CR3寄存器包含L1页表的物理地址,VPN1提供到一个L1 PTE的偏移量,这个PTE包含L2页表的基地址,依此类推。
7.5 三级Cache支持下的物理内存访问
得到地址后,三级Cache逐级访问以获取在内存上的地址。
7.6 hello进程fork时的内存映射
为fork被调用时位新进程创建虚拟内存,并创建当前进程的区域结构和页表的原样副本,两个进程中的每个页面都标记为只读,两个进程中的每个区域结构都标记为私有的写时复制。在新进程中返回时,新进程拥有与调用fork进程相同的虚拟内存,随后的写操作通过写时复制机制创建新页面。
7.7 hello进程execve时的内存映射
Exerve执行了删除已存在的用户区域,创建新的区域结构,共享对象由动态链接映射到本进程共享区域,设置PC,指向代码区域的入口点等操作。
7.8 缺页故障与缺页中断处理
缺页导致页面出错 (缺页异常)时,缺页异常处理程序选择一个牺牲页,该页表储存相应信息后导致缺页的指令重新启动, 页面即命中。
7.9动态存储分配管理
动态内存分配器维护着一个进程的虚拟内存区域,称为堆。分配器将堆视为一组大小不同的块的集合来维护,每个块就是一个连续的虚拟内存片,要么是已分配的,要么是空闲的,空闲块可用于分配,已分配的块显式地保留供应用程序使用。
7.10本章小结
本章介绍了hello的存储管理,包括存储器地址空间,Intel逻辑地址到线性地址的变换-段式管理,TLB与四级页表支持下的VA到PA的变换,三级Cache支持下的物理内存访问,hello进程时fork,exerve的内存映射, 缺页故障与缺页中断处理,动态存储管理。
(第7章 2分)

第8章 hello的IO管理
8.1 Linux的IO设备管理方法
设备的模型化:文件
设备管理:unix io接口,
所有设备都被模型化为文件,所有的输入输出都能以一致的被当作对相应文件的读和写来执行。
8.2 简述Unix IO接口及其函数
这种将设备优雅地映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix I/O。
open():
返回一个小的描述符数字---- 文件描述符。返回的描述符总是在进程中当前没有打开的最小描述符。
close():
关闭文件是通知内核你要结束访问一个文件
read():
读文件从当前文件位置复制字节到内存位置,然后更新文件位置
Write():
写文件从内存复制字节到当前文件位置,然后更新文件位置. 返回值表示的是从内存向文件fd实际传送的字节数量
lseek():
改变当前的文件位置,指示文件要读写位置的偏移量
8.3 printf的实现分析

从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析

异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
本章介绍了hello的IO管理,主要包括Linux的IO设备管理方法,Unix IO接口及其函数,printf的实现分析,getchar的实现分析。
(第8章1分)

结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
编写后的hello.c文件,通过预处理得到hello.i文件,通过编译器编译得到hello.s文件,再通过汇编器汇编生成可重定位目标程序文件hello.o,最后通过链接器链接得到可执行目标程序hello。
运行时,在界面输入./hello, 父进程调用fork函数创建一个子进程,创建虚拟地址空间,接着通过execve函数的调用,映射到虚拟内存之中。程序开始运行,shell创建一个进程。程序执行过程中,若遇到异常,系统会对产生的错误进行处理。Hello通过系统级I/O在终端得到相应的输出。进程结束后,父进程将对子进程进行回收。

通过这学期计算机系统的学习,对程序产生执行结束的过程有了一定的了解。一段代码经历如此多的流程在我们面前的电脑上实现它的功能,也让我愈发感慨于计算机系统的精妙之处与人类智慧的结晶。

(结论0分,缺失 -1分,根据内容酌情加分)

附件
列出所有的中间产物的文件名,并予以说明起作用。
hello.i:预处理后的文件
hello.s:编译后的文件
hello.o:汇编后的文件
hello.o_obj:hello.o的反汇编文件
hello_o.elf:hello.o的ELF文件格式
hello.txt:hello的反汇编文件
hello_o.txt:hello.o的反汇编文件
hello.elf:hello的ELF文件格式
(附件0分,缺失 -1分)

参考文献
为完成本次大作业你翻阅的书籍与网站等
[1] 林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.
[2] 辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.
[3] 赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
[4] 谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.
[5] KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.
[6] CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.
(参考文献0分,缺失 -1分)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值