湘潭大学 操作系统 调度算法 FCFS SSTF SCAN SJF OPT LRU

首先!

这个有bug,很多,我不会再改了。。因为已经忘干净了。。。

调度算法:

#include <stdio.h>
#include <stdlib.h>
typedef struct TEST
{
	char name[20];	//作业名
	int cometime;	//到达时间
	int servicetime;//服务时间
	int starttime;	//开始时间
	int endtime;	//结束时间
	int zztime;		//周转时间
	double dqzztime;//带权周转时间
	int flag;		//是否被使用
	int runtime; 	//时间片算法已运行时间
}Test;

int System_time;	//系统时间

int cmp_servicetime(const void *a,const void *b)    //qsort排序 服务时间从小到大
{
	Test *c = (Test *)a;
	Test *d = (Test *)b;
	return c->servicetime - d->servicetime;
}

int cmp_cometime(const void *a,const void *b)    //qsort排序 到达时间从小到大
{
	Test *c = (Test *)a;
	Test *d = (Test *)b;
	return c->cometime - d->cometime;
}

int Get(Test test[])    //输入函数
{
	puts("请输入作业的数量");
	int ca;
	scanf("%d",&ca);

	int i;
	puts("作业 到达时间 服务时间");
	for(i=0;i<ca;i++)
	{
		scanf("%s %d %d",test[i].name,&test[i].cometime,&test[i].servicetime);
		test[i].flag = 0;	//重置为未使用状态
		test[i].runtime = 0;
	}
	return ca;
}

void Print(Test test[],int n)//输出函数
{
	int i,sum=0;
	double dq = 0.0;
	puts("作业 到达时间 服务时间 开始时间 完成时间 周转时间 带权周转时间");
	for(i=0;i<n;i++)
	{
	    sum += test[i].zztime;
	    dq += test[i].dqzztime;
        printf("%s %7d   %7d %7d  %7d  %7d      %.3f\n",test[i].name,test[i].cometime,test[i].servicetime,test[i].starttime,test[i].endtime,test[i].zztime,test[i].dqzztime);
    }
    printf("平均周转时间:%.2f\n",sum*1.0/n);
    printf("平均带权周转时间:%2f\n",dq*1.0/n);
}

void FIFO()	//先来先服务算法
{
	/*****FIFO先来先服务调度算法*****/
	Test test[100];
	puts("/*****FIFO先来先服务调度算法*****/");
	int ca = Get(test);			//输入作业的信息
	System_time = 0;			//重置系统时间
	int cnt = 1;				//计数器
	while(cnt <= ca)			//如果每进行ca个作业
	{
		if(System_time >= test[cnt-1].cometime)                 //如果系统时间内作业已到达
		{
		    test[cnt-1].starttime = System_time;                //开始时间就等于系统时间
			System_time += test[cnt-1].servicetime;             //系统时间走过服务时间完成作业
			test[cnt-1].endtime = System_time;                  //完成时间此时等于系统时间
			test[cnt-1].zztime = test[cnt-1].endtime - test[cnt-1].cometime;    //计算周转时间
			test[cnt-1].dqzztime = (test[cnt-1].zztime * 1.0) / test[cnt-1].servicetime;//计算带权周转时间
			cnt++ ;
		}
		else System_time = test[cnt-1].cometime;                //如果作业没到 等待作业到达
	}
	Print(test,ca);     //打印结果
	getchar();
}

void SJF()
{
    /*****SJF短作业优先调度算法*****/
	Test test[100];
	puts("/*****SJF短作业优先调度算法*****/");
	int ca = Get(test);			//输入作业的信息
	System_time = 0;			//重置系统时间
	int cnt = 1;                //重置计数器
	qsort(test,ca,sizeof(test[0]),cmp_servicetime);
	while(cnt <= ca)
    {
        int i;
    	for(i=0;i<ca;i++)		//找到到达时间满足的
    	{
    		if (test[i].cometime <= System_time && test[i].flag == 0)
    			break;
    	}
    	if(i<ca)
    	{
    		test[i].starttime = System_time;                //开始时间就等于系统时间
			System_time += test[i].servicetime;             //系统时间走过服务时间完成作业
			test[i].endtime = System_time;                  //完成时间此时等于系统时间
			test[i].zztime = test[i].endtime - test[i].cometime;    //计算周转时间
			test[i].dqzztime = (test[i].zztime * 1.0) / test[i].servicetime;//计算带权周转时间
			cnt++ ;
			test[i].flag = 1;       						//标记为已使用
    	}
    	else
    	{
    		int Min = 1e8,j;
    		for(j=0;j<ca;j++) 		//找到最短的到达时间的
	        {
	        	if(test[j].cometime <= Min && test[j].flag == 0)
	    		{
	    			Min = test[j].cometime;
	    		}
	        }
	        System_time += Min;
    	}
	}
	qsort(test,ca,sizeof(test[0]),cmp_cometime);
	Print(test,ca);
	getchar();
}

