操作系统实验

进程同步(linux环境)

生产者消费者问题

生产者

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>
int main() {
	int i=0,n;
	sem_t *mutex=sem_open("mutex",O_CREAT,0666,1);
	sem_t *empty=sem_open("empty",O_CREAT,0666,5);
	sem_t *full=sem_open("full",O_CREAT,0666,0);
	for(i=0; i<20; i++) {
		sem_wait(empty);
		sem_wait(mutex);
		sem_getvalue(full,&n);
		printf("Producerr put a production! Production Num:%d\n",n+1);
		sem_post(mutex);
		sem_post(full);
		sleep(rand()%3);
	}
	sem_close(mutex);
	sem_close(empty);
	sem_close(full);
	sem_unlink("mutex");
	sem_unlink("empty");
	sem_unlink("full");
	return 0;
}

消费者

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>
int main() {
	int i=0,n;
	sem_t *mutex=sem_open("mutex",O_CREAT,0666,1);
	sem_t *empty=sem_open("empty",O_CREAT,0666,5);
	sem_t *full=sem_open("full",O_CREAT,0666,0);
	for(i=0; i<20; i++) {
		sem_wait(full);
		sem_wait(mutex);
		sem_getvalue(full,&n);
		printf("Consumer get a production! Production Num:%d\n",n);
		sem_post(mutex);
		sem_post(empty);
		sleep(rand()%3);
	}
	sem_close(mutex);
	sem_close(empty);
	sem_close(full);
	sem_unlink("mutex");
	sem_unlink("empty");
	sem_unlink("full");
	return 0;
}

哲学家进餐问题

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>
int main(int argc,char *argv[]) {
	int name;
	int i=0;
	if(argc>1) {
		name=argv[1][0];
		name-=48;
	}
	sem_t *room=sem_open("mysem",O_CREAT,0666,4);
	sem_t *chopstick[5];
	for(i=0;i<5;i++){
		chopstick[i]=sem_open("chopstick"+i,O_CREAT,0666,1);
	}
	for(i=0;i<5;i++){
		sleep(rand()%3);
		sem_wait(room);
		sem_wait(chopstick[name-1]);
		sem_wait(chopstick[name%5]);
		printf("philosopher %d eating\n",name);
		sem_post(chopstick[name-1]);
		sem_post(chopstick[name%5]);
		sem_post(room);
	}
	printf("philosopher %d full up\n",name);
	sem_close(room);
	for(i=0;i<5;i++){
		sem_close(chopstick[i]);
	}
	sem_unlink("room");
	for(i=0;i<5;i++){
		sem_unlink("chopstick"+i);
	}
}
/*
./philosopher 1 & ./philosopher 2 & ./philosopher 3 & ./philosopher 4 & ./philosopher 5
*/

小和尚打水老和尚喝水问题

小和尚

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>
int main(int argc,char *argv[]) {
	char* name;
	int i=0,n;
	if(argc>1) {
		name=argv[1];
	}
	sem_t *mutexWell=sem_open("mutexWell",O_CREAT,0666,1);
	sem_t *mutexBucket=sem_open("mutexBucket",O_CREAT,0666,3);
	sem_t *mutexVat=sem_open("mutexVat",O_CREAT,0666,1);
	sem_t *emptyVat=sem_open("emptyVat",O_CREAT,0666,10);
	sem_t *fullVat=sem_open("fullVat",O_CREAT,0666,0);
	for(i=0; i<5; i++) {
		sleep(rand()%2);
		sem_wait(emptyVat);
		sem_wait(mutexBucket);
		printf("little monk %s get a bucket.\n",name);
		sleep(rand()%2);
		sem_wait(mutexWell);
		printf("little monk %s get the water from well.\n",name);
		sem_post(mutexWell);
		sleep(rand()%2);
		sem_wait(mutexVat);
		sem_getvalue(fullVat,&n);
		printf("little monk %s put the into vat. Vat: %d\n",name,n+1);
		sem_post(mutexVat);
		sem_post(fullVat);
		sem_post(mutexBucket);
	}
	sem_close(mutexWell);
	sem_close(mutexBucket);
	sem_close(mutexVat);
	sem_close(emptyVat);
	sem_close(fullVat);
	sem_unlink("mutexWell");
	sem_unlink("mutexVat");
	sem_unlink("mutexBucket");
	sem_unlink("emptyVat");
	sem_unlink("fullVat");
	return 0;
}
/*
./lm2 1 & ./lm2 2 & ./lm2 3 & ./bm 1 & ./bm 2
*/

