天天看点

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

▶▶▶完整代码在最后!!!

FIFO算法:先进先出调度算法,该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。

LRU算法:最近最少使用算法,根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。选择最近最久未使用的页面予以淘汰。

OPT算法:最佳淘汰算法,选择永不使用或在未来最长时间内不再被访问的页面予以替换。

CLOCK算法:根据页面内存是否被访问来决定是否置换该页面。

改进版CLOCK算法:在之前的CLOCK算法上面除了使用位,还增加了一个修改位,进行判断。

LFU算法:最近最少使用算法,如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰,也就是每次淘汰那些使用次数最少的数据。

系统最后的界面图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

系统设计流程图:

FIFO算法流程图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

LRU算法流程图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

OPT算法流程图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

CLOCK算法流程图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

改进版CLOCK算法流程图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

LFU算法流程图:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

算法分析(举例):

页面顺序为0 1 5 4 1 7 3 2 6 7

FIFO算法分析过程:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

LRU算法分析过程:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

OPT算法分析过程:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

CLOCK算法分析过程:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

改进版CLOCK算法分析过程:(修改位是随机产生的)

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法

LFU算法分析过程:

操作系统——页面置换FIFO、LRU、OPT、CLOCK、改进版CLOCK、LFU等算法
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <memory.h>

#define MAX_SEQ_LEN 50   /*页面序列的最大长度*/
int blockNum;   /*分配给进程的内存块数量*/
int pageNum;   /*进程页面数,决定随机生成的页面序列中页面号的最大值*/
int pageSequenceLen;   /*实际页面序列长度*/
int pageSequence[MAX_SEQ_LEN];  /*页面序列数组*/
int *memBlocks;    /*为进程分配的内存块,动态数组,存放页号*/
int *isPageLoaded;  /*页面状态数组,动态数组,1表示已经在内存块中,0表示不在内存块中*/
int *useSite;  /*CLOCK算法的使用位,标记页号的状态*/
int *reviseSite; /*改进CLOCK算法的修改位*/
int oldPageIndex=0;  /*被置换的页索引*/
int pageFaultTimes=0;  /*缺页次数统计*/
float effectiveTime=0;  /*有效访问时间  有效访问时间=(1-pageFaultTimes)*内存访问时间+pageFaultTimes*页错误处理时间  /本例中 内存访问时间=100ns ; 页错误处理时间=20ms */
char choice1; /*用来存储是否开始(y/n)*/
int choice2=-1;/*用来存储选择的排序到序号*/

void FIFO(){
	printf("---------------------FIFO Replacement---------------------\n");
	int i,j,k, n;
	oldPageIndex = 0;
	pageFaultTimes = 0;
	effectiveTime=0;
	memBlocks = (int *)malloc(blockNum * sizeof(int));  //初始化内存块中的页面号,全部初始化设置为-1
	memset(memBlocks, -1, blockNum*sizeof(int));        //-1表示该内存块未装入任何页面

	isPageLoaded = (int *)malloc(pageNum * sizeof(int));//初始化页面状态数组,初始化未装入
	memset(isPageLoaded, 0, pageNum*sizeof(int));

	printf("页\t\t物理块\n");
	for (i=0; i<pageSequenceLen; i++) {
		printf("%2d\t-->\t", pageSequence[i]);
		if (0 == isPageLoaded[pageSequence[i]]) {
			pageFaultTimes++;
			for (j=0; j<blockNum; j++) {	//找空闲块
				if (memBlocks[j]==-1) break;
				}
			if (j<blockNum) {		//有空闲块
				memBlocks[j] = pageSequence[i]; //将当前页面序列的页号写入空闲内存块
				isPageLoaded[pageSequence[i]] = 1; //将页号对应的页面状态修改为已装入
				}
			else {		//没有空闲块,页面置换
				isPageLoaded[memBlocks[oldPageIndex]] = 0; //将被置换出去的页面状态修改为未装入
				memBlocks[oldPageIndex] = pageSequence[i]; //将当前页号写入内存块
				oldPageIndex = (oldPageIndex + 1) % blockNum;  //将最先进入的索引修改为下一个索引
				isPageLoaded[pageSequence[i]] = 1;   //将当前页面状态修改为1
				}

			for (j=0; j<blockNum; j++)    //显示内存块数组中的页号
				if (memBlocks[j] != -1)
					printf("%d ", memBlocks[j]);
			printf("\n");
			}
		else printf("\n");
	}
	srand((unsigned)time(NULL));
	effectiveTime=((1-pageFaultTimes*1.0/pageSequenceLen)*100+ pageFaultTimes*1.0/pageSequenceLen*20*1000000)/1000;
	printf("缺页次数为:%d,缺页率为:%.3f,有效访问时间:%.3fus\n", pageFaultTimes,pageFaultTimes*1.0/pageSequenceLen, effectiveTime);
		
}

