【Linux修炼之工具篇】——总结学习Linux系统一系列必不可少的工具(yum,vim,gcc/g++,gdb,make/makefile,git)

鸡汤来咯:

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

那些杀不死你的,终将使你变得更强大!!! 

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

目录

一:yum软件安装工具

1.1:yum是什么?

1.2:yum下载安装

1.3:使用yum安装一个小火车程序,"吹牛"程序

二:vim编辑工具

2.1:命令模式

2.2:底行模式(一定要含有 : )

2.3:如何配置适合自己的vim编辑器

三:gcc/g++编译工具

3.1:gcc如何完成编译

3.1.1:预处理

3.1.2:编译

3.1.3:汇编

3.1.4:链接

3.2:函数库的概念

3.3:.o文件和库的链接

3.3.1:动态链接和静态链接

 3.3.2:动态链接 VS 静态链接

四:gdb调式工具

4.1:背景

4.2:使用gdb

五:Make/Makefile工具

5.1:背景

5.2:Makefile

5.3:Make

5.4:特殊符号

六:编写第一个Linux程序:进度条

6.1:知识储备

6.2:进度条方法一

6.3:进度条方法二

6.4:进度条方法三(回调显示)

七:git代码上传工具

7.1:安装git

7.2:在Gitee创建项目

7.2.1:新建仓库

7.2.2:设置一些属性

7.2.3:克隆仓库到本地

7.3:使用Linux上传文件到Gitee项目(git三板斧)

7.3.1:git add '文件名'

7.3.2:git commit -m '用于介绍该文件'

7.3.3:git push 


一:yum软件安装工具

1.1:yum是什么?

        yum(全称为 Yellow dog Updater, Modified)是一个在 Fedora ,centos,BClinux,RedHat 以及 CentOS 中的 Shell 前端软件包管理器。基于 RPM 包管理 , 能够从指定的服务器自动下载 RPM 包并且安装 , 可以自动处理依赖性关系 , 并且一次安装所有依赖的软件包 , 无须繁琐地一次次下载、安装。

1.2:yum下载安装

在Linux中有三种安装软件的方式:

  1. 源代码安装
  2. rpm安装
  3. yum安装【强烈推荐】

在yum下载安装之前,我们先讲一个情况,在我们买的手机/ipad/电脑中都有一个系统自带的应用商店,通过应用商店,我们能下载各种各样的软件APP(例如抖音,王者荣耀,腾讯视频.....)。所以yum源就相当于在Linux中的”应用商店“。

所以:

  • 使用yum安装软件:yum install 安装包的名字
  • 使用yum卸载软件:yum remove安装包的名字

注意:安装和卸载软件都是使用的 root 用户账号!!!

那么,我们是怎么知道我们要安装哪些软件呢?【按需求】

即:安装软件之前先查看yum源的”类型“

输入:ll /etc/yum.repos.d/ 命令,查看yum 源的官方类型和扩展类型

所谓yum扩展类型就是,在yum官方中没有的软件。即在我们手机中的应用商店中总有那么一些软件是我们下载不了的,这些下载不了的软件只能在别的应用商店(非官方)中下载。所以,yum扩展类型就相当于别的应用商店。

即:官方yum[...Base...],扩展yum[...epel....]

非必要,我们就需要安装扩展yum来满足我们各种形式的需要

安装扩展yum源:yum install -y epel-release

1.3:使用yum安装一个小火车程序,"吹牛"程序

首先,在安装之前我们一定要下载 扩展yum源!!!

然后我们还需要知道小火车软件( sl 程序指令),”吹牛“软件(cowsay "吹牛" 程序指令)。

在我们没有下载两个程序软件之前,是没有任何动作的:

那么如何进行安装呢?=>

所有的软件都是要切换到 root 用户后安装的!!!

  1. 切换到 root 用户
  2. 安装 sl(小火车软件)—— yum install -y sl
  3. 安装 cowsay("吹牛"软件)—— yum install -y cowsay