void SJP()
{
	/*****时间片轮转优先调度算法*****/
	Test test[100];
	puts("/*****时间片轮转优先调度算法*****/");
	int ca = Get(test);			//输入作业的信息
	System_time = 0;			//重置系统时间
	int cnt = 1;   				//重置计数器

	puts("输入时间片的大小");
	int sjp;
	scanf("%d",&sjp); 			//获取时间片的大小

	qsort(test,ca,sizeof(test[0]),cmp_cometime);	//对到达时间排序
	int sum_servicetime = 0;						//总服务时间

	int i;
	for(i=0;i<ca;i++) sum_servicetime += test[i].servicetime;	//总服务时间

	int run = 0;				//已运行时间
	while(sum_servicetime)
	{
		int j;
		for(j=0;j<ca;j++)
		{
			if(test[j].cometime <= System_time && test[j].flag == 0)	//如果在时间内到达且未完成
			{
				if(test[j].servicetime - test[j].runtime > sjp && test[j].flag == 0)	//如果服务时间剩余超过时间片大小且未完成
				{
				    printf("system time:%3d   选取%4d   运行时间 %3d\n",System_time,j,sjp);
				    if(test[j].runtime ==0) test[j].starttime = System_time;		//开始时间
					System_time += sjp;												//系统时间增加
					test[j].runtime += sjp;											//作业运行时间增加
					sum_servicetime -= sjp;											//剩余服务时间减少
				}
				else if (test[j].servicetime - test[j].runtime <= sjp && test[j].servicetime - test[j].runtime >= 0 && test[j].flag == 0)
				{
				    printf("system time:%3d   选取%4d   运行时间 %3d\n",System_time,j,test[j].servicetime - test[j].runtime);
				    if(test[j].runtime ==0) test[j].starttime = System_time;		//开始时间
					System_time += test[j].servicetime - test[j].runtime;			//系统时间增加
					test[j].endtime = System_time;									//结束时间
					sum_servicetime -= test[j].servicetime - test[j].runtime;		//剩余服务时间减少
					test[j].runtime = test[j].servicetime;							//运行时间增加
					test[j].flag = 1;												//标记为已完成
				}
			}
			else continue;
		}
	}
	for(i=0;i<ca;i++)	//计算周转时间和带权周转时间
    {
        test[i].zztime = test[i].endtime -test[i].cometime;
        test[i].dqzztime = test[i].zztime*1.0 / test[i].servicetime;
    }
	Print(test,ca);		//输出
    getchar();
}

int main()
{
	puts("欢迎进入调度算法程序");
	puts("1:FIFO先来先服务调度算法");
	puts("2:SJF短作业优先调度算法");
	puts("3:SJP时间片轮转算法");
	int n;
	while(1)
	{
		puts("\n\n请输入一个数字表示你要执行的程序,-1结束程序");
		scanf("%d",&n);
		if(n==-1)
        {
            puts("程序结束!");
            break;
        }
		switch (n)
		{
			case 1:{
				FIFO();
				break;
			}
			case 2:{
				SJF();
				break;
			}
			case 3:{
				SJP();
				break;
			}
			default :{
				puts("请输入合法的数字!");
				continue;
			}
		}

	}
	return 0;
}

 

页面置换算法:

#include <stdio.h>

typedef struct Pbd
{
	int num;		//页面走向
	int pb[100];	//物理块数
	int page;		//是否缺页
}PBD;