void LRU(){
	printf("---------------------LRU Replacement---------------------\n");
	int i,j,k, n,m,h;
	oldPageIndex = 0;
	pageFaultTimes = 0;
	memBlocks = (int *)malloc(blockNum * sizeof(int));  //初始化内存块中的页面号,全部初始化设置为-1
	memset(memBlocks, -1, blockNum*sizeof(int));        //-1表示该内存块未装入任何页面

	isPageLoaded = (int *)malloc(pageNum * sizeof(int));//初始化页面状态数组,初始化未装入
	memset(isPageLoaded, 0, pageNum*sizeof(int));
	printf("页\t\t物理块\n");
	for (i=0; i<pageSequenceLen; i++) {
		h=0;
		printf("%2d\t-->\t", pageSequence[i]);
		if (isPageLoaded[pageSequence[i]] == 0){
			pageFaultTimes++;
			for (j=0; j<blockNum; j++) {	//找空闲块
				if (memBlocks[j]==-1) break;
				}
			if (j<blockNum) {		//有空闲块
				memBlocks[j] = pageSequence[i]; //将当前页面序列的页号写入空闲内存块
				isPageLoaded[pageSequence[i]] = 1; //将页号对应的页面状态修改为已装入
			}
			else {
				int a[blockNum],p;
				for(p=0;p<blockNum;p++)
					a[p]=0;
				for(k=i-1;k>=0;k--){
					for(m=0;m<j;m++)
						if(pageSequence[k]==memBlocks[m] && a[m]==0){
							h=m;
							a[m]=1;
						}
				}
				isPageLoaded[memBlocks[h]] = 0;
				memBlocks[h] = pageSequence[i];
				isPageLoaded[pageSequence[i]] = 1;
			}
			for (j=0; j<blockNum; j++)    //显示内存块数组中的页号
				if (memBlocks[j] != -1)
					printf("%d ", memBlocks[j]);
			printf("\n");
		}
		else printf("\n");
	}
	srand((unsigned)time(NULL));
        effectiveTime=((1-pageFaultTimes*1.0/pageSequenceLen)*100+ pageFaultTimes*1.0/pageSequenceLen*20*1000000)/1000;
        printf("缺页次数为:%d,缺页率为:%.3f,有效访问时间:%.3fus\n", pageFaultTimes,pageFaultTimes*1.0/pageSequenceLen, effectiveTime);
}