1.切换到 root 用户

2.安装 sl(小火车软件)—— yum install -y sl

最后显示到 Complete! 则下载成功。

3.安装 cowsay("吹牛"软件)—— yum install -y cowsay

最后显示到 Complete! 则下载成功。

4、运行小火车,运行吹牛

直接输入 sl 命令,运行小火车:

输入 cowsay "你想输入的东西" ,运行吹牛:

二:vim编辑工具

vim编辑工具,所谓编辑,就是文本编写。通俗简单的来讲就是写文档、写代码的工具。

vim的含有主要的三种模式,分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:

命令模式(Normal mode)

  • 控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode
插入模式(Insert mode)
  • 只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。
末行模式(last line mode)
  • 文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入:help vim-modes 
  • 命令模式--->插入模式    输入 i/insert
  • 插入模式--->命令模式    输入 esc
  • 命令模式--->底行模式    输入 : ...
  • 底行模式--->命令模式    输入 esc

首先创建两个文件,并在文件内写入内容:

2.1:命令模式

命令模式是vim的默认模式。在该模式下,用户所有的输入都会被当作命令,一般不会给你作为文本输入。

文本编辑上下操作:
gg              定位光标到最开始行
shift+g         定位光标到最末尾行
n+shift+g(nG)   定位光标到任意指定行

文本编辑复制粘贴操作:
(n)yy           复制光标所在(n)行
(n)p            粘贴(n)复制行,光标所在的下一行
u               撤销
(n)dd           (多行)剪切

文本编辑左右操作:
shift+$         定位光标到当前行末尾
shift+^         定位光标到当前行开始
w,b             进行单行/多行,来进行以单词为单位的前后移动
h,j,k,l         左,下,上,右移动

文本编辑字符替换操作:
shift+~         小写字符与大写字符的相互转换
(n)r+字符       对光标字符之后的n个字符进行批量化替换
shift+r         批量化替换模式                                                                              
(n)x            对光标字符之后的字符进行删除

2.2:底行模式(一定要含有 : )

分屏:
: vs code.c     分屏打开名为code.c的文件
ctrl+ww         进行分屏切换

底行输入指令:
:wq             保存退出
:w!             强制保存
:q!             强制退出
:! gcc code.c   可以执行外部命令(编译code.c文件)
:/main          搜索 main 单词的位置
:set nu         调出行号
:set nonu       取消行号
:syntax on      设置语法高亮

2.3:如何配置适合自己的vim编辑器

手动配置自己的vim编辑工具:
在家目录下:创建 .vimrc 隐藏文件,在该文件内部输入需要配置的命令(eg:set nu),保存退出,之后的vim编辑器一打开就有行号。

一定要在家目录下!!!

配置网上的vim编辑工具:

在网上找到vim配置的网址,然后直接复制粘贴到命令行中。

注意:
最好一个用户一个vim配置文件,用户与用户之间不会相互影响。不建议给root用户做配置,改用普通用户配置。

三:gcc/g++编译工具

背景知识:

  • 预处理(进行宏替换)
  • 编译(生成汇编)
  • 汇编(生成机器可识别代码)
  • 链接(生成可执行文件或库文件)

3.1:gcc如何完成编译

首先创建一个mycode.cC语言文件,写入代码内容:

3.1.1:预处理

功能:1.将注释去掉;2.头文件展开;3.条件编译;4.宏替换

即:生成一个预处理文件(一份干净的代码,.i文件)

命令gcc -E mycode.c -o mycode.i

-o mycode.i:自定义命名,即将生成的文件命名为mycode.i

-E:告诉gcc,从现在开始进行程序的翻译,将预处理工作做完就停下来,不要再往后走了!!

 生成mycode.i文件:

vim mycode.i 查看mycode.i文件内容:

3.1.2:编译

功能:生成汇编语言