void GET(PBD pbd[],int pagenum)
{
	int i,j;
	for(i=0;i<100;i++)
		for(j=0;j<100;j++) pbd[i].pb[j] = 0;
    puts("请输入走向表");
	for(i=0;i<pagenum;i++)
	{
		scanf("%d",&pbd[i].num);
		pbd[i].page = 0;
	}
}

void Print(PBD pbd[],int pagenum,int phbnum)
{
	int i,j;
	printf("页面走向:");
	for(i=0;i<pagenum;i++) printf("%2d  ",pbd[i].num); printf("\n");
	for(i=0;i<phbnum;i++)
	{
		printf("物理块%d   ",i+1);
		for(j=0;j<pagenum;j++)
		{
			printf("%2d  ",pbd[j].pb[i]);
		}
		printf("\n");
	}
	int que = 0;
	printf("缺页中断:");
	for(i=0;i<pagenum;i++)
	{
	    if(pbd[i].page) que++;
		printf("%2d  ",pbd[i].page);
	}
	printf("\n");
	//此处加上缺页数和缺页率
	printf("缺页数:%3d\n缺页率:%.1f%%\n",que,que*100.0/pagenum);
}

void OPT()
{
	PBD pbd[100];
	puts("/*****OPT最佳置换算法*****/");
	puts("请输入页面数量、物理块数");
	int pagenum,phbnum;
	scanf("%d %d",&pagenum,&phbnum);	//页数  块数
	GET(pbd,pagenum);
	int cnt = 1,a=0;
	while(cnt <= phbnum)			//未占满块数的情况
	{
		int i,j;
		for(i=0;i<cnt;i++)
		{
			if (pbd[a].pb[i] == pbd[i].num) break;	//查看是否已存在
		}
		if(i<=cnt)
        {
			if(!a)
			{
				pbd[a].pb[a] = pbd[a].num;			//0位数组特殊处理
			}
			else
			{
				for(j=0;j<cnt-1;j++)
				{
					pbd[a].pb[j] = pbd[a-1].pb[j];	//赋值进去
				}
				pbd[a].pb[j] = pbd[a].num;			//放入空位
			}
			pbd[a].page = 1;						//缺页
			cnt++;
			a++;
		}
		else
        {											//若已存在 就不缺页
            for(j=0;j<cnt;j++)
            {
                pbd[a].pb[j] = pbd[a-1].pb[j];
            }
            pbd[a].pb[j] = pbd[a].num;
            a++;
        }
	}cnt--;
	int i,j;
	puts(" ");
	for(cnt;cnt<=pagenum;cnt++)			//占满的情况
	{
	    int use[100]={0};				//表示到后面的距离
		for(j = 0;j < phbnum; j++)
		{								//此处计算距离
			for(i=cnt;i<=pagenum;i++)
			{
				if(pbd[cnt-1].pb[j]==pbd[i].num) break;
			}
			use[j] = i;
		}
		int Max = 0;					//找最远的
		for(j=0;j<phbnum;j++)
		{
			if(use[Max] < use[j]) Max = j;
		}
		for(j=0;j<phbnum;j++)			//逐个放进去
		{
			pbd[cnt].pb[j] = pbd[cnt-1].pb[j];
		}
		int flag = 0;
		for(j=0;j<phbnum;j++)			//检查是不是已经存在
        {
            if(pbd[cnt].num == pbd[cnt-1].pb[j]) flag = 1;
        }
		if(!flag)						//不存在就放入
        {
            pbd[cnt].pb[Max] = pbd[cnt].num;
            pbd[cnt].page = 1;			//缺页
        }

	}
	Print(pbd,pagenum,phbnum);			//打印
}