void OPT(){
        printf("---------------------OPT Replacement---------------------\n");
	int i,j,k, n,m,h;
        oldPageIndex = 0;
        pageFaultTimes = 0;
        effectiveTime=0;
        memBlocks = (int *)malloc(blockNum * sizeof(int));  //初始化内存块中的页面号,全部初始化设置为-1
        memset(memBlocks, -1, blockNum*sizeof(int));        //-1表示该内存块未装入任何页面

        isPageLoaded = (int *)malloc(pageNum * sizeof(int));//初始化页面状态数组,初始化未装入
        memset(isPageLoaded, 0, pageNum*sizeof(int));
	printf("页\t\t物理块\n");
	for (i=0; i<pageSequenceLen; i++) {
                h=0;
                int count=0;
                printf("%2d\t-->\t", pageSequence[i]);
                if (isPageLoaded[pageSequence[i]] == 0){
                        pageFaultTimes++;
                        for (j=0; j<blockNum; j++) {    //找空闲块
                                if (memBlocks[j]==-1) break;
                                }
                        if (j<blockNum) {               //有空闲块
                                memBlocks[j] = pageSequence[i]; //将当前页面序列的页号写入空闲内存块
                                isPageLoaded[pageSequence[i]] = 1; //将页号对应的页面状态修改为已装入
                        }
                        else {
                                int a[blockNum],p;
                                for(p=0;p<blockNum;p++)
                                        a[p]=0;
                                for(k=i+1;k<pageSequenceLen;k++){
                                        for(m=0;m<j;m++)
                                        	if(pageSequence[k]==memBlocks[m] && a[m]==0){
                                                	h=m;
                                                	a[m]=1;
							count++;
                                        	}
                                }
				if(count<blockNum)
					for(p=0;p<blockNum;p++){
						if(a[p]==0){
							h=p;
							break;
					}
				}
                                isPageLoaded[memBlocks[h]] = 0;
                                memBlocks[h] = pageSequence[i];
                                isPageLoaded[pageSequence[i]] = 1;
                        }
                        for (j=0; j<blockNum; j++)    //显示内存块数组中的页号
                                if (memBlocks[j] != -1)
                                        printf("%d ", memBlocks[j]);
                        printf("\n");
                }
                else printf("\n");
        }
        srand((unsigned)time(NULL));
        effectiveTime=((1-pageFaultTimes*1.0/pageSequenceLen)*100+ pageFaultTimes*1.0/pageSequenceLen*20*1000000)/1000;
        printf("缺页次数为:%d,缺页率为:%.3f,有效访问时间:%.3fus\n", pageFaultTimes,pageFaultTimes*1.0/pageSequenceLen, effectiveTime);
}

void CLOCK(){
	printf("---------------------CLOCK Replacement---------------------\n");
        int i,j,k, n,m,h;
        oldPageIndex = 0;
        pageFaultTimes = 0;
        memBlocks = (int *)malloc(blockNum * sizeof(int));  //初始化内存块中的页面号,全部初始化设置为-1
        memset(memBlocks, -1, blockNum*sizeof(int));        //-1表示该内存块未装入任何页面

        isPageLoaded = (int *)malloc(pageNum * sizeof(int));//初始化页面状态数组,初始化未装入
        memset(isPageLoaded, 0, pageNum*sizeof(int));
	
	useSite = (int *)malloc(blockNum * sizeof(int));//初始化页面使用位数组,初始化未装入
	memset(useSite, 0, blockNum*sizeof(int));
		
	int *pageSite;//标记页号在内存块中的位置
	pageSite = (int *)malloc(pageNum * sizeof(int));//初始化页面使用位数组,初始化未装入
	memset(pageSite, 0, pageNum*sizeof(int));

        printf("页\t\t物理块\n");
	
	for (i=0; i<pageSequenceLen; i++) {
                printf("%2d\t-->\t", pageSequence[i]);
                if (isPageLoaded[pageSequence[i]] == 0){
                        pageFaultTimes++;
                        for (j=0; j<blockNum; j++) {    //找空闲块
                                if (memBlocks[j]==-1) break;
                                }
                        if (j<blockNum) {               //有空闲块
                                memBlocks[j] = pageSequence[i]; //将当前页面序列的页号写入空闲内存块
                                isPageLoaded[pageSequence[i]] = 1; //将页号对应的页面状态修改为已装入
				useSite[j] = 1;
				pageSite[pageSequence[i]] = j;
                        }
                        else {
				int flag=0;
				while(flag==0){
					if(useSite[oldPageIndex] == 0){
                                		isPageLoaded[memBlocks[oldPageIndex]] = 0; //将被置换出去的页面状态修改为未装入
                                		memBlocks[oldPageIndex] = pageSequence[i]; //将当前页号写入内存块
						pageSite[pageSequence[i]] = oldPageIndex;
						useSite[oldPageIndex] = 1;
                                		oldPageIndex = (oldPageIndex + 1) % blockNum;  //将最先进入的索引修改为下一个索引
                                		isPageLoaded[pageSequence[i]] = 1;   //将当前页面状态修改为1
						flag=1;
					}
					else{
						useSite[oldPageIndex] = 0;
                                        	oldPageIndex = (oldPageIndex + 1) % blockNum;
					}
				}
                        }
                        for (j=0; j<blockNum; j++)    //显示内存块数组中的页号
                                if (memBlocks[j] != -1)
                                        printf("%d ", memBlocks[j]);
                        printf("\n");
                }
                else{
			useSite[pageSite[pageSequence[i]]] = 1;
			printf("\n");
		}
        }
        srand((unsigned)time(NULL));
        effectiveTime=((1-pageFaultTimes*1.0/pageSequenceLen)*100+ pageFaultTimes*1.0/pageSequenceLen*20*1000000)/1000;
        printf("缺页次数为:%d,缺页率为:%.3f,有效访问时间:%.3fus\n", pageFaultTimes,pageFaultTimes*1.0/pageSequenceLen, effectiveTime);
}

