操作系统课程设计实验报告

上传人:学** 文档编号:87382629 上传时间:2022-05-09 格式:DOCX 页数:15 大小:100.69KB
收藏 版权申诉 举报 下载
操作系统课程设计实验报告_第1页
第1页 / 共15页
操作系统课程设计实验报告_第2页
第2页 / 共15页
操作系统课程设计实验报告_第3页
第3页 / 共15页
资源描述:

《操作系统课程设计实验报告》由会员分享,可在线阅读,更多相关《操作系统课程设计实验报告(15页珍藏版)》请在装配图网上搜索。

1、操作系统课程设计报告班级:团队成员:目录 .错误 !未定义书签。一、 实验要求:建立线程系统 .错误 !未定义书签。1.1Task 2.1实现文件系统调用 .31.1.1题目要求 .31.1.2题目分析与实现方案 .31.1.3关键点与难点 .41.1.4实现代码 .41.2Task 2.2 完成对多道程序的支持 .51.2.1题目要求 .51.2.2题目分析与实现方案 .51.2.3关键点与难点 .61.2.4实现代码 .71.3Task 2.3 实现系统调用 .71.3.1题目要求 .71.3.2题目分析与实现方案 .81.3.3关键点与难点 .91.3.4实现代码 .91 /141.4T

2、ask 2.4 实现彩票调度10题目要求10题目分析与实现方案10关键点与难点11实现代码11二、测试结果2错误 !未定义书签。2/14一、实验要求: 多道程序设计1.1 Task 2.1 实现文件系统调用题目要求实现文件系统调用(创建,打开,读,写,关闭, unlink),在 syscall.h 中有详细的记录,可以看一下 UserProcess.java中的代码,最好把你自己写的系统调用的代码也放在这里。记住你不是在实现一个文件系统,而是在给用户进程获取我们给你定义好的文件系统的能力。我们在 start.s 里为你提供了用户进程进行系统调用所必需的汇编代码。( SYSCALL会为每个系统调

3、用产生汇编代码)。其中 Unlink 为删除目录相并减少一个连接数, 如果链接数为 0 并且没有任何进程打开该文件,该文件内容才能被真正删除,但是若又进程打开了该文件,则文件暂时不删除直到所有打开该文件的进程都结束时文件才能被删除。题目分析与实现方案系统共提供了七个系统调用:halt (停机 , 已经提供 ),creat (创建并打开磁盘文件),open (打开磁盘文件 ),read (读 IO, 可以是磁盘或屏幕 ),write (写 IO),close (关闭 IO),unlink (删除磁盘文件 )。要确保如下几点:1)稳定性 , 不能因为一个进程的非法系统调用就使操作系统崩溃 , 而应

4、该 返回错误代码。2)halt()调用只能由第一个进程(root process) 执行。3)系统调用需要读写内存时, 通过 readVirtualMemory和 writeVirtualMemory进行。4)文件名以 null 结尾 , 不超过 256 字符。5)如果系统调用出错 , 应返回 -1。6)为每个打开的 IO 文件分配一个“文件描述符” , 用整数表示 . 每个进 程最多可以拥有 16 个。其中 0 和 1 应分配给标准输入和标准输出 (即屏幕 ),这由 SynchConsole 类管理。不同进程可以用相同的文件描述符处理不同的文件。7)Nachos已经提供了一个简单的文件系统(

5、 Machine 包中), 通过 ThreadedKernel. 访问。8)系统不需要考虑文件访问的互斥等问题。方案:1)create 系统调用:1.根据传入的 ,从虚拟内存中读出文件名2.判断文件名是否存在,即处是否有文件名3.如果不存在,直接创建。先去找合适的位置,如果已经有大于 16 个,退出,否则创建,创建只需调用的 open 即可(传入的布尔值 create 为 true)2)open 系统调用:1.根据传入的,从虚拟内存中读出文件名3/142.判断文件名是否存在,即处是否有文件名3.先去找合适的位置,如果已经有大于 16 个,退出,否则创建只需调用的 open 即可(传入的布尔值

6、create 为 false)4.维护本地描述符表3)read 系统调用Read系统调用的三个参数依次为: 文件描述符 , 写入的内存地址 , 读取的字节数。在 Read系统调用中进行如下操作:1.如果打开文件大于16 个或者小于 0 个,或者打开文件列表为空,直接返回。2.创建数组 temp,把文件内容读入temp,求出读出数据长度3.若读出数据小于0 即为出错,返回。4.把该数据写入虚拟内存。5.返回写入内存的字节数4)write 系统调用Write 系统调用的三个参数依次为 : 文件描述符 , 读内存的地址 , 写入文件的字节数。在 Write 系统调用中进行如下操作:1.如果打开文件大