即:生成一个汇编文件

命令:gcc -S mycode.c(mycode.i也可以) -o mycode.s

-S:告诉gcc,从现在开始进行程序的翻译,将编译工作做完就停下来!!!

  生成mycode.s文件:

 vim mycode.s 查看mycode.s文件内容:看到内部全部都是汇编指令

3.1.3:汇编

功能:机器可识别代码,二进制代码

命令:gcc -c mycode.c(mycode.s也可以) -o mycode.o
-c:从现在开始进行程序的翻译,将汇编工作做完就停下来!!!

 vim mycode.o 查看mycode.o文件内容:看到内部全部都是二进制代码

3.1.4:链接

功能:生成可执行程序或库文件

命令:gcc mycode.c(mycode.o也可以) -o mycode.exe
链接过程,生成可执行文件。将可重定位目标二进制文件和库进行链接生成可执行文件!!!

 运行mycode.exe可执行文件:

3.2:函数库的概念

在上述链接,生成可执行文件的过程中。将可重定位目标二进制文件和进行链接生成可执行文件。

所谓库,库给我们提供方法的实现。

例如Linux中的C标准库(ll /usr/lib64/libc.so*),即库本身就是一个文件,有自己的格式,有路径。

 格式:

  • Linux中:后缀 .so(动态库)    .a(静态库)
  • Windows中:后缀 .dll(动态库)   .lib(静态库)

注意:库是有自己的命名规则的:eg:Linux动态库:libname.so.XXX [name表明该库的特征],而且我们Linux机器上,默认只会安装动态库,静态库默认是没有安装的。

所以:即编译型语言(例如Vs2019,Vscode等编译软件),下载过程中,安装安装包时,必定是下载安装对应的头文件+库文件。

总结:

  • 方法的实现就是在库当中!!!
  • 库其实就是把源文件(.c文件)经过一定的编译、打包。只给你提供一个文件即可,不用给你太多的源文件,也可达到隐藏源文件的目的
  • 头文件提供方法的声明 + 库文件提供方法的实现 + 自己的代码 = 自己的软件

3.3:.o文件和库的链接

3.3.1:动态链接和静态链接

链接分为动态链接 和 静态链接

理解小故事:

  • 动态链接:“我”假期实现一系列计划过程中,中间有上网这一计划,就跑到学校附近的网吧玩电脑
  • 静态链接:“我”假期实现一系列计划过程中,中间上有网这一计划,直接在宿舍玩电脑(不在去往网吧玩游戏电脑了)。

即,动态链接,需要”跑“到别的地方去实现库函数;静态链接就是将相应的库函数复制粘贴到你写的代码中。

因为 ”网吧中的电脑不仅仅是一个学生玩,是有多个学生玩的“,所以动态库不能缺失,一旦对应的动态库缺失,影响的不仅仅是一个程序,可能导致很多程序都无法进行正常运行。

ldd指令:查看可执行程序所用到的库(eg:ldd mycode.exe)

静态库:在编译器在使用静态库进行静态链接时,会将需要用到的库资源拷贝到目标程序中,并不是将静态库中所有的资源    都拷贝到目标程序中。

实操验证静态链接和动态链接:
动态链接:
gcc mycode.c -o mycode.exe
ldd mycode.exe
在Linux中,编译形成的可执行程序,默认采用的是动态链接(提供动态库)
静态链接:
gcc mycode.c -o mycode_static.exe -static
ldd mycode_static.exe
在Linux中,如果按照静态链接的方式,形成可执行程序,需要添加static选项(提供静态库),static选项本质(改变优先级)

并且可以明显发现使用静态库生成的可执行文件比使用动态库生成的可执行文件要大得多!!!

默认情况下,Linux系统中是没有静态库的:

安装静态库:

  • C静态库:yum install -y glibc-static
  • CPP静态库:yum install -y libstdc++-static

file 指令