void improvedCLOCK(){
	printf("---------------------改进版CLOCK Replacement---------------------\n");
	int i,j,k, n,m,h;
        oldPageIndex = 0;
        pageFaultTimes = 0;
        memBlocks = (int *)malloc(blockNum * sizeof(int));  //初始化内存块中的页面号,全部初始化设置为-1
        memset(memBlocks, -1, blockNum*sizeof(int));        //-1表示该内存块未装入任何页面

        isPageLoaded = (int *)malloc(pageNum * sizeof(int));//初始化页面状态数组,初始化未装入
        memset(isPageLoaded, 0, pageNum*sizeof(int));

        useSite = (int *)malloc(blockNum * sizeof(int));//初始化页面使用位数组,初始化未装入
        memset(useSite, 0, blockNum*sizeof(int));
	
	reviseSite = (int *)malloc(pageSequenceLen * sizeof(int));//初始化页面使用位数组,初始化未装入
        memset(reviseSite, 0, pageSequenceLen*sizeof(int));

	int *reviseSites;//内存块中的修改位
        reviseSites = (int *)malloc(blockNum * sizeof(int));//
        memset(reviseSites, 0, blockNum*sizeof(int));

	int *pageSite;//标记页号在内存块中的位置
        pageSite = (int *)malloc(pageNum * sizeof(int));
        memset(pageSite, 0, pageNum*sizeof(int));


	for (i=0; i<pageSequenceLen; i++) { 
		printf("%d ", pageSequence[i]);
	}
	printf("\n");
	n=2;
	for (i=0; i<pageSequenceLen; i++) {
         	reviseSite[i] = rand()%n;
		printf("%d ", reviseSite[i]);       
        }
	printf("\n");
	     
	printf("页\t\t物理块\n");
	for (i=0; i<pageSequenceLen; i++) {
                printf("%2d\t-->\t", pageSequence[i]);
                if (isPageLoaded[pageSequence[i]] == 0){
                        pageFaultTimes++;
                        for (j=0; j<blockNum; j++) {    //找空闲块
                                if (memBlocks[j]==-1) break;
                                }
                        if (j<blockNum) {               //有空闲块
                                memBlocks[j] = pageSequence[i]; //将当前页面序列的页号写入空闲内存块
                                isPageLoaded[pageSequence[i]] = 1; //将页号对应的页面状态修改为已装入
                                useSite[j] = 1;
				reviseSites[j] = reviseSite[i];
                                pageSite[pageSequence[i]] = j;
                        }
                        else {
				int flag=0;
				while(flag==0){
					int count=0;
					while((useSite[oldPageIndex]!=0 || reviseSites[oldPageIndex]!=0) && count<blockNum){ 
						count++;
						oldPageIndex = (oldPageIndex + 1) % blockNum;
					}
					if(count<blockNum){
						isPageLoaded[memBlocks[oldPageIndex]] = 0;
						memBlocks[oldPageIndex] = pageSequence[i];
						reviseSites[oldPageIndex] = reviseSite[i];
                                        	useSite[oldPageIndex] = 1;
                                                pageSite[pageSequence[i]] = oldPageIndex;
                                        	oldPageIndex = (oldPageIndex + 1) % blockNum;
                                        	isPageLoaded[pageSequence[i]] = 1;
						flag=1;
					}
					else{
						int count1=0;
						while((useSite[oldPageIndex]!=0 || reviseSites[oldPageIndex]!=1) && count1<blockNum){
                                        		count1++;
							useSite[oldPageIndex] = 0;
                                        		oldPageIndex = (oldPageIndex + 1) % blockNum;
                                		}
						if(count1<blockNum){
							isPageLoaded[memBlocks[oldPageIndex]] = 0;
                                        		memBlocks[oldPageIndex] = pageSequence[i];
                                        		reviseSites[oldPageIndex] = reviseSite[i];
                                       	 		useSite[oldPageIndex] = 1;
                                                	pageSite[pageSequence[i]] = oldPageIndex;
                                        		oldPageIndex = (oldPageIndex + 1) % blockNum;
                                        		isPageLoaded[pageSequence[i]] = 1;
							flag=1;
						}
					}
				}
                        }
                        for (j=0; j<blockNum; j++)    //显示内存块数组中的页号
                                if (memBlocks[j] != -1)
                                        printf("%d ", memBlocks[j]);
                        printf("\n");
                }
		else{
                        useSite[pageSite[pageSequence[i]]] = 1;
			reviseSites[pageSite[pageSequence[i]]] = reviseSite[i];
			printf("\n");
		}
        }
        srand((unsigned)time(NULL));
        effectiveTime=((1-pageFaultTimes*1.0/pageSequenceLen)*100+ pageFaultTimes*1.0/pageSequenceLen*20*1000000)/1000;
        printf("缺页次数为:%d,缺页率为:%.3f,有效访问时间:%.3fus\n", pageFaultTimes,pageFaultTimes*1.0/pageSequenceLen, effectiveTime);
}