7、于16 个或者小于 0 个,或者打开文件列表为空,直接返回。2.创建数组 temp,把虚拟内存中的内容读入 temp, 得到读出数据长度 3.若读出数据小于 0 即为出错,返回。4.把该数据写入磁盘。5.若写的数据长度小于读出的数据长度,则错误,返回错误代码5)close 系统调用Close系统调用的唯一一个参数为文件描述符。在 Close系统调用中进行如下操作:1.如果打开文件大于16 个或者小于 0 个,或者打开文件列表为空,直接返回。2.如果不存在,关闭出错3.否则关闭,把 openfile 数组中中的位置置为06)unlink 系统调用:1.根据传入的,从虚拟内存中读出文件名。2.如果

8、不存在,不必删除3.如果存在,就删除,出错返回错误代码一般地,在Unlink 调用中只需读取文件名并执行方法删除文件即可。但是,一个文件可能被多个进程打开而不能立即删除,必须等所有打开这个文件的进程都关闭该文件后才能删除。因此,在Close系统调用中还要增加如下内容:若文件关闭后它在全局文件表中已经不存在且文件名在删除队列中,则此时执行删除文件操作,并将文件从删除队列中移出。关键点与难点注意:以上系统调用只是在一般情况下函数的执行流程。为了提高系统的健壮性 , 在系统调用中还要进行下列错误检查:a)文件名长度不得超过256 字符 , 不得含有非法字符或空。b)打开 , 创建文件时 , 局部描述

9、符表不能满。c)的操作返回值必须正确。d)readVirtualMemory 和 writeVirtualMemory 的返回值必须正确。4/14实现代码private int handleCreate (int ) /限定文件名长度,readVirtualMemoryString读取文件名String= readVirtualMemoryString(, 256);if ( = null )return -1;int= findEmpty ();if ( = -1)return -1;else / ThreadedKernel.() 打开文件 (第二个参数为true 表示创建新文件)open

10、file = ThreadedKernel .open (,true );return ;private int handleOpen (int ) / 限定文件名长度String= readVirtualMemoryString(, 256);if ( = null )return -1;int= findEmpty ();/ 为空,报错。 if ( = -1)return -1;else openfile = ThreadedKernel .open (,false );return ;private int handleRead (int , int bufferAddress , in

11、t length ) / 如果打开文件大于 16个或者小于 0个,或者打开文件列表为空,直接返回。if ( 15 | 0| openfile = null ) return -1;byte temp = new byte length ;/ 通过 Open 读取文件内容int readNumber = openfile . read (temp , 0, length );if (readNumber 15 | 0| openfile = null ) return -1;/ 文件未打开 ,出错/创建数组 temp ,把虚拟内存中的内容读入temp, 得到读出数据长度byte temp = n

12、ew byte length ;int readNumber = readVirtualMemory(bufferAddress , temp );/ 若读出数据小于 0即为出错,返回。 if (readNumber = 0)return 0;/ 把该数据写入磁盘。int writeNumber= openfile . write (temp , 0, length );/ 若写的数据长度小于读出的数据长度,则错误,返回错误代码5/14if (writeNumber 15 | 0| openfile = null )/ 文件不存在,关闭出错return -1;/ 否则关闭,把 openfile

