操作系统课程设计_第1页
操作系统课程设计_第2页
操作系统课程设计_第3页
操作系统课程设计_第4页
操作系统课程设计_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

年4月19日操作系统课程设计文档仅供参考燕山大学课程设计说明书课程设计名称:操作系统题目:多道程序缓冲区协调操作班级:10级计算机应用2班开发小组名称:酷狗小队课题负责人:邓凯课题组成员:姓名:邓凯学号:班级:计算机应用2班自评成绩:A姓名:张聪慧学号:班级:计算机应用2班自评成绩:B课题开发日期:1月7日1概述1.1课程设计目的经过编写一个生产者消费者的实例,了解多线程的创立,运行原理,经过信号量机制的运用了解各线程间的协调工作机制;经过实现界面编程,了解MFC编程思想。1.2主要完成的任务如下图所示,有多个PUT操作要不断循环地向Buffer1送字符数据,有Move1操作不断地将Buffer1的数据取到Buffer2,Move2操作不断地将Buffer2的数据取到Buffer3,有多个GET操作要不断地从Buffer3中取数据。PUT、MOVE、GET每次操作一个数据,为了在操作的过程中要保证数据不丢失,每个Buffer每次只能接受一个PUT或一个Move或一个Get,多个操作不能同时操作同一BUFFER。设计一个多道程序完成上述操作。Move2Move1Move2Move1Buff2GetBuff3PutBuff1Buff2GetBuff3PutBuff1图1Buffer操作(1)能够随机产生字符数据,由put操作放入Buff1,buffer中容量单位是字符。(2)提供良好图形界面,显示Buffer的操作过程。(3)能够设定各Buffer的容量、PUT、GET、Move操作的个数;(4)能够设定PUT、GET、Move操作的速度;(5)实时显示每个Buffer中数据的个数和数据的内容,空闲Buffer的空间的个数;(6)实时显示线程、进程所处于等待(阻塞)状态的个数(7)程序运行结束,显示汇总数据:总的运行时间;Buffer中数据的个数;已放入BUFFER的数据个数;已放已取的数据个数;平均每个buffer中的数据个数。1.3课程设计使用的开发语言和工具语言:C++开发环境:VisualStudio及其开发环境下的MFC平台。1.4解决的主要问题MFC界面设计模拟生产者消费者的互斥操作各信号量的使用2使用的基本概念和原理2.1MFCMFC是Windows下程序设计的最流行的一个类库,它合理的封装了WIN32API函数,并设计了一套方便的消息映射机制。2.2MFC的消息实现机制在MFC的框架结构下,能够进行消息处理的类的头文件里面都会含有DECLARE_MESSAGE_MAP()宏,这里主要进行消息映射和消息处理函数的声明。所有能够进行消息处理的类都是基于CCmdTarget类的,也就是说CCmdTarget类是所有能够进行消息处理类的父类。CCmdTarget类是MFC处理命令消息的基础和核心。2.3线程线程是程序独立运行的基本单位,一个程序经过执行多个线程能够提高机器本身资源的利用率,同时也能够完成多任务并行运行的操作。2.4信号量信号量是一个在一定范围内变化的整形数据,用来表示一种临界资源,线程经过信号量的值来确定自己的状态是执行还是挂起,各线程间也是经过信号量机制来协调运行顺序一起完成任务。3总体设计确定基本技术路线为面向对象程序设计,使用MFC编写程序,建立基本对话框。在对话框中设立生产者、MOVE、消费者板块,各板块内的按钮能控制各自线程的建立、暂停以及相关数据的设定。经过创立生产者线程往BUFFER1中投放随机产生的字符,创立MOVE1线程将BUFFER1中的字符移动到BUFFER2中,创立MOVE2线程将BUFFER2中的字符移动到BUFFER3中,创立消费者线程从BUFFER3中取出字符消费。建立信号量,因为生产者线程和MOVE1线程共同使用临界资源BUFFER1,因此用Mutex信号量来协调生产者线程和MOVE1线程;因为MOVE1线程和MOVE2线程共同使用临界资源BUFFER2,因此用Mutex1信号量来协调MOVE1线程和MOVE2线程,因为MOVE2线程和消费者线程共同使用临界资源BUFFER3,因此用Mutex3信号量来协调MOVE2线程和消费者线程。4详细设计4.1ThreadInfo结构体typedefstructThreadInfo{ CListBox*pList;}thread,*lpthread;此结构体用来保存在线程建立时往线程中传送的参数信息(如该线程指定的操作控件),以供在本线程中使用。4.2线程操作函数4.2.1执行函数的声明分别声明生产者、MOVE1、MOVE2、消费者函数,格式为:DWORDWINAPIthreadFIFO(LPVOIDlparam);//声明3个不同的生产者线程,主要区别是能分别输出该生产的字符是哪个生产者生产的。DWORDWINAPIProductor1(LPVOIDpthread)DWORDWINAPIProductor2(LPVOIDpthread)DWORDWINAPIProductor3(LPVOIDpthread)//声明MOVE1线程。DWORDWINAPIMove1(LPVOIDpthread)//声明MOVE2线程。DWORDWINAPIMove2(LPVOIDpthread)//声明3个不同的消费者线程,主要区别是能分别输出该消费的字符是哪个消费者消费的。DWORDWINAPIConsumer1(LPVOIDpthread)DWORDWINAPIConsumer2(LPVOIDpthread)DWORDWINAPIConsumer3(LPVOIDpthread)4.2.2定义12个线程//3个生产者线程hThread1=CreateThread(NULL,0,Productor1,&thread1,0,&ProducterID);hThread2=CreateThread(NULL,0,Productor2,&thread1,0,&ProducterID);hThread7=CreateThread(NULL,0,Productor3,&thread1,0,&ProducterID);//3个MOVE1线程hThread5=CreateThread(NULL,0,Move1,&thread3,0,&MoveID[0]);hThread9=CreateThread(NULL,0,Move1,&thread3,0,&MoveID[0]);hThread10=CreateThread(NULL,0,Move1,&thread3,0,&MoveID[0]);//3个MOVE2线程hThread6=CreateThread(NULL,0,Move2,&thread4,0,&MoveID[1]);hThread11=CreateThread(NULL,0,Move2,&thread4,0,&MoveID[1]);hThread12=CreateThread(NULL,0,Move2,&thread4,0,&MoveID[1]);4.2.3各信号量的定义Mutex=CreateMutex(NULL,false,NULL);Mutex1=CreateMutex(NULL,false,NULL);Mutex2=CreateMutex(NULL,false,NULL);BufferFull=CreateSemaphore(NULL,BUFFER_SIZE1,BUFFER_SIZE1,NULL);BufferEmpty=CreateSemaphore(NULL,0,BUFFER_SIZE1,NULL);/Buffer1Full=CreateSemaphore(NULL,BUFFER_SIZE1,BUFFER_SIZE1,NULL);Buffer1Empty=CreateSemaphore(NULL,0,BUFFER_SIZE1,NULL);Buffer2Full=CreateSemaphore(NULL,BUFFER_SIZE1,BUFFER_SIZE1,NULL);Buffer2Empty=CreateSemaphore(NULL,0,BUFFER_SIZE1,NULL);4.2.4各线程的函数接口的定义及算法描述生产者线程函数接口:DWORDWINAPIProductor1(LPVOIDpthread){ lpthreadtemp=(lpthread)pthread; CStringstr=_T("生产者:"); while(control){ WaitForSingleObject(BufferFull,INFINITE);WaitForSingleObject(Mutex,INFINITE); buffer[in%BUFFER_SIZE1]=(char)('Z'-rand()%26); temp->pList->AddString(str+buffer[in%BUFFER_SIZE1]); c_Buffer.AddString(buffer[in%BUFFER_SIZE1]); in=in+1; Sleep(t1); ReleaseMutex(Mutex); ReleaseSemaphore(BufferEmpty,1,NULL); } returntrue;}MOVE1线程函数接口:DWORDWINAPIMove1(LPVOIDpthread){ intflag; lpthreadtemp=(lpthread)pthread; CStringstr=_T(""); while(control){ WaitForSingleObject(BufferEmpty,INFINITE); WaitForSingleObject(Buffer1Full,INFINITE); WaitForSingleObject(Mutex,INFINITE); WaitForSingleObject(Mutex1,INFINITE); buffer1[mov1%BUFFER_SIZE1]=buffer[mov1%BUFFER_SIZE1]; temp->pList->AddString(str+buffer1[mov1%BUFFER_SIZE1]); flag=c_Buffer.FindString(0,(LPCTSTR)buffer[mov1%BUFFER_SIZE1]); if(flag!=CB_ERR) { c_Buffer.DeleteString(flag); } buffer[mov1%BUFFER_SIZE1]="0"; mov1=mov1+1; Sleep(t2); ReleaseMutex(Mutex); ReleaseMutex(Mutex1); ReleaseSemaphore(BufferFull,1,NULL); ReleaseSemaphore(Buffer1Empty,1,NULL); } returntrue;}MOVE2线程函数接口:DWORDWINAPIMove2(LPVOIDpthread){ intflag; lpthreadtemp=(lpthread)pthread; CStringstr=_T(""); while(control){ WaitForSingleObject(Buffer1Empty,INFINITE); WaitForSingleObject(Buffer2Full,INFINITE); WaitForSingleObject(Mutex2,INFINITE); WaitForSingleObject(Mutex1,INFINITE); buffer2[mov2%BUFFER_SIZE1]=buffer1[mov2%BUFFER_SIZE1]; temp->pList->AddString(str+buffer2[mov2%BUFFER_SIZE1]); flag=c_Buffer1.FindString(0,(LPCTSTR)buffer1[mov2%BUFFER_SIZE1]); if(flag!=CB_ERR) { c_Buffer1.DeleteString(flag); } buffer1[mov2%BUFFER_SIZE1]="0"; mov2=mov2+1; Sleep(t2); ReleaseMutex(Mutex1); ReleaseMutex(Mutex2); ReleaseSemaphore(Buffer1Full,1,NULL); ReleaseSemaphore(Buffer2Empty,1,NULL); } returntrue; }消费者线程函数的接口:DWORDWINAPIConsumer1(LPVOIDpthread){ intflag; lpthreadtemp=(lpthread)pthread; CStringstr=_T("消费者:"); while(control){ WaitForSingleObject(Buffer2Empty,INFINITE); WaitForSingleObject(Mutex2,INFINITE); temp->pList->AddString(str+buffer2[out%BUFFER_SIZE1]); flag=c_Buffer2.FindString(0,(LPCTSTR)buffer2[out%BUFFER_SIZE1]); if(flag!=CB_ERR) { c_Buffer2.DeleteString(flag); } buffer2[out%BUFFER_SIZE1]="0"; out=out+1; Sleep(t3); ReleaseMutex(Mutex2); ReleaseSemaphore(Buffer2Full,1,NULL); } returntrue;}4.3其它辅助函数//创立线程响应函数voidCConsuProduThreadDlg::OnCreateThread(){ GetDlgItem(IDC_DESTROY_THREAD)->EnableWindow(true); GetDlgItem(IDC_PRODUCTOR1)->EnableWindow(true); GetDlgItem(IDC_PRODUCTOR2)->EnableWindow(true); GetDlgItem(IDC_PRODUCTOR3)->EnableWindow(true); GetDlgItem(IDC_MOVE1)->EnableWindow(true); GetDlgItem(IDC_MOVE2)->EnableWindow(true); GetDlgItem(IDC_MOVE3)->EnableWindow(true); GetDlgItem(IDC_CONSUMER1)->EnableWindow(true); GetDlgItem(IDC_CONSUMER2)->EnableWindow(true); GetDlgItem(IDC_CONSUMER3)->EnableWindow(true); GetDlgItem(IDC_CREATE_THREAD)->EnableWindow(false); ct1=CTime::GetCurrentTime(); ((CComboBox*)GetDlgItem(IDC_COMBO1))->GetWindowText(buff); control=true; BUFFER_SIZE1=_wtoi(buff.GetBuffer()); ((CEdit*)GetDlgItem(IDC_EDIT1))->GetWindowText(T1); t1=(_tstoi(T1))*1000; ((CEdit*)GetDlgItem(IDC_EDIT2))->GetWindowText(T2); t2=(_tstoi(T2))*1000; ((CEdit*)GetDlgItem(IDC_EDIT3))->GetWindowText(T3); t3=(_tstoi(T3))*1000; Mutex=CreateMutex(NULL,false,NULL); Mutex1=CreateMutex(NULL,false,NULL); Mutex2=CreateMutex(NULL,false,NULL);BufferFull=CreateSemaphore(NULL,BUFFER_SIZE1,BUFFER_SIZE1,NULL);/BufferEmpty=CreateSemaphore(NULL,0,BUFFER_SIZE1,NULL); Buffer1Full=CreateSemaphore(NULL,BUFFER_SIZE1,BUFFER_SIZE1,NULL);Buffer1Empty=CreateSemaphore(NULL,0,BUFFER_SIZE1,NULL); Buffer2Full=CreateSemaphore(NULL,BUFFER_SIZE1,BUFFER_SIZE1,NULL);Buffer2Empty=CreateSemaphore(NULL,0,BUFFER_SIZE1,NULL); }//结束线程响应函数voidCConsuProduThreadDlg::OnDestroyThread(){ GetDlgItem(IDC_CREATE_THREAD)->EnableWindow(true); DWORDcode; control=false; intgct1,gct2,gct3,gct4,gct5,gct6,gct7,gct8,gct9,gct10,gct11,gct12; gct1=GetExitCodeThread(hThread1,&code); gct2=GetExitCodeThread(hThread2,&code); gct3=GetExitCodeThread(hThread3,&code); gct4=GetExitCodeThread(hThread4,&code); gct5=GetExitCodeThread(hThread5,&code); gct6=GetExitCodeThread(hThread6,&code); gct7=GetExitCodeThread(hThread7,&code); gct8=GetExitCodeThread(hThread8,&code); gct9=GetExitCodeThread(hThread9,&code); gct10=GetExitCodeThread(hThread10,&code); gct11=GetExitCodeThread(hThread11,&code); gct12=GetExitCodeThread(hThread12,&code); if(gct1&&code==STILL_ACTIVE){ TerminateThread(hThread1,0); CloseHandle(hThread1); } if(gct2&&code==STILL_ACTIVE){ TerminateThread(hThread2,0); CloseHandle(hThread2); } if(gct3&&code==STILL_ACTIVE){ TerminateThread(hThread3,0); CloseHandle(hThread3); } if(gct4&&code==STILL_ACTIVE){ TerminateThread(hThread4,0); CloseHandle(hThread4); } if(gct5&&code==STILL_ACTIVE){ TerminateThread(hThread5,0); CloseHandle(hThread5); } if(gct6&&code==STILL_ACTIVE){ TerminateThread(hThread6,0); CloseHandle(hThread6); } if(gct7&&code==STILL_ACTIVE){ TerminateThread(hThread7,0); CloseHandle(hThread7); } if(gct8&&code==STILL_ACTIVE){ TerminateThread(hThread8,0); CloseHandle(hThread8); } if(gct9&&code==STILL_ACTIVE){ TerminateThread(hThread9,0); CloseHandle(hThread9); } if(gct10&&code==STILL_ACTIVE){ TerminateThread(hThread10,0); CloseHandle(hThread10); } if(gct11&&code==STILL_ACTIVE){ TerminateThread(hThread11,0); CloseHandle(hThread11); } if(gct12&&code==STILL_ACTIVE){ TerminateThread(hThread12,0); CloseHandle(hThread12); } CTimect2=CTime::GetCurrentTime(); intct11=ct1.GetSecond(); intct22=ct2.GetSecond(); intct33=ct22-ct11; CStringStr=_T("总的运行时间:"); CStringStr1; intt; Str1.Format(TEXT("%d"),ct33); Str+=Str1; c_End.AddString(Str); Str=_T("总共生产的字符为:"); Str1.Format(TEXT("%d"),in); Str+=Str1; c_End.AddString(Str); Str=_T("总共消费的字符为:"); Str1.Format(TEXT("%d"),out); Str+=Str1; c_End.AddString(Str); Str=_T("BUFFER中还剩下的字符为:"); t=in-out; Str1.Format(TEXT("%d"),t); Str+=Str1; c_End.AddString(Str); Str=_T("平均每个BUFFER中字符为:"); t=in-out; t=t/3; Str1.Format(TEXT("%d"),t); Str+=Str1; c_End.AddString(Str); GetDlgItem(IDC_PRODUCTOR1)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR2)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR3)->EnableWindow(false); GetDlgItem(IDC_MOVE1)->EnableWindow(false); GetDlgItem(IDC_MOVE2)->EnableWindow(false); GetDlgItem(IDC_MOVE3)->EnableWindow(false); GetDlgItem(IDC_CONSUMER11)->EnableWindow(false); GetDlgItem(IDC_CONSUMER22)->EnableWindow(false); GetDlgItem(IDC_CONSUMER33)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR11)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR22)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR33)->EnableWindow(false); GetDlgItem(IDC_MOVE11)->EnableWindow(false); GetDlgItem(IDC_MOVE22)->EnableWindow(false); GetDlgItem(IDC_MOVE33)->EnableWindow(false); GetDlgItem(IDC_CONSUMER1)->EnableWindow(false); GetDlgItem(IDC_CONSUMER2)->EnableWindow(false); GetDlgItem(IDC_CONSUMER3)->EnableWindow(false); GetDlgItem(IDC_ClearUp)->EnableWindow(true); }//输出清空函数voidCConsuProduThreadDlg::OnClearUp(){ GetDlgItem(IDC_ClearUp)->EnableWindow(false); c_Productor.ResetContent(); c_Consumer.ResetContent(); c_Buffer.ResetContent(); c_Buffer1.ResetContent(); c_Buffer2.ResetContent(); c_End.ResetContent(); GetDlgItem(IDC_PRODUCTOR1)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR2)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR3)->EnableWindow(false); GetDlgItem(IDC_MOVE1)->EnableWindow(false); GetDlgItem(IDC_MOVE2)->EnableWindow(false); GetDlgItem(IDC_MOVE3)->EnableWindow(false); GetDlgItem(IDC_CONSUMER11)->EnableWindow(false); GetDlgItem(IDC_CONSUMER22)->EnableWindow(false); GetDlgItem(IDC_CONSUMER33)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR11)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR22)->EnableWindow(false); GetDlgItem(IDC_PRODUCTOR33)->EnableWindow(false); GetDlgItem(IDC_MOVE11)->EnableWindow(false); GetDlgItem(IDC_MOVE22)->EnableWindow(false); GetDlgItem(IDC_MOVE33)->EnableWindow(false); GetDlgItem(IDC_CONSUMER1)->EnableWindow(false); GetDlgItem(IDC_CONSUMER2)->EnableWindow(false); GetDlgItem(IDC_CONSUMER3)->EnableWindow(false);}5编码设计5.1开发环境的设置和建立如图所示选择MFC应用程序,输入项目名称后单击“确定”。图1新建项目再选择“基于对话框”,之后单击“完成”建立项目。如图2:图2MFC程序向导开发环境建立完毕。5.2主要程序的代码设计及注释主要的代码及生产者消费者过程实现的代码//生产者:while(control){ WaitForSingleObject(BufferFull,INFINITE);//表示等待缓冲区满,将进程挂起 WaitForSingleObject(Mutex,INFINITE);//等待互斥信号量被释放 buffer[in%BUFFER_SIZE1]=(char)('Z'-rand()%26);//往缓冲区内放资源,用随机字母表示 temp->pList->AddString(str+buffer[in%BUFFER_SIZE1]); c_Buffer.AddString(buffer[in%BUFFER_SIZE1]);//将资源放入缓冲区 in=in+1;//指向下一个可放资源缓冲区 Sleep(t1); ReleaseMutex(Mutex);//释放互斥信号量,允许其它进程访问 ReleaseSemaphore(BufferEmpty,1,NULL);//释放信号量,对BufferEmpty信号量加操作 }//MOVE1while(control){ WaitForSingleObject(BufferEmpty,INFINITE);//表示缓冲区空,则挂起线程 WaitForSingleObject(Buffer1Full,INFINITE); WaitForSingleObject(Mutex,INFINITE);//等待互斥信号量被释放,结束挂起线程 WaitForSingleObject(Mutex1,INFINITE);//等待互斥信号量被释放,结束挂起线程 buffer1[mov1%BUFFER_SIZE1]=buffer[mov1%BUFFER_SIZE1]; temp->pList->AddString(str+buffer1[mov1%BUFFER_SIZE1]); flag=c_Buffer.FindString(0,(LPCTSTR)buffer[mov1%BUFFER_SIZE1]);//统计buffer[mov1]的内容 if(flag!=CB_ERR)//如果返回值正常,则删除该内容 { c_Buffer.DeleteString(flag); } buffer[mov1%BUFFER_SIZE1]="0";//将该缓冲区置为空 mov1=mov1+1;//指向下一个可取资源的缓冲区 //count--; Sleep(t2); ReleaseMutex(Mutex);//释放互斥信号量 ReleaseMutex(Mutex1);//释放互斥信号量,允许其它进程访问 ReleaseSemaphore(BufferFull,1,NULL);//释放缓冲区满信号量,即BufferFull信号量加 ReleaseSemaphore(Buffer1Empty,1,NULL); }//MOVE2:while(control){ WaitForSingleObject(Buffer1Empty,INFINITE);//表示缓冲区空,则挂起线程 WaitForSingleObject(Buffer2Full,INFINITE); WaitForSingleObject(Mutex2,INFINITE);//等待互斥信号量被释放,结束挂起线程 WaitForSingleObject(Mutex1,INFINITE);//等待互斥信号量被释放,结束挂起线程 buffer2[mov2%BUFFER_SIZE1]=buffer1[mov2%BUFFER_SIZE1]; temp->pList->AddString(str+buffer2[mov2%BUFFER_SIZE1]); flag=c_Buffer1.FindString(0,(LPCTSTR)buffer1[mov2%BUFFER_SIZE1]);//统计buffer[out]的内容 if(flag!=CB_ERR)//如果返回值正常,则删除该内容 { c_Buffer1.DeleteString(flag); } buffer1[mov2%BUFFER_SIZE1]="0";//将该缓冲区置为空 mov2=mov2+1;//指向下一个可取资源的缓冲区 Sleep(t2); ReleaseMutex(Mutex1);//释放互斥信号量 ReleaseMutex(Mutex2);//释放互斥信号量,允许其它进程访问 ReleaseSemaphore(Buffer1Full,1,NULL);//释放缓冲区满信号量,即BufferFull信号量加 ReleaseSemaphore(Buffer2Empty,1,NULL); }//消费者while(control){ WaitForSingleObject(Buffer2Empty,INFINITE);//表示缓冲区空,则挂起线程 WaitForSingleObject(Mutex2,INFINITE);//等待互斥信号量被释放,结束挂起线程 temp->pList->AddString(str+buffer2[out%BUFFER_SIZE1]); flag=c_Buffer2.FindString(0,(LPCTSTR)buffer2[out%BUFFER_SIZE1]);//统计buffer[out]的内容 if(flag!=CB_ERR)//如果返回值正常,则删除该内容 { c_Buffer2.Del

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论