void LFU(){
	printf("---------------------LFU Replacement---------------------\n");
	int i,j,k, n;
        oldPageIndex = 0;
        pageFaultTimes = 0;
        effectiveTime=0;
        memBlocks = (int *)malloc(blockNum * sizeof(int));  //初始化内存块中的页面号,全部初始化设置为-1
        memset(memBlocks, -1, blockNum*sizeof(int));        //-1表示该内存块未装入任何页面

        isPageLoaded = (int *)malloc(pageNum * sizeof(int));//初始化页面状态数组,初始化未装入
        memset(isPageLoaded, 0, pageNum*sizeof(int));
	
	int *pagenumber;//各个页面出现的次数统计
	pagenumber = (int *)malloc(pageNum * sizeof(int));
	memset(pagenumber, 0, pageNum*sizeof(int));

	int *blocktime;//标记各个页面出现的先后顺序
        blocktime = (int *)malloc(blockNum * sizeof(int));
        memset(blocktime, 0, blockNum*sizeof(int));

        printf("页\t\t物理块\n");
        for (i=0; i<pageSequenceLen; i++) {
                printf("%2d\t-->\t", pageSequence[i]);
                if (isPageLoaded[pageSequence[i]] == 0) {
                        pageFaultTimes++;
                        for (j=0; j<blockNum; j++) {    //找空闲块
                                if (memBlocks[j]==-1) break;
                                }
                        if (j<blockNum) {               //有空闲块
                                memBlocks[j] = pageSequence[i]; //将当前页面序列的页号写入空闲内存块
                                isPageLoaded[pageSequence[i]] = 1; //将页号对应的页面状态修改为已装入
				pagenumber[pageSequence[i]]++;
				blocktime[j] = j;
                                }
                        else {          //没有空闲块,页面置换
				oldPageIndex = 0;
				for(j=1;j<blockNum;j++){
					if(pagenumber[memBlocks[oldPageIndex]]>pagenumber[memBlocks[j]])
						oldPageIndex=j;
					else if(pagenumber[memBlocks[oldPageIndex]] == pagenumber[memBlocks[j]] && blocktime[oldPageIndex]<blocktime[j])
						oldPageIndex = j;
				}
                                isPageLoaded[memBlocks[oldPageIndex]] = 0; //将被置换出去的页面状态修改为未装入
                                memBlocks[oldPageIndex] = pageSequence[i]; //将当前页号写入内存块
                                isPageLoaded[pageSequence[i]] = 1;   //将当前页面状态修改为1
				pagenumber[pageSequence[i]]++;
				for(j=0;j<blockNum;j++){
					if(blocktime[j]>blocktime[oldPageIndex])
						blocktime[j]--;
				}
				blocktime[oldPageIndex] = blockNum-1;
			}

                        for (j=0; j<blockNum; j++)    //显示内存块数组中的页号
                                if (memBlocks[j] != -1)
                                        printf("%d ", memBlocks[j]);
                        printf("\n");
                        }
                else{
			pagenumber[pageSequence[i]]++;
			printf("\n");
		}
        }
        srand((unsigned)time(NULL));
        effectiveTime=((1-pageFaultTimes*1.0/pageSequenceLen)*100+ pageFaultTimes*1.0/pageSequenceLen*20*1000000)/1000;
        printf("缺页次数为:%d,缺页率为:%.3f,有效访问时间:%.3fus\n", pageFaultTimes,pageFaultTimes*1.0/pageSequenceLen, effectiveTime);

}