13、 数组中中的位置置为 0 openfile . close();openfile = null ; return 0;private int handleUnlink (int ) / 根据传入的,从虚拟内存中读出文件名。String= readVirtualMemoryString(, 256);/ 如果不存在,不必删除if ( = null )return 0;/ 如果存在,就删除,出错返回错误代码if (ThreadedKernel .remove ()return 0;elsereturn -1;1.2 Task 2.2 完成对多道程序的支持题目要求完成对多道程序的支持。已给出的代码只

14、能一次运行一个进程,而你要使它支持多道程序。从分配物理内存入手,不同的进程在在内存使用上不会重叠。用户程序不会使用 malloc()或 free(),既用户没有动态内存分配的需求。也就是说当进程创建,你完全知道它需要的内存大小,你要为进程栈分配合适的页大小,8 页就足够了。建议保持空闲物理页的全局链接列表(UserKernel class的一部分),访问列表时会用到同步。解决方案为新进程分配页时务必有效的使用内存。只在连续块上分配内存是不可取的的,你的方案必须用到空闲内存池中的缝隙。保持每个进程的页表,页表保持了用户虚拟地址到物理地址的映射。TranslationEntry class 代表了

15、一个虚拟到物理的页转换。如果页来自COFFsection,那么在TranslationEntry.readOnly 文件中要将其标记为只读。这个方法失败不会抛出异常,它总会返回传送的位数,即使是零。修改 UserProcess.loadSections(),根据所需为进程分配页数。用你决定的分配规则。 这个方法还要为进程开启页表 structure ,这样进程就被加载到当前物理内存页中。题目分析与实现方案Nachos 为不同进程应分配完全不同的物理内存,但不支持动态内存分配, 所以需要分配的内存在装入程序时就可以确定了(代码 , 数据 , 堆栈部分 )。故在装入6/14程序时就为每个进程一次性

16、分配固定的物理内存, 在进程结束时收回它们。这里还需要实现如下简单的虚拟内存方案 : 每个进程的地址空间是连续的虚拟内存 , 但这些连续的虚拟页面在物理内存中却不一定是连续的。 这个方案的简单之处在于 , 虚拟空间的总容量和物理空间的总容量相等 , 映射机制只是从虚拟内存到物理内存的一一映射。除了内存的分配 , 内存的读写也要体现出映射机制。方案:页表 pageTable以虚拟页号为下标,其中的每个项目是一个 machine.TranslationEntry 类型的对象,存放了一个页的下列信息:物理页号,虚拟页号,是否有效,是否只读,是否被用过,是否脏。在UserKernel中定义一个全局队列

17、memoryLinkedList用于存放当前空闲的物理页号,一个保护内存互斥访问的锁 allocateMemoryLock。开始时,memoryLinkedList包括所有的物理页面。 当启动新进程时 , UserProcess.load负责从磁盘装入进程。过程 UserProcess.loadSections完成如下操作:先获得 allocateMemoryLock,锁定内存。该进程需要的页面数已知, 保存在 numPage 变量中。与 memoryLinkedList 比较,判断空余存储空间是否足够。分配物理页 (UserKernel. allocatePages)时从 memoryLin

18、kedList 中出队相应数量的页面 (返回的是物理页号的数组 )。2)整个需要装入的进程是一个 machine.CoffSection类型的对象, 包括若干个页。 在 loadSection 中,在释放 allocateMemoryLock 前应该创建一个页表。3)得到可用的物理页号后,就装入所有的页,为段中每个虚拟页在 pageTable 中创建一个新的 TranslationEntry对象并为其赋上相应的虚拟页号和物理页号等信息,然后将原来 section 对象的读写权限等转移, 然后并调用 CoffSection.loadPage将页的内容读入。读入时进行物理地址和逻辑地址的关联,然后

19、把程序的每一块按照顺序对应于物理地址导入到内存中。完成了题目的“保持物理页的全局链接表”的要求。4) 在进程结束时,对于 页表中所有的页面,只要将其虚拟页号放入memoryLinkedList 队列。UserProcess.readVirtualMemory读虚拟内存。读内存时,要先利用页表将逻辑地址转换为物理地址然后再将内存数据复制到数组中。类似地,UserProcess.writeVirtualMemory 写虚拟内存,其方法与readVirtualMemory 类似,要先利用页表将逻辑地址转换为物理地址然后再将数组数据复制到内存中,并注意取页面时要检查页面是否为只读。关键点与难点在 lo