老和尚

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<fcntl.h>
#include<sys/stat.h>
int main(int argc,char *argv[]) {
	char* name;
	int i=0,n;
	if(argc>1) {
		name=argv[1];
	}
	sem_t *mutexWell=sem_open("mutexWell",O_CREAT,0666,1);
	sem_t *mutexBucket=sem_open("mutexBucket",O_CREAT,0666,3);
	sem_t *mutexVat=sem_open("mutexVat",O_CREAT,0666,1);
	sem_t *emptyVat=sem_open("emptyVat",O_CREAT,0666,10);
	sem_t *fullVat=sem_open("fullVat",O_CREAT,0666,0);
	for(i=0; i<5; i++) {
		sleep(rand()%2);
		sem_wait(fullVat);
		sem_wait(mutexBucket);
		printf("big monk %s get a bucket.\n",name);
		sleep(rand()%2);
		sem_wait(mutexVat);
		sem_getvalue(fullVat,&n);
		printf("big monk %s drink the water.Vat: %d \n ",name,n);
		sem_post(mutexVat);
		sem_post(emptyVat);
		sem_post(mutexBucket);
	}
	sem_close(mutexWell);
	sem_close(mutexBucket);
	sem_close(mutexVat);
	sem_close(emptyVat);
	sem_close(fullVat);
	sem_unlink("mutexWell");
	sem_unlink("mutexVat");
	sem_unlink("mutexBucket");
	sem_unlink("emptyVat");
	sem_unlink("fullVat");
	return 0;
}

作业调度算法模拟

  1. 先来先服务(FCFS)算法短作业优先(SJF)算法高响应比优先(HRRF)算法高优先权优先(HPF)算法
  2. 输入格式,以文件形式输入作业信息
    在这里插入图片描述
  3. 结果示例
    在这里插入图片描述
    源码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include<iostream>