void FIFO()
{
	PBD pbd[100];
	puts("/*****FIFO先进先出置换算法*****/");
	puts("请输入页面数量、物理块数");
	int pagenum,phbnum;
	scanf("%d %d",&pagenum,&phbnum);	//页数  块数
	GET(pbd,pagenum);
	int cnt = 1,a=0;
	while(cnt <= phbnum)			//未占满块数的情况
	{
		int i,j;
		for(i=0;i<cnt;i++)
		{
			if (pbd[a].pb[i] == pbd[i].num) break;	//查看是否已存在
		}
		if(i<=cnt)
        {
			if(!a)
			{
				pbd[a].pb[a] = pbd[a].num;			//0位数组特殊处理
			}
			else
			{
				for(j=0;j<cnt-1;j++)
				{
					pbd[a].pb[j] = pbd[a-1].pb[j];	//赋值进去
				}
				pbd[a].pb[j] = pbd[a].num;			//放入空位
			}
			pbd[a].page = 1;						//缺页
			cnt++;
			a++;
		}
		else
        {											//若已存在 就不缺页
            for(j=0;j<cnt;j++)
            {
                pbd[a].pb[j] = pbd[a-1].pb[j];
            }
            pbd[a].pb[j] = pbd[a].num;
            a++;
        }
	}cnt--;
	int i,j;
	puts(" ");
	for(cnt;cnt<=pagenum;cnt++)
	{
		int use[100]={0};				//表示到后面的距离
		for(j = 0;j < phbnum; j++)
		{								//此处计算距离
			for(i=0;i<=cnt-1;i++)
			{
				if(pbd[cnt-1].pb[j]==pbd[i].pb[j]) use[j]++;
			}
		}
		int Max = 0;					//找最远的
		for(j=0;j<phbnum;j++)
		{
			if(use[Max] < use[j]) Max = j;
		}
		for(j=0;j<phbnum;j++)			//逐个放进去
		{
			pbd[cnt].pb[j] = pbd[cnt-1].pb[j];
		}
		int flag = 0;
		for(j=0;j<phbnum;j++)			//检查是不是已经存在
        {
            if(pbd[cnt].num == pbd[cnt-1].pb[j]) flag = 1;
        }
		if(!flag)						//不存在就放入
        {
            pbd[cnt].pb[Max] = pbd[cnt].num;
            pbd[cnt].page = 1;			//缺页
        }
	}
	Print(pbd,pagenum,phbnum);			//打印
}

void LRU()
{
	PBD pbd[100];
	puts("/*****LRU最近最久未使用置换算法*****/");
	puts("请输入页面数量、物理块数");
	int pagenum,phbnum;
	scanf("%d %d",&pagenum,&phbnum);	//页数  块数
	GET(pbd,pagenum);
	int cnt = 1,a=0;
	while(cnt <= phbnum)			//未占满块数的情况
	{
		int i,j;
		for(i=0;i<cnt;i++)
		{
			if (pbd[a].pb[i] == pbd[i].num) break;	//查看是否已存在
		}
		if(i<=cnt)
        {
			if(!a)
			{
				pbd[a].pb[a] = pbd[a].num;			//0位数组特殊处理
			}
			else
			{
				for(j=0;j<cnt-1;j++)
				{
					pbd[a].pb[j] = pbd[a-1].pb[j];	//赋值进去
				}
				pbd[a].pb[j] = pbd[a].num;			//放入空位
			}
			pbd[a].page = 1;						//缺页
			cnt++;
			a++;
		}
		else
        {											//若已存在 就不缺页
            for(j=0;j<cnt;j++)
            {
                pbd[a].pb[j] = pbd[a-1].pb[j];
            }
            pbd[a].pb[j] = pbd[a].num;
            a++;
        }
	}cnt--;
	int i,j;
	puts(" ");
	for(cnt;cnt<=pagenum;cnt++)
	{
		int use[100]={0};				//表示到前面的距离
		for(j = 0;j < phbnum; j++)
		{								//此处计算距离
			for(i=cnt-1;i>=0;i--)
			{
				if(pbd[cnt-1].pb[j]==pbd[i].num) break;
				use[j]++;
			}
		}
		int Max = 0;					//找最远的
		for(j=0;j<phbnum;j++)
		{
			if(use[Max] < use[j]) Max = j;
		}
		for(j=0;j<phbnum;j++)			//逐个放进去
		{
			pbd[cnt].pb[j] = pbd[cnt-1].pb[j];
		}
		int flag = 0;
		for(j=0;j<phbnum;j++)			//检查是不是已经存在
        {
            if(pbd[cnt].num == pbd[cnt-1].pb[j]) flag = 1;
        }
		if(!flag)						//不存在就放入
        {
            pbd[cnt].pb[Max] = pbd[cnt].num;
            pbd[cnt].page = 1;			//缺页
        }
	}
	Print(pbd,pagenum,phbnum);			//打印
}