int main(int argc,char **argv)
{
	printf("本例中 内存访问时间=100ns   页错误处理时间=20ms\n");
	int i,n;
	printf("Begin? (Y or N): ");
	choice1 = getchar();
	while (choice1=='Y' || choice1=='y') {
		printf("输入分配给该进程的内存块数:");
		scanf("%d", &blockNum);
		printf("输入该进程的页面总数:");
		scanf("%d", &pageNum);
		printf("输入该进程访问的页面序列长度:");
		scanf("%d", &pageSequenceLen);
		getchar();
		//srand((int)time(0));	
//		pageSequence[0]=0;pageSequence[1]=1;pageSequence[2]=5;pageSequence[3]=4;pageSequence[4]=1;
//		pageSequence[5]=7;pageSequence[6]=3;pageSequence[7]=2;pageSequence[8]=6;pageSequence[9]=7;
		for (i=0; i<pageSequenceLen; i++) {   //随机生成页面序列
			n=rand()%pageNum;
			pageSequence[i] = n;
			printf("%d ", pageSequence[i]);
		}		
		printf("\n请选择需要使用到算法:\n");
		printf("1.FIFO\n2.LRU\n3.OPT\n4.CLOCK\n5.改进版CLOCK\n6.LFU\n0.exit\n");
		printf("选择算法序号:");
		scanf("%d",&choice2);
		while(choice2){
			switch(choice2){
				case 1: FIFO();  	  break;
				case 2: LRU();   	  break;
				case 3: OPT();   	  break;
				case 4: CLOCK(); 	  break;
				case 5: improvedCLOCK();  break;
				case 6: LFU();		  break;            
				defalut: break;
			}
                	printf("请选择需要使用到算法:\n");
                	printf("1.FIFO\n2.LRU\n3.OPT\n4.CLOCK\n5.改进版CLOCK\n6.LFU\n0.exit\n");
	                printf("选择算法序号:");
			scanf("%d",&choice2);
		}
		printf("Begin? (Y or N): ");
		getchar();
		choice1 = getchar();
	}
}

           

继续阅读