20、adSection 中,在导入 coff 之前应该创建一个页表,进行物理地址和逻辑地址的关联,然后把程序的每一块按照顺序对应于物理地址导入到内存中。这样就完成了题目的“保持物理页的全局链接表”的要求。读写内存时,要先利用页表将逻辑地址转换为物理地址然后再将内存数据复制到数组中,取页面时要检查页面是否为只读。读写内存时要注意判断内存是否已满,数组是否已满,是否有错误参数(比如写入数据的长度 0),另外题目要求无论读写是否成功都不报错,而是返回读写数据的长度。实现代码7/14UserKernel :/ 保护内存互斥访问的锁public static Lock allocateMemoryLock;

21、/ 全局队列 ,用于存放当前空闲的物理页号public static LinkedList memoryLinkedList;UserProcess:protectedboolean loadSections () / 获取分配内存的锁,锁定内存UserKernel .allocateMemoryLock.acquire ();/ 判断能否装载if (numPages UserKernel .memoryLinkedList .size() coff .close();Lib.debug (dbgProcess, tinsufficient physical memory);UserKerne

22、l .allocateMemoryLock.release();/ 返回装载失败 return false;/ 创建页表pageTable = new TranslationEntry numPages;for (int i = 0; i numPages; i+) int nextPage = UserKernel .memoryLinkedList .remove ();pageTablei = new TranslationEntry (i, nextPage, true , false,false , false );/ 释放锁UserKernel .allocateMemoryLoc

23、k.release();for (int s = 0; s coff .getNumSections (); s+) CoffSection section = coff .getSection (s);/获得 sectionLib.debug (dbgProcess, tinitializing + section .getName ()+ section ( + section .getLength () + pages) ); for (int i = 0; i section .getLength (); i+) int vpn = section .getFirstVPN() + i

24、;/ 标记只为已读pageTablevpn .readOnly = section .isReadOnly();section .loadPage(i, pageTable vpn. ppn);return true ;public int readVirtualMemory(int vaddr , byte data , int offset , int length ) /保证偏移量与长度都为正,偏移量+长度 = 0 & length = 0& offset + length (pageSize * numPages - vaddr ) /判断能否读取length = pageSize *

25、 numPages - vaddr ;if (data .length - offset length )length = data .length - offset ;int transferredbyte= 0;do int pageNum = Processor.pageFromAddress (vaddr + transferredbyte );if (pageNum = pageTable .length )return 0;int pageOffset = Processor .offsetFromAddress (vaddr+ transferredbyte );int left

26、Byte = pageSize - pageOffset ;int amount = Math .min(leftByte , length - transferredbyte );int realAddress = pageTablepageNum .ppn * pageSize + pageOffset ;System.arraycopy (memory , realAddress , data, offset+ transferredbyte , amount );8/14transferredbyte= transferredbyte+ amount ; while (transfer

27、redbyte = 0 & length = 0& offset + length (pageSize * numPages - vaddr )length = pageSize * numPages - vaddr ;if (data .length - offset length )length = data .length - offset ;int transferredbyte= 0;do int pageNum = Processor.pageFromAddress (vaddr + transferredbyte ); if (pageNum = pageTable .lengt

28、h )return 0;int pageOffset = Processor .offsetFromAddress (vaddr+ transferredbyte );int leftByte = pageSize - pageOffset ;int amount = Math .min(leftByte , length - transferredbyte );int realAddress = pageTablepageNum .ppn * pageSize + pageOffset ; System.arraycopy (data , offset + transferredbyte ,

29、 memory ,realAddress , amount );transferredbyte= transferredbyte+ amount ; while (transferredbyte length ); return transferredbyte ;1.3 Task 2.3实现系统调用题目要求实现系统调用 (exec, join, and exit, 同样在 syscall.h)。此外,所有通过寄存器来 Exec 和 加 入 的 地 址 是 虚 拟 地 址 。 你应 该 使 用 readVirtualMemory 和 readVirtualMemoryString 在内核和用户进

30、程之间传递内存。 同样,你必须防止这些系统调用。注意,子过程的状态是进程完全私有的。这意味着,父进程和子进程不直接共享存储器或文件描述符。注意两个过程当然可以打开相同的文件;例如,所有的进程应该有的0 和 1 映射到系统控制台的文件描述符。不像KThread.join(),只有一个进程的父进程可以调用 join()。举例来说,如果 A 创建 B 并且 B 创建 C,A 不允许 join()到 C 中,但 B 被允许 join() 到 C。加入需要一个进程 ID 作为参数,用于唯一标识其父母希望加入的子进程。进程ID 应该是全局唯一的正整数,在每个进程创建时分配。(虽然在这个项目的唯一使用的进程

31、ID 是在 join(),进程 ID 是整个系统中的所有正在运行的进程是唯一的以后项目阶段很重要)。解决这个问题的最简单的方法就是保持一个表明接下来的进程ID 分配的静止计数器。由于该进程 ID 是 int 类型,则有可能对是否存在在系统中的许多过程这个值溢出。对于这个项目,你不必要处理这种情况下,也就是说,假定该方法ID 计数器不会溢出。当进程调用 exit(),它的线程应立即终止,而这个过程应该清理与它相关的任何状态(也就是释放内存,关闭打开的文件等)。如果一个进程异常退出执行相同的清理。 在退出过程的退出状态应转移到父进程,如果父调用 join()系统调用。一个进程退出状态的异常与否取决

32、于你。对于 join()的目的,如果它任何状态9/14下调用退出函数,那么一个子进程正常退出,如果内核杀死它(例如,由于未处理的异常)则是不正常的。最后一个过程调用 exit()应使 machine 类暂停,通过(请注意,只有根进程中应允许调用 halt()系统调用,但最后退出的过程中应该直接调用() 题目分析与实现方案在该系统调用中 , 第一个参数为文件名地址, 第二个参数为参数个数 , 第三个参数为参数表指针 . 需要做的工作是 :读虚拟内存获得文件名2. 处理参数。首先用第三个参数作为虚拟内存地址得到参数表数组的首址, 然后用 readVirtualMemoryString 依次读出每个

33、参数3. 用 UserProcess.newUserProcess创建子进程 , 将文件和参数表加载到子进程4. 用 UserProcess.execute方法执行子进程,同时将这个子进程的父进程置为这个进程,再将子进程加入子进程列表join:该系统调用中 , 第一个参数为子进程编号 , 第二个参数一个地址 , 用于保存子进程的返回值 . 需要做的工作是 :1. 利用进程号确定 join 的是哪一个进程,检查 childProcesses, 遍历子进程链表,确定 join 的进程是子进程。如果子进程编号不在其中则出错返回2. 获得 join 锁,让该进程休眠,直到子进程唤醒3. 子进程唤醒之后

34、,将子进程的状态存入自己的内存中,判断当前进程是否正常结束。结束则返回。exit:首先关闭 coff,然后将所有的打开文件关闭,把退出的状态置入,如果该进程有父进程,看是否执行了 join 方法,如果执行就将其唤醒,同时将本进程从子进程链表中删除,释放内存,结束底层线程,如果是最后一个结束的进程则将系统关闭。 该系统调用的唯一参数为返回值。需要做的工作为 :1. 关闭 coff,关闭所有打开的文件,把退出的状态置入2. 如果该进程有父进程, 看是否执行了 join 方法,如果执行就将其唤醒, 同 时将此进程从子进程链表中删除3. 调用 unloadsections 释放内存,调用 KThrea

35、d.finish方法结束当前线程4. 如果是最后一个进程,调用 Machine.halt() 停机,修改运行的进程总数关键点与难点exec()实现创建子进程并执行功能,涉及执行程序地址,参数数量,参数地址相关参数,并返回子进程id。join()阻塞等待某子进程执行完毕;涉及参数子进程id,子进程地址,并返回-1/0/1exit()关闭进程,清除相关信息,涉及进程状态参数,返回0. 应注意:1)父进程和子进程不共享任何的内存,文件或其它状态。2)只有父进程能对子进程进行join 操作。例如 A 执行 B,B 执行 C,则 A 不允许 join C,而 B 允许 join C。3)需要为每个进程分