int main()
{
	puts("欢迎进入页面置换算法程序");
	puts("1:OPT最佳置换算法");
	puts("2:FIFO先进先出置换算法");
	puts("3:LRU最近最久未使用置换算法");
	int n;
	while(1)
	{
		puts("\n\n请输入一个数字表示你要执行的程序,-1结束程序");
		scanf("%d",&n);
		if(n==-1)
        {
            puts("程序结束!");
            break;
        }
		switch (n)
		{
			case 1:{
				OPT();
				break;
			}
			case 2:{
				FIFO();
				break;
			}
			case 3:{
				LRU();
				break;
			}
			default :{
				puts("请输入合法的数字!");
				continue;
			}
		}

	}
	return 0;
}

/*测试数据
12 3
1 2 3 4 1 2 5 1 2 3 4 5
*/

磁盘调度算法:

 

#include <stdio.h>

typedef struct Ct
{
	int num;	//磁盘号
	int space;	//磁盘寻道间距
	int use;	//是否使用过
	int rank;	//运行序号
}CT;

int cmp_rank(const void *a,const void *b)	//序号比较
{
	CT *c = (CT *)a;
	CT *d = (CT *)b;
	return c->rank - d->rank;
}

int cmp_num(const void *a,const void *b)	//磁头号比较
{
	CT *c = (CT *)a;
	CT *d = (CT *)b;
	return c->num - d->num;
}

int Get(CT ct[])	//得到磁头数据并返回磁头个数
{
	puts("请输入总磁头数");
	int ca;
	scanf("%d",&ca);
	int i;
	puts("请输入磁头");
	for(i=0;i<ca;i++)
	{
		scanf("%d",&ct[i].num);
		ct[i].space = 0;
		ct[i].use = 0;
		ct[i].rank = -1;
	}
	puts("");
	return ca;
}

void Print(CT ct[],int ca)	//打印列表
{
	int i;
	puts("序号  磁头号     寻道数");
	for(i=0;i<ca;i++)
	{
		printf("%3d  %5d      %5d\n",ct[i].rank,ct[i].num,ct[i].space);
	}
}

void FCFS()
{
	CT ct[100];
	puts("/****FCFS先来先服务调度算法****/");
	int ca = Get(ct);
	puts("请输入初始所在位置");
	int place;				//初始位置
	scanf("%d",&place);

	int i;
	for(i=0;i<ca;i++)		//计算间距
	{
		if(!i){
			ct[i].space += ct[i].num - place > 0 ? ct[i].num - place : place - ct[i].num;
			ct[i].rank = i+1;
		}
		else
		{
			ct[i].space += ct[i].num - ct[i-1].num > 0 ? ct[i].num - ct[i-1].num : ct[i-1].num - ct[i].num;
			ct[i].rank = i+1;
		}
	}
	Print(ct,ca);			//输出数据列表
	int sum=0;				//总寻道数
	double average;			//平均寻道数
	for(i=0;i<ca;i++)
	{
		sum += ct[i].space;	//求总寻道数
	}
	average = sum*1.0 / ca;
	printf("总寻道数:%d\n平均寻道数:%.3f\n",sum,average);
}

void SSTF()
{
	CT ct[100];
	puts("/****SSTF最短寻道时间优先调度算法****/");
	int ca = Get(ct);
	puts("请输入初始所在位置");
	int place;				//初始位置
	scanf("%d",&place);
	int a,i;
	for(a=0;a<ca;a++)		//ca次运行
	{
		int Min = 9999999,flag = -1;
		for(i=0;i<ca;i++)	//查找最近的磁头
		{
            if((ct[i].num - place > 0 ? ct[i].num - place : place - ct[i].num) < Min && ct[i].use==0)
            {
                Min = ct[i].num - place > 0 ? ct[i].num - place : place - ct[i].num;
                flag = i;
            }
		}
		if(flag>=0)
		{
			ct[flag].use = 1;
			ct[flag].space = ct[flag].num - place > 0 ? ct[flag].num - place : place - ct[flag].num;
			place = ct[flag].num;
			ct[flag].rank = a+1;
		}
	}
	qsort(ct,ca,sizeof(ct[0]),cmp_rank);	//排序rank
	Print(ct,ca);
	int sum=0;				//总寻道数
	double average;			//平均寻道数
	for(i=0;i<ca;i++)
	{
		sum += ct[i].space;	//求总寻道数
	}
	average = sum*1.0 / ca;
	printf("总寻道数:%d\n平均寻道数:%.3f\n",sum,average);
}