#include <algorithm>
using namespace std;
//无穷
const int INF=1e6;
//最大作业数量
const int MAXJOB=50;
//作业的数据结构
typedef struct node {
	int number;//作业号
	int reach_time;//作业抵达时间
	int need_time;//作业的执行时间
	int privilege;//作业优先权
	float excellent;//响应比
	int start_time;//作业开始时间
	int wait_time;//等待时间
	int visited;//作业是否被访问过
	bool isreached;//作业是否抵达
} job;
job jobs[MAXJOB];//作业序列
int quantity;//作业数量
int cmp(job a, job b) {
	return a.reach_time<b.reach_time;
}
//初始化作业序列
void initial_jobs() {
	int i;
	for(i=0; i<MAXJOB; i++) {
		jobs[i].number=0;
		jobs[i].reach_time=0;
		jobs[i].privilege=0;
		jobs[i].excellent=0;
		jobs[i].start_time=0;
		jobs[i].wait_time=0;
		jobs[i].visited=0;
		jobs[i].isreached=false;
	}
	quantity=0;
}
//重置全部作业信息
void reset_jinfo() {
	int i;
	for(i=0; i<MAXJOB; i++) {
		jobs[i].start_time=0;
		jobs[i].wait_time=0;
		jobs[i].visited=0;
		jobs[i].isreached=false;
	}
}
//检查到达的作业
void checkReached(int current_time) {
	int i;
	for(i=0; i<quantity; i++) {
		if(!jobs[i].isreached&&jobs[i].reach_time<=current_time) {
			jobs[i].isreached=true;
		}
	}
}
//查找当前current_time已到达未执行的最短作业,若无返回-1
int findminjob(job jobs[],int count) {
	int minjob=-1;//=jobs[0].need_time;
	int minloc=-1;
	for(int i=0; i<count; i++) {
		if(minloc==-1) {
			if(jobs[i].isreached && jobs[i].visited==0) {
				minjob=jobs[i].need_time;
				minloc=i;
			}
		} else if(minjob>jobs[i].need_time&&jobs[i].visited==0&&jobs[i].isreached) {
			minjob=jobs[i].need_time;
			minloc=i;
		}
	}
	return minloc;
}
//查找最早到达作业,若全部到达返回-1.
int findrearlyjob(job jobs[],int count) {
	int rearlyloc=-1;
	int rearlyjob=-1;
	for(int i=0; i<count; i++) {
		if(!jobs[i].visited) {
			rearlyloc=i;
			break;
		}
//		if(rearlyloc==-1) {
//			if(jobs[i].visited==0) {
//				rearlyloc=i;
//				rearlyjob=jobs[i].reach_time;
//			}
//		} else if(rearlyjob>jobs[i].reach_time&&jobs[i].visited==0) {
//			rearlyjob=jobs[i].reach_time;
//			rearlyloc=i;
//		}
	}
	return rearlyloc;
}
//查找响应比最大的作业
int findHRRjob(job jobs[],int count) {
	int loc=-1;
	int hrr=-1;
	for(int i=0; i<count; i++) {
		if(loc==-1) {
			if(jobs[i].isreached&&!jobs[i].visited) {
				hrr=jobs[i].excellent;
				loc=i;
			}
		} else if(hrr<jobs[i].excellent&&jobs[i].isreached&&!jobs[i].visited) {
			hrr=jobs[i].excellent;
			loc=i;
		}
	}
	return loc;
}
//查找优先权最高的作业
int findHighPrivilegeJob(){
	int loc=-1;
	int p=-1;
	for(int i=0;i<quantity;i++){
		if(jobs[i].isreached&&!jobs[i].visited&&p<jobs[i].privilege){
			loc=i;
			p=jobs[i].privilege;
		}
	}
	return loc;
}
//更新响应比
void refreshHRR(int current_time) {
	int i;
	for(i=0; i<quantity; i++) {
		if(jobs[i].isreached&&!jobs[i].visited) {
			jobs[i].excellent=1+(current_time-jobs[i].reach_time)*1.0/jobs[i].need_time;
		}
	}
}
//读取作业数据
void readJobdata() {
	FILE *fp;
	char fname[20];
	int i;
	//输入测试文件文件名
	printf("please input job data file name\n");
	scanf("%s",fname);
	if((fp=fopen(fname,"r"))==NULL) {
		printf("error, open file failed, please check filename:\n");
	} else {
		//依次读取作业信息
		while(!feof(fp)) {
			if(fscanf(fp,"%d %d %d %d",&jobs[quantity].number,&jobs[quantity].reach_time,&jobs[quantity].need_time,&jobs[quantity].privilege)==4)
				quantity++;
		}
		//打印作业信息
		printf("output the origin job data\n");
		printf("---------------------------------------------------------------------\n");
		printf("\tjobID\treachtime\tneedtime\tprivilege\n");
		for(i=0; i<quantity; i++) {
			printf("\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[i].number,jobs[i].reach_time,jobs[i].need_time,jobs[i].privilege);
		}
	}
	sort(jobs,jobs+quantity,cmp);
}
//FCFS
void FCFS() {
	int i;
	int current_time=0;
	int loc;
	int total_waitime=0;
	int total_roundtime=0;
	//输出作业流
	printf("\n\nFCFS算法作业流\n");
	printf("------------------------------------------------------------------------\n");
	printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
	//每次循环找出最先到达的作业并打印相关信息
	for(i=0; i<quantity; i++) {
		loc=findrearlyjob(jobs,quantity);
		if(jobs[loc].reach_time>current_time) {
			jobs[loc].start_time=jobs[loc].reach_time;
			current_time=jobs[loc].reach_time;
		} else {
			jobs[loc].start_time=current_time;
		}
		jobs[loc].wait_time=current_time-jobs[loc].reach_time;
		printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
		       jobs[loc].wait_time+jobs[loc].need_time);
		jobs[loc].visited=1;
		current_time+=jobs[loc].need_time;
		total_waitime+=jobs[loc].wait_time;
		total_roundtime=total_roundtime+jobs[loc].wait_time+jobs[loc].need_time;
	}
	printf("总等待时间:%-8d 总周转时间:%-8d\n",total_waitime,total_roundtime);
	printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n",(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
//短作业优先作业调度
void SFJschdulejob(job jobs[],int count) {
	int i,j;
	int current_time=0;
	int loc;
	int total_waitime=0;
	int total_roundtime=0;
	//输出作业流
	printf("\n\nSJF算法作业流\n");
	printf("------------------------------------------------------------------------\n");
	printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
	//查找最先到达的作业
	current_time=INF;
	for(i=0; i<quantity; i++) {
		if(current_time>jobs[i].reach_time) {
			current_time=jobs[i].reach_time;
		}
	}
	//每次循环找出执行时间最短的作业并打印相关信息
	for(i=0; i<quantity; i++) {
		checkReached(current_time);
		loc=findminjob(jobs,quantity);
		while(loc==-1) {
			current_time=INF;
			for(j=0; j<quantity; j++) {
				if(!jobs[j].isreached&&current_time>jobs[j].reach_time) {
					current_time=jobs[j].reach_time;
				}
			}
			checkReached(current_time);
			loc=findminjob(jobs,quantity);
		}
		if(jobs[loc].reach_time>current_time) {
			jobs[loc].start_time=jobs[loc].reach_time;
			current_time=jobs[loc].reach_time;
		} else {
			jobs[loc].start_time=current_time;
		}
		jobs[loc].wait_time=current_time-jobs[loc].reach_time;
		printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
		       jobs[loc].wait_time+jobs[loc].need_time);
		jobs[loc].visited=1;
		current_time+=jobs[loc].need_time;
		total_waitime+=jobs[loc].wait_time;
		total_roundtime=total_roundtime+jobs[loc].wait_time+jobs[loc].need_time;
	}
	printf("总等待时间:%-8d 总周转时间:%-8d\n",total_waitime,total_roundtime);
	printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n",(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
//高响应比调度算法
void HRRFschdulejob() {
	int i,j;
	int current_time=0;
	int loc;
	int total_waitime=0;
	int total_roundtime=0;
	//输出作业流
	printf("\n\nHRRF算法作业流\n");
	printf("------------------------------------------------------------------------\n");
	printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
	//查找最先到达的作业
	current_time=INF;
	for(i=0; i<quantity; i++) {
		if(current_time>jobs[i].reach_time) {
			current_time=jobs[i].reach_time;
		}
	}
	//每次循环找出执行时间最短的作业并打印相关信息
	for(i=0; i<quantity; i++) {
		checkReached(current_time);
		refreshHRR(current_time);
		loc=findHRRjob(jobs,quantity);
		while(loc==-1) {
			current_time=INF;
			for(j=0; j<quantity; j++) {
				if(!jobs[j].isreached&&current_time>jobs[j].reach_time) {
					current_time=jobs[j].reach_time;
				}
			}
			checkReached(current_time);
			refreshHRR(current_time);
			loc=findHRRjob(jobs,quantity);
		}
		if(jobs[loc].reach_time>current_time) {
			jobs[loc].start_time=jobs[loc].reach_time;
			current_time=jobs[loc].reach_time;
		} else {
			jobs[loc].start_time=current_time;
		}
		jobs[loc].wait_time=current_time-jobs[loc].reach_time;
		printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
		       jobs[loc].wait_time+jobs[loc].need_time);
		jobs[loc].visited=1;
		current_time+=jobs[loc].need_time;
		total_waitime+=jobs[loc].wait_time;
		total_roundtime=total_roundtime+jobs[loc].wait_time+jobs[loc].need_time;
	}
	printf("总等待时间:%-8d 总周转时间:%-8d\n",total_waitime,total_roundtime);
	printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n",(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
//优先权高者优先调度算法
void HPF(job jobs[]) {
	int i,j;
	int current_time=0;
	int loc;
	int total_waitime=0;
	int total_roundtime=0;
	//输出作业流
	printf("\n\nHPF算法作业流\n");
	printf("------------------------------------------------------------------------\n");
	printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
	//查找最先到达的作业
	current_time=INF;
	for(i=0; i<quantity; i++) {
		if(current_time>jobs[i].reach_time) {
			current_time=jobs[i].reach_time;
		}
	}
	//每次循环找出执行时间最短的作业并打印相关信息
	for(i=0; i<quantity; i++) {
		checkReached(current_time);
		loc=findHighPrivilegeJob();
		while(loc==-1) {
			current_time=INF;
			for(j=0; j<quantity; j++) {
				if(!jobs[j].isreached&&current_time>jobs[j].reach_time) {
					current_time=jobs[j].reach_time;
				}
			}
			checkReached(current_time);
			refreshHRR(current_time);
			loc=findHRRjob(jobs,quantity);
		}
		if(jobs[loc].reach_time>current_time) {
			jobs[loc].start_time=jobs[loc].reach_time;
			current_time=jobs[loc].reach_time;
		} else {
			jobs[loc].start_time=current_time;
		}
		jobs[loc].wait_time=current_time-jobs[loc].reach_time;
		printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
		       jobs[loc].wait_time+jobs[loc].need_time);
		jobs[loc].visited=1;
		current_time+=jobs[loc].need_time;
		total_waitime+=jobs[loc].wait_time;
		total_roundtime=total_roundtime+jobs[loc].wait_time+jobs[loc].need_time;
	}
	printf("总等待时间:%-8d 总周转时间:%-8d\n",total_waitime,total_roundtime);
	printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n",(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
int main() {
	initial_jobs();
	readJobdata();
	FCFS();
	reset_jinfo();
	SFJschdulejob(jobs,quantity);
	reset_jinfo();
	HRRFschdulejob();
	reset_jinfo();
	HPF(jobs);
	system("pause");
	return 0;
}

动态分区分配方式模拟

#include<stdio.h>
#include<stdlib.h>
const int INF=1e7;
const int capacity=640;
typedef struct block {
	int start;
	int length;
	int job;
	block* next;
} block;
block* occupiedTable;//头指针
block* freeTable;//头指针
int job;
void Init() {
	occupiedTable=(block*)malloc(sizeof(block));
	occupiedTable->next=NULL;
	freeTable=(block*)malloc(sizeof(block));
	freeTable->next=(block*)malloc(sizeof(block));
	freeTable->next->start=0;
	freeTable->next->length=capacity;
	freeTable->next->next=NULL;
}
void PrintOccupiedTable() {
	printf("----------已分区表----------\n起始地址\t长度\t占用作业\n");
	block* b=occupiedTable->next;
	while(b) {
		printf("%dKB\t\t%dKB\t%d\n",b->start,b->length,b->job);
		b=b->next;
	}
}
void PrintFreeTable() {
	printf("----------空闲区表----------\n起始地址\t长度\t\n");
	block* b=freeTable->next;
	while(b) {
		printf("%dKB\t\t%dKB\n",b->start,b->length);
		b=b->next;
	}
}
int AllocFirstFit(int size) {
	int i,j,flag=0;
	block* x;
	block *p,*q,*n;
	p=NULL;
	n=(block*)malloc(sizeof(block));
	p=freeTable;
	q=occupiedTable;
	while(p->next) {
		//首次适应算法
		if(p->next->length>=size) {
			n->start=p->next->start;
			n->length=size;
			n->job=++job;
			flag=1;
			break;
		} else {
			p=p->next;
		}
	}
	if(flag==0) return 0;
	else {
		//跟新空闲分区表
		if(size==p->next->length) {
			p->next=p->next->next;
		} else {
			p->next->start+=size;
			p->next->length-=size;
		}
		//跟新已分区表
		while(q->next&&q->next->start<n->start) q=q->next;
		n->next=q->next;
		q->next=n;
	}
}
int AllocBestFit(int size) {
	int i,j,flag=0,minFree=INF;
	block* x;
	block *p,*q,*n,*t;
	p=NULL;
	n=(block*)malloc(sizeof(block));
	p=freeTable;
	q=occupiedTable;
	//最佳适应算法
	while(p->next) {
		if(p->next->length>=size&&p->next->length<minFree) {
			t=p;
			flag=1;
			minFree=t->next->length;
		}
		p=p->next;
	}
	n->start=t->next->start;
	if(flag==0) return 0;
	else {
		//跟新空闲分区表
		if(size==t->next->length) {
			t->next=t->next->next;
		} else {
			t->next->start+=size;
			t->next->length-=size;
		}
		//跟新已分区表
		while(q->next&&q->next->start<n->start) q=q->next;
		n->length=size;
		n->job=++job;
		n->next=q->next;
		q->next=n;
	}
}
int Free(int size) {
	int flag=0;
	block* p,* q, *n;
	p=occupiedTable;
	q=freeTable;
	n=(block*)malloc(sizeof(block));
	while(p->next) {
		if(p->next->length==size) {
			flag=1;
			n->start=p->next->start;
			n->length=size;
			p->next=p->next->next;
			break;
		} else {
			p=p->next;
		}
	}
	if(flag==0) return 0;
	else {
		while(q->next&&q->next->start<n->start) q=q->next;
		//加入并合并空闲区
		if(q->start+q->length==n->start) {
			q->length+=n->length;
		} else {
			n->next=q->next;
			q->next=n;
			q=n;
		}
		if(q->next&&q->start+q->length==q->next->start) {
			q->length+=q->next->length;
			q->next=q->next->next;
		}
	}
}
int main() {
	char a;
	int num;
	Init();
	printf("*------------帮助------------*\n");
	printf("| 申请大小为num的内存 a num  |\n");
	printf("| 释放大小为num的内存 f num  |\n");
	printf("|        查看已分区表 x      |\n");
	printf("|       查看空闲分区表 y     |\n");
	printf("|            退出 e          |\n");
	printf("*----------------------------*\n");
	while(scanf("%c",&a)) {
		if(a=='a') {
			scanf("%d",&num);
			if(!AllocBestFit(num)) {
				printf("无可用内存分配!\n");
			}
		} else if(a=='f') {
			scanf("%d",&num);
			if(!Free(num)) {
				printf("释放失败!\n");
			}
		} else if(a=='x') {
			PrintOccupiedTable();
		} else if(a=='y') {
			PrintFreeTable();
		} else if(a=='e') {
			break;
		} else {
			printf("非法字符!\n");
		}
		fflush(stdin);
	}
	return 0;
}
/*
a 130
a 60
a 100
f 60
a 200
f 100
f 130
a 140
a 60
a 50
f 60
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值