欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    电子科大-计算机-实际操作系统实验报告-2014级.doc

    • 资源ID:2783666       资源大小:425.90KB        全文页数:19页
    • 资源格式: DOC        下载积分:8金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要8金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    电子科大-计算机-实际操作系统实验报告-2014级.doc

    #+电 子 科 技 大 学实 验 报 告学生姓名:郫县LBJ 学号:2014666666666 指导教师:温柔可爱的刘杰彦实验地点:主楼A2-413 实验时间:2017年4月22日上午1、 实验室名称:计算机学院主楼机房2、 实验项目名称:进程与资源管理实验分工:郫县LBJ 进程管理设计 郫县小胖子 资源管理设计 郫县威斯布鲁克 进程调度与时钟中断设计3、 实验学时:24、 实验原理: 此处的实验原理在指导书上非常丰富,因此不照搬过来,主要写出所要使用到知识点,具体实现过程中的原理分析见报告第八部分“实验步骤”处。(一) 总体设计系统总体架构如图1所示,最右边部分为进程与资源管理器,属于操作系统内核的功能。要求能够设计与实现一个简单的进程与资源管理器,具有如下功能:完成进程创建、撤销和进程调度;完成多单元 (multi_unit)资源的管理;完成资源的申请和释放;完成错误检测和定时器中断功能。图1 系统总体结构(二) Test shell设计应具有的功能:1、从终端或者测试文件读取命令;2、将用户需求转换成调度内核函数(即调度进程和资源管理器);3、在终端或输出文件中显示结果:如当前运行的进程、错误信息等。(三) 进程管理设计1、进程状态与操作2、进程控制块结构PCB3、主要函数:创建进程、撤销进程(四) 资源管理设计1、主要数据结构RCB2、请求资源3、释放资源(五)进程调度与时钟中断设计关键:使用基于优先级的抢占式调度策略,在同一优先级内使用时间片轮转算法。参考课上ppt: 5、 实验目的:设计和实现进程与资源管理,并完成Test shell的编写,以建立系统的进程管理、调度、资源管理和分配的知识体系,从而加深对操作系统进程调度和资源管理功能的宏观理解和微观实现技术的掌握。6、 实验内容:设计与实现一个简单的进程与资源管理器,要求具有如下功能:完成进程创建、撤销和进程调度;完成多单元 (multi_unit)资源的管理;完成资源的申请和释放;完成错误检测和定时器中断功能。通过编写测试脚本(test shell)来完成对进程与资源管理器的测试。7、 实验环境(设备、元器件):Windows 7、Visual Studio 20158、 实验步骤:(一) 系统功能需求分析:(二) 总体框架设计:1、 具体原理和总体工作流程分析:首先,通过test shell从测试文件中读入各种命令。然后,对命令进行分析,将用户的需求转换成调度内核函数,也就是说,通过调度进程和资源管理器,实现创建进程、撤销进程、进程调度、对资源进行管理、申请和释放资源、检测错误和定时器中断等功能,从而模拟一个操作系统对进程进行调度和对资源进行管理的过程。最后,在终端或者输出文件中,把一系列操作后的结果显示出来,包括当前运行的进程、错误信息等。2、 相关方法和算法:(1) C语言中的结构struct,用来实现PCB、RCB等(2) C语言中的指针、链表操作,用来实现将PCB和RCB加入队列尾部、从队列中删除、转移至阻塞队列等操作,以及进程的调度执行等。本实验中我们采用的带头结点的链表来实现各种操作。(3) 基于优先级的调度算法、时间片轮转调度算法、抢占式调度算法的综合应用。3、 模块调用关系:本实验中,我们组共编写了三个头文件(pcb.h、rcb.h、test_shell_data.h)和四个源文件(main.c、pcb.c、rcb.c、test_shell_data.c),因此可以分为主函数设计模块、进程管理设计模块、资源管理设计模块和test shell设计模块。在主函数模块中,需要调用其他三个模块,如创建进程、展示父子子进程等操作,需要调用进程管理设计模块;调度算法的执行、展示各种队列等,需要调用test shell设计模块;在进程管理设计模块中,像销毁PCB等操作,需要执行对RCB的释放,则需调用test shell设计模块;在资源管理设计模块中,提供一些最小的操作,不调用其他模块;在test shell设计模块中,设计到对资源和进程的各种操作,需要调用资源管理设计模块和进程管理设计模块。(三) 进程管理设计模块详细设计(本部分我负责实现)我们的计划是在在进程管理设计模块中,实现关于进程的各种最基础的结构和操作,具体包括:实现PCB结构体、PCB链表、PCB子节点链表;实现对PCB链表的初始化、对子节点链表的初始化、新建PCB、对PCB链表中进行删除、插入、移除(不free)、从等待和阻塞队列中获取PCB得知、打印当前PCB父节点、打印当前PCB父节点、打印当前PCB子节点链表、插入子队列的尾部、从子队列尾部删除。1、 进程状态与操作(1) 进程状态共ready/running/blocked三种状态,通过结构struct实现,代码如下:struct int running; int blocked; int ready;PCB_STATUS; /定义pcb状态的三种情况(2) 进程操作:在本次实验中,将会读进程进行以下操作,结合这些操作的具体内容和所学知识,很容易考虑到通过链表来实现这些操作。创建(create): (none) -> ready撤销(destroy): running/ready/blocked -> (none)请求资源(Request): running -> blocked (当资源没有时,进程阻塞)释放资源(Release): blocked -> ready (因申请资源而阻塞的进程被唤醒)时钟中断(Time_out): running -> ready调度:ready -> running / running ->ready2、 主要数据结构实现:(1)进程控制块结构PCB进程控制块PCB是进程存在的唯一标识,并且常驻内存,进程控制块中有许多信息,在本次实验中,根据我们的需求,所设计的进程控制块结构如下:结合实验指导书,我们通过结构struct实现进程控制块结构PCB,包含以下信息:PID(name)Other_resources /: resource which is occupiedStatus: Type & List/ type: ready, block, running., /List: RL(Ready list) or BL(block list)Creation_tree: Parent/ChildrenPriority: 0, 1, 2 (Init, User, System)主要代码及注释如下:struct PCB /pcb结构体 char name64; /Pname unsigned int pid; /Pid struct RCB_LIST* rcb_list; /Other resources struct PCB_LIST* parent_pcb; /父进程 struct CHILD_PCB_LIST* child_pcb; /子进程 int state; /Type&List int priority; /0,1,2;(3) 实现一个PCB的链表,方便后面的操作:struct PCB_LIST /pcb链表 struct PCB pcb; struct PCB_LIST * next_pcb;(4) 实现PCB的子节点链表:struct CHILD_PCB_LIST /pcb子节点链表 struct PCB_LIST* node; struct CHILD_PCB_LIST* next_node;3、 主要操作设计实现过程(1) 初始化PCB链表(添加了头结点):void init_pcb_list(struct PCB_LIST *list) if (*list) return; struct PCB_LIST *p = (struct PCB_LIST*)malloc(sizeof(struct PCB_LIST); p->next_pcb = NULL; memset(p, NULL, sizeof(struct PCB); *list = p;(2) 初始化子节点链表:void init_child_pcb_list(struct CHILD_PCB_LIST *list) if (*list) return; struct CHILD_PCB_LIST *p = (struct CHILD_PCB_LIST*)malloc(sizeof(struct CHILD_PCB_LIST); p->next_node = NULL; memset(p, NULL, sizeof(struct CHILD_PCB_LIST); *list = p;(3) 创建一个新的PCB:struct PCB_LIST* create_pcb(char* name, unsigned int pid, int state, unsigned int priority,struct PCB_LIST* parent_pcb) struct PCB pcb; strcpy(pcb.name,name,strlen(name); pcb.pid = pid; pcb.rcb_list = NULL; pcb.state = state; pcb.priority = priority; pcb.parent_pcb = parent_pcb; pcb.child_pcb = NULL; struct PCB_LIST* pcb_node = (struct PCB_LIST*)malloc(sizeof(struct PCB_LIST); pcb_node->pcb = pcb; pcb_node->next_pcb = NULL; return pcb_node;(4) 从PCB链表中进行删除:void destory_from_pcb_list(struct PCB_LIST* list, char *name) struct PCB_LIST* pr_temp, *temp; pr_temp = temp = list; int ret = 1; while (temp) if (!strcmp(name, temp->pcb.name) && ret) release_resource(temp); pr_temp = temp = list; ret = 0; if (!strcmp(name, temp->pcb.name) pr_temp->next_pcb = temp->next_pcb; free(temp); return; pr_temp = temp; temp = temp->next_pcb; (5)插入pcb链表:void insert_into_pcb_list(struct PCB_LIST* list, struct PCB_LIST*node) if (!*list) init_pcb_list(list); struct PCB_LIST *pr_temp, *temp; pr_temp = temp = *list; while (temp) pr_temp = temp; temp = temp->next_pcb; pr_temp->next_pcb = node;(5) 从PCB链表中移除,并不释放该PCB占用的空间:void delete_from_pcb_list(struct PCB_LIST* list, char *name) struct PCB_LIST* pr_temp, *temp; pr_temp = temp = list; while (temp) if (!strcmp(name, temp->pcb.name) pr_temp->next_pcb = temp->next_pcb; return; pr_temp = temp; temp = temp->next_pcb; (6) 从等待和阻塞队列中获取PCB的地址:struct PCB_LIST* get_pcb(char* name) struct PCB_LIST* temp; for (int i = 2; i >= 0; i-) temp = READY_LISTi->next_pcb; while (temp) if (!strcmp(temp->pcb.name, name) return temp; temp = temp->next_pcb; if (BLOCKED_LIST) temp = BLOCKED_LIST->next_pcb; while (temp) if (!strcmp(temp->pcb.name, name) return temp; temp = temp->next_pcb; return NULL;(7) 打印当前PCB的父节点void show_pcb_parent(struct PCB_LIST* node) printf("%s parent node is %s n", node->pcb.name, node->pcb.parent_pcb->pcb.name);(8) 打印当前PCB的子节点链表void show_pcb_child(struct PCB_LIST* node) printf("%s child is ", node->pcb.name); struct CHILD_PCB_LIST* temp = node->pcb.child_pcb; if (temp) temp = temp->next_node; while (temp) printf(" -> |%s|", temp->node->pcb.name); temp = temp->next_node; printf("n");(9) 插入子队列的尾部void insert_into_child_pcb_list(struct CHILD_PCB_LIST* list, struct PCB_LIST*node) if (!*list) init_child_pcb_list(list); struct CHILD_PCB_LIST *pr_temp, *temp; pr_temp = temp = *list; while (temp) pr_temp = temp; temp = temp->next_node; struct CHILD_PCB_LIST *p = (struct CHILD_PCB_LIST*)malloc(sizeof(struct CHILD_PCB_LIST); p->node = node; p->next_node = NULL; pr_temp->next_node = p;(10) 从子队列尾部进行删除void delete_from_child_pcb_list(struct CHILD_PCB_LIST* list, char *name) struct CHILD_PCB_LIST* pr_temp, *temp; if (!list) return; pr_temp = list; temp = pr_temp->next_node; while (temp) if (!strcmp(name, temp->node->pcb.name) pr_temp->next_node = temp->next_node; return; pr_temp = temp; temp = temp->next_node; (四) 其他模块设计(组内其他人设计)1、 Test shell设计Test shell将调度我们设计的进程与资源管理器,从而完成测试,具有以下功能:(1)从终端或者测试文件读取命令;(2)将用户需求转换成调度内核函数(即调度进程和资源管理器);(3)在终端或输出文件中显示结果:如当前运行的进程、错误信息等。2、 资源管理设计与进程管理设计的思路和流程相似,首先是设计好各类数据结构,包括RCB结构体、RCB等待队列链表、系统RCB结构体、系统RCB链表、RCB链表。之后是实现好各类与RCB有关的基础操作,包括初始化前面设计的各种链表、新建RCB,以及对链表进行插入、删除、移除等操作,还有显示RCB队列的操作。3、 实验进程调度与时钟中断设计核心思想即时间片轮转调度算法、优先级调度算法、抢占式算法的综合应用,设计到对前面各模块的调用。9、 实验数据及结果分析:将实验指导书中给出的测试命令放到测试文件test.txt中,程序从该文件读取命令,并将执行结果输出到屏幕,如下图所示:上图结果与试验指导书中给出的预期输出结果是一致的,说明实验成功。具体的结果分析:为了更易于观察,我们可以注释掉读文件的操作,让程序从键盘输入读取命令,每步命令的解释及相关执行结果截图如下:cr x 1 /创建优先级为1的进程x,应显示“* the x is running”cr p 1 /创建优先级为1的进程p,应显示“* the x is running”cr q 1 /创建优先级为1的进程q,应显示“* the x is running”cr r 1 /创建优先级为1的进程r,应显示“* the x is running”经过以上四条指令,就绪队列中优先级1的队列中应依次为x、p、q、r,可用资源数应该都是总的资源数,执行结果、就绪队列、资源队列情况见下图:to /一个时间片结束,应去执行p,显示“* the p is running”同时,x进程PCB将进入优先级为0的就绪队列,如下图:req 2 1 /为当前进程x申请1个R2资源,显示不变输出显示不变,但是可用资源数目会发生变化,如下图:to /一个时间片结束,应去执行q,显示“* the q is running”req R3 3 /为当前进程q申请3个R3资源,显示不变过程中截图如下,可用资源数目进一步减小: to /一个时间片结束,应去执行r,显示“* the r is running”req R4 3 /为当前进程x申请3个R4资源,显示不变to /一个时间片结束,应去执行优先级为0的就绪队列中的第一个进程x,显示“* the x is running”to指令后截图如下,包括此时就绪队列的情况,所有进程的PCB都在优先级为0的就绪队列中:to /一个时间片结束,应去执行p,显示“* the p is running”,x移到优先级0就绪队列的结尾新的优先级为0的就绪队列截图如下:下面的两条指令分别为当前进程申请资源,申请不到足够的资源,相应进程则会进入阻塞队列。req R3 1 /p申请1个R3,但R3已经全部给了q,因此p被阻塞,进入阻塞队列,当前转去执行原来在p后的q进程,显示“* the q is running”显示及阻塞队列如下: req R4 2 /q申请2个R4,但R4已经只剩下1个,因此q被阻塞,进入阻塞队列,当前转去执行原来在q后的r进程,显示“* the r is running”req R2 2 /r申请2个R2,但R2已经只剩下1个,因此r被阻塞,进入阻塞队列,当前转去执行原来在r后的x进程,显示“* the x is running”以上两步过后,阻塞队列及就绪队列截图如下:to /一个时间片结束,就绪队列中只有x,因此仍然执行x,显示“* the x is running” de q /撤销q进程,将释放q进程占用的3个R3资源,前面因为申请不到R3资源而被阻塞的p进程将重新回到就绪队列,位于x的后面,显示不变to /一个时间片结束,应去执行p,显示“* the p is running”to /一个时间片结束,应去执行x,显示“* the x is running”经过以上四条指令,就绪队列中优先级0的队列中应依次为x、p,阻塞队列中应该只有r,如下图: 至此,详细的每步分析完毕,实验成功。10、 实验结论:本次实验过程中,我组成员分工明确,在熟练掌握课堂知识的基础上,使用c语言模拟了操作系统对进程和资源的管理,成功地实现了基于优先级和时间片轮转的抢占式调度算法,实验结果与预期相同,很好地完成了本次实验11、 总结及心得体会:(1) 链表、指针的掌握和应用十分重要;(2) 将总的任务划分成各个模块,实现各个模块后再总体实现,可以提高效率;(3) 在程序中增加一些出错处理的提示信息,有利于提高调试过程的效率。12、 对本实验过程及方法、手段的改进建议:可以增加难度更大的功能,如模拟进程中断后,返回断点继续执行等。 报告评分: 指导教师签字:电 子 科 技 大 学实 验 报 告学生姓名:郫县LBJ 学号:2014666666666 指导教师:温柔可爱的刘杰彦实验地点:主楼A2-413 实验时间:2017年6月2日一、 实验室名称:计算机学院主楼机房二、 实验项目名称:内存地址转化实验三、 实验学时:2四、 实验原理:(一) 逻辑地址到线性地址的转换1、 逻辑地址、段标识符、索引号、GDT、LDT、T1字段、段描述符、Base字段、线性地址等概念;2、 GDTR、LDTR等相关寄存器知识;(以上两条在实验指导书中很详细,篇幅较长,不做粘贴了)3、 逻辑地址到线性地址的转换过程从逻辑地址到线性地址的转换过程,如下图所示(以T1=1为例,此时从段选择符中分离出段描述符和T1字段,T1=1,表明段描述符存放在LDT中);(1)从GDTR中获得GDT的地址,从LDTR中获得LDT在GDT中的偏移量,查找GDT,从中获取LDT的起始地址;(2)从DS中的高13位获取DS段在LDT中索引位置,查找LDT,获取DS段的段描述符,从而获取DS段的基地址;(3)根据DS段的基地址段内偏移量,获取所需单元的线性地址。、(二) 线性地址到物理地址的转换1、 物理地址的概念;(不做粘贴了)2、 将线性地址转换成物理地址的步骤:(1)、因为页目录表的地址放在CPU的cr3寄存器中,因此首先从cr3中取出进程的页目录表地址(操作系统负责在调度进程的时候,已经把这个地址装入对应寄存器);(2)、根据线性地址前十位,在页目录表中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不是页的地址,而是一个页表的起始地址。(3)、查找页表,根据线性地址的中间十位,在页表中找到数据页的起始地址;(4)、将页的起始地址与页内偏移量(即线性地址中最后12位)相加,得到最终我们想要的物理地址;五、 实验目的:(1)掌握计算机的寻址过程(2)掌握页式地址地址转换过程(3)掌握计算机各种寄存器的用法六、 实验内容:本实验运行一个设置了全局变量的循环程序,通过查看段寄存器,LDT表,GDT表等信息,经过一系列段、页地址转换,找到程序中该全局变量的物理地址。七、 实验器材(设备、元器件):计算机、Linux内核(0.11)+Bochs虚拟机八、 实验步骤:1、 点击bochs.exe安装bochs。2、 拷贝bootimage-0.11-hd、diska.img、hdc-0.11-new.img、mybochsrc-hd.bxrc至安装目录。3、 在安装目录中找到bochsdbg.exe程序,并运行。4、 在弹出的界面中,点击“Load”加载配置文件“mybochsrc-hd.bxrc”。随后,点击“Start”启动Bochs虚拟机。 5、 虚拟机启动后,出现两个窗口,一个为Bochs控制窗口(Console),另一个为Linux操作系统运行窗口(主显示窗口Display)。6、 在控制窗口输入“c”后回车,加载Linux操作系统。 7、 在Linux操作系统中,使用vi工具编写mytest2.c源文件。随后执行“gcc -o mytest2 mytest2.c”命令编译并生成“mytest2”可执行文件。实验中所使用的C语言代码如下:#include <stdio.h>int j = 0x123456;int main() printf("the address of j is 0x%xn", &j); while(j); printf("program terminated normally!n"); return 0;8、 在Linux操作系统中,运行“./mytest2”可执行文件,结果如下:由此可以看出,在“while(j)”处进入死循环,程序的第二条输出语句不会被执行。9、 先关闭bochs和虚拟机,再右键mybochsrc-hd.bxrc,选择debugger,点击start,在console界面输入c后回车,在display界面中再次输入./mytest2,运行之前写好分程序,再回到console界面进行Ctrl+c操作: 10、 在控制窗口中输入sreg命令,查看段的具体信息。根据ds段的信息是可以确定索引号为标蓝的13位,即索引号为02H,TI为标红的1位,对应TI=1,因此可知段描述符放在LDT中,并且为LDT表的第三项。0x0017=0000 0000 0001 0111B11、 查看LDTR寄存器,其中存放了LDT在GDT的位置,可知索引号为标蓝的13位,即索引为0DH,表示LDT起始地址存放在GDT的第14项。0x0068=0000 0000 0110 1000B12、 查看GDTR寄存器,其中存放了GDT在内存中的起始地址5CB8H:13、 由上图可知,GDT在内存中的起始地址为5CB8H,因为每一个段描述符由8个字节组成,则LDT的首地址为:(GDTR)+0x0D*8 = 0x5CB8 + 0x0D*8 = 0x5D20执行xp /2w 0x5cb8+0x0d*8,查看GDT中对应的表项,得到LDT段描述符: 根据原理中的数据结构,由上图可知LDT的基址为:0x00fd92d0。14、 因为段描述符在LDT表中的偏移量为2,,所以执行xp /2w 0x00fd92d0+2*8,查看LDT中第3项段描述符,即ds段的描述符信息,应与ds寄存器(dl、dh)中的数值完全相同,比较见下图: 与此同时,根据原理中的数据结构和表项,由上图计算出DS段基址为0x1000 0000,与用sreg得到信息一致:15、 程序运行显示j的偏移地址为0x3004:计算线性地址0x10000000+0x3004 = 0x10003004,换算为二进制,并按照10-10-12比特进行划分:0x10003004=0001 0000 0000 0000 0011 0000 0000 0100 B可知页目录索引为1000000B,即64;页表索引为11b,即3;页内偏移为100B,即4。16、 使用creg查看寄存器CR3 值为0,即页目录表的起始地址为0。使用xp /w 64*4,查看PDE为0x00fa6027, 0x00fa6027 = 0000 0000 1111 1010 0110 0000 0010 0111 B将标红的为20位下一级索引,左移12位,得到下一级索引为0x00fa6000:17、 执行xp /w 0x00fa6000+3*4,查看PTE为0x00fa3067:同理,下一级索引为0x00fa3000,得到物理地址为0x00fa3000+4。18、 使用xp /w 0x00fa3000+4,内容为0x00123456,与C语言源程序中为J设置的值相同:19、 执行setpmem 0x00fa3004 4 0,设置0x00fa5004开始的四个字节均为0,并检查是否成功: 由上图可知,设置成功。20、 在Console输入c继续运行程序,在Display显示程序正常结束,实验成功:九、 实验数据及结果分析:修改j的值为0后,再运行程序,程序可以正常结束,显示“program terminated normally!”,实验成功(每一步的具体分析及原理见报告第八部分,图文并茂,非常漂亮)。十、 实验结论:通过本次实验,结合计算机寻址过程、页式地址转换过程、计算机各种寄存器的用法等知识,成功寻找到变量的存储位置,并对变量的值进行修改,从而使程序可以正常结束,成功地完成了实验要求。十一、 总结及心得体会:(一)通过这次实验接触到了使用bochs这一虚拟机来运行linux内核,开拓了眼界;(二)加深了对计算机的寻址过程、页式地址转换过程、计算机各寄存器的用法等知识的理解和掌握;(三)在紧张的期末复习阶段用自习的电脑再做一遍实验,写一下实验报告,截一截图,复习知识的同时放松了身心。十二、 对本实验过程及方法、手段的改进建议:可以跟汇编语言结合起来,加强学科的交叉性,还能同时巩固汇编语言。 报告评分: 指导教师签字:

    注意事项

    本文(电子科大-计算机-实际操作系统实验报告-2014级.doc)为本站会员(小**)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开