void SCAN()
{
	CT ct[100];
	puts("/****SCAN扫描调度算法****/");
	int ca = Get(ct);
	puts("请输入初始所在位置");
	int place;				//初始位置
	scanf("%d",&place);
	qsort(ct,ca,sizeof(ct[0]),cmp_num);
	int a = 1;
	int i;
	for(i=0;i<ca;i++)
	{
		if(ct[i].num > place && !ct[i].use)
		{
			ct[i].use = 1;
			ct[i].space = ct[i].num - place;
			ct[i].rank = a++;
			place = ct[i].num;
		}
	}
	for(i=ca-1;i>=0;i--)
	{
		if(ct[i].num < place && !ct[i].use)
		{
			ct[i].use = 1;
			ct[i].space = place - ct[i].num;
			ct[i].rank = a++;
			place = ct[i].num;
		}
	}
	qsort(ct,ca,sizeof(ct[0]),cmp_rank);	//排序rank
	Print(ct,ca);
	int sum=0;				//总寻道数
	double average;			//平均寻道数
	for(i=0;i<ca;i++)
	{
		sum += ct[i].space;	//求总寻道数
	}
	average = sum*1.0 / ca;
	printf("总寻道数:%d\n平均寻道数:%.3f\n",sum,average);
}

void C_SCAN()
{
	CT ct[100];
	puts("/****C-SCAN循环扫描调度算法****/");
	int ca = Get(ct);
	puts("请输入初始所在位置");
	int place;				//初始位置
	scanf("%d",&place);
	qsort(ct,ca,sizeof(ct[0]),cmp_num);
	int a = 1;
	int i;
	for(i=0;i<ca;i++)
	{
		if(ct[i].num > place && !ct[i].use)
		{
			ct[i].use = 1;
			ct[i].space = ct[i].num - place;
			ct[i].rank = a++;
			place = ct[i].num;
		}
	}

	for(i=0;i<ca;i++)
	{
		if(ct[i].num < place && !ct[i].use &&!i)
		{
			ct[i].use = 1;
			ct[i].space = place - ct[i].num;
			ct[i].rank = a++;
			place = ct[i].num;
			printf("place %d\n",place);
		}
		else if(ct[i].num > place && !ct[i].use && i)
        {
            ct[i].use = 1;
            ct[i].space = ct[i].num - place;
            ct[i].rank = a++;
            place = ct[i].num;
        }
	}
	qsort(ct,ca,sizeof(ct[0]),cmp_rank);	//排序rank
	Print(ct,ca);
	int sum=0;				//总寻道数
	double average;			//平均寻道数
	for(i=0;i<ca;i++)
	{
		sum += ct[i].space;	//求总寻道数
	}
	average = sum*1.0 / ca;
	printf("总寻道数:%d\n平均寻道数:%.3f\n",sum,average);
}

int main()
{
	puts("欢迎进入磁盘调度算法程序");
	puts("1:FCFS先来先服务调度算法");
	puts("2:SSTF最短寻道时间优先调度算法");
	puts("3:SCAN扫描调度算法");
	puts("4:C-SCAN循环扫描调度算法");
	int n;
	while(1)
	{
		puts("\n\n请输入一个数字表示你要执行的程序,-1结束程序");
		scanf("%d",&n);
		if(n==-1) 
        {
            puts("程序结束!");
            break;
        }
		switch (n)
		{
			case 1:{
				FCFS();
				break;
			}
			case 2:{
				SSTF();
				break;
			}
			case 3:{
				SCAN();
				break;
			}
			case 4:{
				C_SCAN();
				break;
			}
			default :{
				puts("请输入合法的数字!");
				continue;
			}
		}

	}
	return 0;
}
/*
9
55 58 39 18 90 160 150 38 184
100
*/

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值