除了ldd指令查看动静态库,file指令也可查看可执行程序是静态/动态链接。

 3.3.2:动态链接 VS 静态链接

动态链接:
优:是共享库,有效的节省资源(磁盘空间、内存空间、网络空间等)
缺:动态库一旦缺失,导致各个程序都无法运行
静态链接:
优:不依赖库,程序可以独立运行
缺:体积大,比较消耗资源

四:gdb调式工具

4.1:背景

程序的发布方式有两种,debug模式和release模式

  • debug:能被调试,形成可执行程序的时候会有调试信息
  • release:不能被调试,没有调试信息

Linux gcc/g++出来的二进制程序,默认是release模式(即:不能被调试)

要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项【eg:gcc mycode.c -o mycode-debug.exe -g】

4.2:使用gdb

gdb mycode-debug.exe:开始调试

先查看 mycode.c 文件中的代码

 gdb调试命令:

  • list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
  • list/l 函数名:列出某个函数的源代码。
  • r或run:运行程序。
  • n 或 next:单条执行。(类似于F10)
  • s或step:进入函数调用(类似于F11)
  • break(b) 行号:在某一行设置断点
  • break 函数名:在某个函数开头设置断点
  • info break :查看断点信息。
  • finish:执行到当前函数返回,然后挺下来等待命令
  • print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
  • p 变量:打印变量值。
  • set var:修改变量的值
  • continue(或c):从当前位置开始连续而非单步执行程序
  • run(或r):从开始连续而非单步执行程序
  • delete breakpoints:删除所有断点
  • delete breakpoints n:删除序号为n的断点
  • disable breakpoints:禁用断点
  • enable breakpoints:启用断点
  • info(或i) breakpoints:参看当前设置了哪些断点
  • display 变量名:跟踪查看一个变量,每次停下来都显示它的值
  • undisplay:取消对先前设置的那些变量的跟踪
  • until X行号:跳至X行
  • breaktrace(或bt):查看各级函数调用及参数
  • info(i) locals:查看当前栈帧局部变量的值
  • quit:退出gdb

五:Make/Makefile工具

Make:是一条指令

Makefile:是一个当前目录下的文件(需要自己touch Makefile)

5.1:背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

5.2:Makefile

首先创建一个mycode.c文件,在.c文件内写一系列代码:

其次,创建一个makefile文本文件

 在makefile 文本文件内部:

其中,mycode:mycode.c【依赖关系,即 目标文件:依赖文件】

gcc mycode.c -o mycode.exe【依赖方法,即根据依赖关系要生成的命令】

.PHONY【伪目标】,作用是总是可执行

clean【依赖关系为空】,使用时,输入 make clean ,执行依赖方法

5.3:Make

make会自顶向下进行扫描,并会默认第一个依赖关系(make:直接执行该依赖关系的依赖方法)

直接输入 make:

输入 make clean【清理】:

5.4:特殊符号

特殊符号:

$@:代表依赖关系的目标文件

$^:代表依赖关系的依赖文件

@:输出make/make clean 时,不回显内容,前面加@

 vim 编辑makefile

 测试:

 make run :输出不回显

 make clean:输出回显

六:编写第一个Linux程序:进度条

6.1:知识储备

  • 回车('\r')      换行('\n')
  • 缓冲区        [清空缓冲区:fflush(stdout)],作用:强制刷新缓冲区。没有 '\n',就是没有立即刷新,因为显示器默认模式是行刷新。                 
  • sleep         暂停/休眠,头文件(unistd.h)

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

颜色输入:

  • #define COLOR "\033[0/1;30-40m"        0/1(0或者1);30-40(30到40之间)
  • #define NONE "\033[0m"                        退出颜色

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

旋转光标:

  • | / - \ 的顺时针顺序依次旋转

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

成果显示:

首先创建三个文件:main.c,processBar.c,processBar.h

main.c 文件写主函数