36、配一个唯一的进程编号。4)exit 操作将使当前进程立即结束,如果父进程对其进行join 操作,返回代码这时应返回。5)最后一个调用exit 的进程将使系统停机实现代码10/14UserProcess parentProcess ;LinkedList childProcess;private KThread thread ;private Lock joinLock ;Condition joinCondition ;int numOfRunningProcess ;private boolean normalExit ;private int status ;private int pid

37、 ;private int handleExec (int , int argc, int argvAddress) / 文件名大小,读虚拟内存获得文件名String= readVirtualMemoryString(, 256);/ 文件出错if ( = null |argc 0 |argvAddress numPages * pageSize) return -1;String args = new String argc;/ 将文件内容读入虚拟内存 for (int i = 0; i 0)argsi = readVirtualMemoryString(Lib.bytesToInt (ar

38、gsAddress, 0), 256);/ 创建子进程 , 将文件和参数表加载到子进程UserProcess process = UserProcess.newUserProcess();/ 文件打开失败,退出if (! process.execute (, args)return -1;/ 将当前父进程信息赋予子进程 process.parentProcess = this ; childProcess.add(process );/ 返回子进程编号return process.pid ;private int handleJoin (int pid, int statusAddress )

39、 UserProcess process = null ;/ 利用进程号确定 join 的是哪一个进程for (int i = 0; i childProcess .size(); i+) / 如果子进程是当前运行程序,则返回 if (pid = childProcess .get(i).pid ) process = childProcess .get (i);break ;if (process = null |process.thread = null )return -1;/ 得到锁 process.joinLock .acquire ();/ 进程睡眠process.joinCond

40、ition .sleep();process.joinLock .release();byte childstat = new byte 4;Lib.bytesFromInt (childstat , 0, process.status );/将要写入虚拟内存大小int numWriteByte= writeVirtualMemory(statusAddress , childstat );if (process.normalExit & numWriteByte= 4)return 1;return 0;11/14private int handleExit (int status) /关闭

41、 coff 区coff .close();/ 关闭所有打开的文件 for (int i = 0; i 调度 引入一个 ThreadState 类用来把进程和彩票数量联系在一起,但是在得到有效优先级时,是把等待自己的队列中的进程的优先级和自己的优先级加起来,总的彩票数才是自己的优先级。在 getEffectivePriorityNachos 中将选取最大优先级的过程改成将所有等待线程的优先级 (彩票数 ) 加到 lockHolder 上 (即等待者把自己拥有的彩票给获得锁的线程 ),其次将 nextThread 修改如下: 首先遍历一遍队列, 计算出 当 前 队 列 中 的 所 有 队 列 的

42、彩 票 总 数 ( 考 虑 过 donation 后 的 )numEffective , 其 次 生 成 一 个0 到numEffective-1 之 间 的 随 机 数randomLottery 表示抽取的彩票,最后再次遍历一遍队列,用累加器 t 计算彩票总数,当 t 对应的当前值大于 randomLottery 时说明当前循环到的线程正好落在目标区间内,即选出该线程。由于不能保存彩票的指针,所以只能遍历队列,累加线程的有效优先级,当有效优先级的总和大于等于中奖号码表示这个线程中奖,这是利用概率中的随机原则,将中奖转换为了累加。找到线程后将线程从队列中取出,将其返回。关键点与难点彩票调度与优

43、先级调度非常类似,只是将“优先级” 的概念变成了“彩票”,即表示该线程下次被运行的几率。而且在调度过程中,并不是选择彩票数最多的线程运行,而是随机抽取一彩票,让彩票的主人运行。这样,彩票越多,下次得到的运行机会就越大。类 LotteryScheduler 继承自类 PriorityScheduler,可以直接利用类 PriorityScheduler的特性把进程和彩票数量联系在一起,并且彩票的“抽奖”过程只能遍历线程队列。实现代码public int getEffectivePriority() / implement meif (effectivePriority!= expiredEffe

44、ctivePriority)return effectivePriority ;effectivePriority= priority ;/ 等待队列为空if (waitors = null )return effectivePriority ;/将所有等待线程的优先级(彩票数 )加到 lockHolder 上for (Iterator i = waitors .waitQueue .iterator (); i.hasNext ();) ThreadState ts = (ThreadState ) getThreadState (KThread ) i.next ();effectivePriority+= ts.priority ;return effectivePriority ;protected ThreadState pickNextThread () / implement me13/14int numEffective = 0;if (waitQueue .isEmpty ()return null ;/

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


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