processBar.h 文件写进度条函数的声明

processBar.c 文件写进度条函数的实现 

6.2:进度条方法一

main.c 文件:

#include "processBar.h"

// 实现一个进度条

// 方法一:
int main()
{
    Processbar();

    return 0;
}

processBar.h 文件:

#pragma once                                             
// 实现一个进度条                                                               
                                                        
#include<stdio.h>                                                         
#include<unistd.h>  //usleep                                
#include<string.h>                                       
                                                                    
#define TOP 100                                                      
#define NUM 102                                             
#define STYLE '='                                                             
#define RIGHT '>'                                                                
                                                                       
#define COLOR1 "\033[0;31m"                                 
#define COLOR2 "\033[0;32m"                              
#define COLOR3 "\033[0;33m"                              
#define COLOR4 "\033[0;34m"                                      
 #define NONE "\033[0m"                                                           
                                                                     
// 声明                                                     
extern void Processbar();

processBar.c 文件:

 // 实现一个进度条

#include"processBar.h"

char bar[102] = {0};
const char *lable = "|/-\\";        // 顺时针旋转
 
void Processbar()
{
    int cnt = 0;
    int len = strlen(lable);

    while( cnt <= 100)
    {
        printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);    // '\r':回车不换行
        
        fflush(stdout);        // 强制刷新缓冲区
        bar[cnt++] = STYLE;
        if(cnt < 100)     bar[cnt] = RIGHT;            // 代表'>'
        usleep(50000);        // “休眠”50000纳秒(50微秒)(0.05秒)
     }
    printf("\n");
 }

6.3:进度条方法二

main.c 文件:

 // 实现一个进度条

#include"processBar.h"
 //方法二
//看进度条是如何被调用的

int main()
{
    int total = 1000;    // 1000MB
	int curr = 0;        //0MB

    while(curr <= total)
    {
        Processbar_sigle(curr*100/total);
        
        curr += 10;
        usleep(50000);
    }
    printf("\n");                                                     
    return 0;                                     
} 

processBar.h 文件:

#pragma once                                             
// 实现一个进度条                                                               
                                                        
#include<stdio.h>                                                         
#include<unistd.h>  //usleep                                
#include<string.h>                                       
                                                                    
#define TOP 100                                                      
#define NUM 102                                             
#define STYLE '='                                                             
#define RIGHT '>'                                                                
                                                                       
#define COLOR1 "\033[0;31m"                                 
#define COLOR2 "\033[0;32m"                              
#define COLOR3 "\033[0;33m"                              
#define COLOR4 "\033[0;34m"                                      
 #define NONE "\033[0m" 

//方法二                                                        
//单次进度                                                                  
extern  void Processbar_sigle(int rate); 

processBar.c 文件:

#include"processBar.h"

char bar[102] = {0};
const char *lable = "|/-\\";

//方法二
//单次进度调用
 
void Processbar_sigle(int rate)
{
    if(rate < 0 || rate > 100)
        return;
    int len = strlen(lable);
    printf("[%-100s][%d%%][%c]\r",bar,rate,lable[rate%len]);
    fflush(stdout);
    bar[rate++] = STYLE;
    if(rate < 100)  bar[rate] = RIGHT;
}  

6.4:进度条方法三(回调显示)

main.c 文件:

#include "processBar.h"

//方法三
//回调显示
typedef void (*callback_t)(int,int);
void DownLoad(callback_t cb,int color)
{
    int total = 1000;
    int curr = 0;
    while(curr <= total)
    {
        //进行某种下载任务
        usleep(50000);
        int rate = curr*100/total;
        cb(rate,color);
        curr += 10;
    }
    printf("\n");
}

int main()
{
    printf("下载任务:1\n");
    DownLoad(Processbar_sigle,31);    //31:确定颜色的类型
    InitBar();

    printf("下载任务:2\n");
    DownLoad(Processbar_sigle,32);
    InitBar();

    printf("下载任务:3\n");
    DownLoad(Processbar_sigle,33);
    InitBar();

    printf("下载任务:4\n");
    DownLoad(Processbar_sigle,34);
    InitBar();
    return 0;
}

processBar.h 文件:

#pragma once
// 实现一个进度条

#include<stdio.h>
#include<unistd.h>  //usleep
#include<string.h>

#define TOP 100
#define NUM 102
#define STYLE '='
#define RIGHT '>'

#define COLOR1 "\033[0;31m"
#define COLOR2 "\033[0;32m"
#define COLOR3 "\033[0;33m"
#define COLOR4 "\033[0;34m"
#define NONE "\033[0m"


extern void Processbar_sigle(int rate, int color);
void InitBar();

processBar.c 文件:

#include"processBar.h"

char bar[102] = {0};
const char *lable = "|/-\\";

void Processbar_sigle(int rate, int color)
{
    if(rate < 0 || rate > 100)
        return;
    int len = strlen(lable);
    switch(color)
    {
        case 31:
            printf(COLOR1"[%-100s]"NONE"[%d%%][%c]\r",bar,rate,lable[rate%len]);
            break;
        case 32:
            printf(COLOR2"[%-100s]"NONE"[%d%%][%c]\r",bar,rate,lable[rate%len]);
            break;
        case 33:
            printf(COLOR3"[%-100s]"NONE"[%d%%][%c]\r",bar,rate,lable[rate%len]);
            break;
        case 34:
            printf(COLOR4"[%-100s]"NONE"[%d%%][%c]\r",bar,rate,lable[rate%len]);
            break;
    }
    fflush(stdout);
    bar[rate++] = STYLE;
    if(rate < 100)  bar[rate] = RIGHT;
}


void InitBar()
{
    memset(bar, '\0', sizeof(bar));
}

七:git代码上传工具

Git大概:

git如何使用?=>
1.新建仓库
2.克隆下载,取上某网地址
3.将仓库拉去到本地
    3.1-确定是否安装git?=>git --help,yum install git
    3.2-克隆:git clone 2步骤取得网地址
    3.3-将目标文件上传到远端仓库
        3.3.1-git add filename
        3.3.2-git commit -m '提交日志'
        3.3.3-git push

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

git的其他问题:
git log     查看git的历史提交记录
git status  查看git的提交状态
隐藏文件(.gitignore):凡是在该隐藏文件中的各种后缀,添加时就不会加入到远端仓库中【注意:在该文件内部进行修改时,要注意最前面的 * 】

第一次使用git是,首次使用需要配置邮箱和用户名
Run:
    git config --global user.email"-------@qq.com"
    git config --global user.name"阿林"

7.1:安装git

切换到root用户来安装git

因为我的已经下载好了,所以什么都不做

7.2:在Gitee创建项目

7.2.1:新建仓库

7.2.2:设置一些属性

7.2.3:克隆仓库到本地

创建仓库后进入到该页面,此为该仓库的主页面。之后点击克隆/下载

上述四个文件是默认有的 

复制该“网址”:

输入 git clone “网址 ”

克隆成功:

7.3:使用Linux上传文件到Gitee项目(git三板斧)

克隆玩成功后,该目录下会有一个名为 temp 的文件夹

 进入该目录默认带有四个文件,其中一个以 . 开头的是隐藏文件,在该目录下创建一个内容为 hello world 的文本文件

将该文件上传到远端仓库中,三板斧:

7.3.1:git add '文件名'

7.3.2:git commit -m '用于介绍该文件'

7.3.3:git push 

第一次使用git时,首次使用需要配置邮箱和用户名

  • git config --global user.email"your email.com"
  • git config --global user.name"your name"

之后输入密码或者账号,显示该页面即为提交成功!!!

刷新远端仓库:

显示有 test.txt 文件,即上传远端仓库成功。 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值