操作系统试验教材_第1页
操作系统试验教材_第2页
操作系统试验教材_第3页
操作系统试验教材_第4页
操作系统试验教材_第5页
已阅读5页,还剩25页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

1、实验 1 进程控制实验内容 :在 windows 系统下通过有关进程的系统调用,实现进程的简单操作,并观 察程序的运行情况,通过阅读和分析实验程序,分析执行结果。这些加深对进 程概念的理解,明确进程与程序之间的区别。实验目的 : 通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进 一步熟悉操作系统的进程概念, 理解 Windows 进程的“一生”,并了解学习创建 进程、观察进程和终止进程的程序设计方法。实验要求:(1) 理解系统调用 CreateProcess(的功能。(2) 编译并运行给出的程序,独立观察和分析程序执行的结果,给出需要回答 的问题。(3) 有多余时间则编写程序

2、, 实现输入任意执行文件并启动和选择结束进程功 能的程序。实验内容 :1. 创建进程本实验显示了创建子进程的基本框架。 程序只是再一次地启动自身, 并显示 它的系统进程 ID 和它在进程列表中的位置。步骤 1:编译并执行 1-1.exe 程序, 完成下列问题。程序1-1是一个简单的使用CreateProcess() API函数的例子。首先形成简单 的命令行,提供当前的 EXE 文件的指定文件名和代表生成克隆进程的号码。大 多数参数都可取缺省值,但是创建标志参数使用了: CREATE_NEW_CONSOLE 标志,指示新进程分配它自己的控制台, 使得运行示例程序时, 在任务栏上产生 许多活动标记

3、。然后该克隆进程的创建方法关闭传递过来的句柄并返回 main()函数。在关闭程序之前,每一进程的执行主线程暂停一下,以便让用户看到其中的至少一个窗口。程序运行时屏幕显示的信息是:Process ID:2540, Clo ne ID:0如果将创建标志参数该为其它,请自己设置一个,程序运行时屏幕显示的信息是:Process ID:2540,Clo ne ID:0如果设置创建参数改为:NULL。则表示程序在一个控制台上显示。程序运行时屏幕最初显示的信息是:Process ID:244, Clo ne ID:0,随后在该控制台上显 示程序运行的结果。2. 正在运行的进程本实验的程序中列出了用于进程信息

4、查询的API函数GetProcessVersion()与GetVersionEx()的共同作用,可确定运行进程的操作系统的版本号。步骤2:编译并执行1-2.exe程序,完成下列问题。执行1-2.exe程序的运行结果:当前PID信息:2064当前操作系统版本:5.1系统提示信息: Task Man ager should now in dicate thin process is high priorty.清单1-2中的程序表明如何获得当前的 PID和所需的进程版本信息。接着,程序 演示了如何使用 GetVersionEx() API函数来提取 OSVERSIONINFOEX结构。这 一数据块中

5、包括了操作系统的版本信息。其中,“OS : 5.1 ”表示当前运行的操作 系统是:Windows XP清单1-2的最后一段程序利用了操作系统的版本信息,以确认运行的是Windows。代码接着将当前进程的优先级提高到比正常级别高。步骤3:单击Ctrl + Alt + Del键,进入“ Windows任务管理器”,在“应用程序”选项卡中右键单击“ 1-2”任务,在快捷菜单中选择“转到进程”命令。在“Windows任务管理器”的“进程”选项卡中,与“ 2-2”任务对应的进 程映像名称是(为什么?):与“1-2 ”任务对应的进程映像名称是 VCSPAWN.EXE,因为“ 1-2”在该程序下运行。右键单

6、击该进程名,在快捷菜单中选择“设置优先级”命令,可以调整该进程的 优先级,如设置为“高”后重新运行 1-2.exe 程序,屏幕显示有变化吗?为什么? 屏幕显示没有变化。已经是高的优先级了。3. 终止进程在清单 1-3 列出的程序中,先创建一个子进程,然后指令它发出“自杀弹” 互斥体去终止自身的运行。清单 1-3 中的程序说明了一个进程从“生”到“死”的整个一生。第一次执 行时,它创建一个子进程。在创建子进程之前,先创建一个互斥的内核对象,以 便父子进程间进行协调。 当创建子进程时, 就打开了互斥体并在其他线程中进行 别的处理工作,同时等待着父进程使用 ReleaseMutex() 发出信号。然

7、后用 Sleep() 来模拟父进程处理其他工作,等完成时,指令子进程终止。进程可使用退出代码将终止方式通知给调用 GetExitCodeProcess() 的其他 进程。同时,GetProcessTimes(函数可向主调者显示进程的终止时间。步骤4:编译并执行1-3.exe程序,其运行结果:1) Creating the child process. 表示:正在创建一个子进程。2) Telling the child process to quit.表示:指令子进程终止。步骤 5:在熟悉清单 1-3源代码的基础上,利用本实验介绍的 API 函数来尝试改 进本程序(例如使用GetProcessT

8、imes(函数)并运行。请描述你所做的工作:程序 1-1.cpp/ proc create 项目#include #include #include #include/ 创建传递过来的进程的克隆过程并赋于其 ID 值void StartClone(int nCloneID)/ 提取用于当前可执行文件的文件名TCHAR szFilenameMAX_PATH ;GetModuleFileName(NULL, szFilename, MAX_PATH) ;/ 格式化用于子进程的命令行并通知其 EXE 文件名和克隆 IDTCHAR szCmdLineMAX_PATH; sprintf(szCmdLin

9、e,%s d%,szFilename,nCloneID);/ 用于子进程的 STARTUPINFO 结构STARTUPINFO si;ZeroMemory(reinterpret_cast (&si) , sizeof(si) ) ; si.cb = sizeof(si) ; / 必须是本结构的大小/ 返回的用于子进程的进程信息PROCESS_INFORMATION pi;/ 利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质BOOL bCreateOK=CreateProcess( szFilename, / 产生这个 EXE 的应用程序的名称 szCmdLine, / 告诉其行为像

10、一个子进程的标志 NULL, / 缺省的进程安全性 NULL, / 缺省的线程安全性 FALSE, / 不继承句柄NULL, /CREATE_NEW_CONSOLE, / 使用新的控制台 标志参数 NULL, / 新的环境 lpEnvironment 参数,指明为新进程提供的环境NULL,/当前目录 IpCurrentDirectory,可用于向主创进程发送与缺省 目录不同的新进程使用的特殊的当前目录&si, / 启动信息 STARTUPINFO 数据结构所必需的, 用于在必要时指 明新应用程序的主窗口的外观。&pi) ; / 返回的进程信息 用于新进程对象及其主线程的句柄和 ID 的 返回值

11、缓冲区。/ 对子进程释放引用if (bCreateOK) CIoseHandIe(pi.hProcess) ;CIoseHandIe(pi.hThread) ;int main(int argc, char* argv )/ 确定进程在列表中的位置int nCIone(0) ;if (argc 1)sscanf(argv1 , %d , &nCIone) ;/ 从第二个参数中提取克隆 ID/ 显示进程位置cout Process ID: GetCurrentProcessId() , CIone ID: nCIone endI;/Sleep(500) ;Sleep(4000);/ 检查是否有创

12、建子进程的需要 const int c_nCloneMax=25;if (nClone c_nCloneMax) StartClone(nClone) ;/ 发送新进程的命令行和克隆号 / 在终止之前暂停一下 (l/2 秒)/Sleep(200) ;Sleep(4000);return 0;程序 1-2.cpp/ version 项目#include #include #include / 利用进程和操作系统的版本信息的简单示例 void main()/ 提取这个进程的 IDDWORD dwIdThis=GetCurrentProcessId();/ 获得这一进程和报告所需的版本,也可以发送

13、0 以便指明这一进程 DWORD dwVerReq= GetProcessVersion(dwIdThis);WORD wMajorReq=(WORD)(dwVerReq16) ;WORD wMinorReq=(WORD)(dwVerReq & 0xffff) ;cout Process ID: dwIdThis, requires OS: wMajorReq wMinorReq endl ;/ 设置版本信息的数据结构,以便保存操作系统的版本信息 OSVERSIONINFOEX osvix;ZeroMemory(&osvix, sizeof(osvix) ) ; osvix.dwOSVersi

14、onInfoSize=sizeof(osvix) ;/ 提取版本信息和报告GetVersionEx(reinterpret_cast (&osvix) ;cout Running on OS: osvix.dwMajorVersion . osvix.dwMinorVersion = 5)/ 改变优先级SetPriorityClass(GetCurrentProcess() , / 进程的 ID 号HIGH_PRIORITY_CLASS); / 改变为 high/ 报告给用户cout Task Manager should now indicate this process is high p

15、riority. endl;getchar();程序 1-3.cpp/ procterm 项目# include # include # include #include static LPCTSTR g_szMutexName = w2kdg.ProcTerm.mutex.Suicide ;/ 创建当前进程的克隆进程的简单方法void StartClone()/ 提取当前可执行文件的文件名TCHAR szFilenameMAX_PATH ;GetModuleFileName(NULL, szFilename, MAX_PATH) ;/ 格式化用于子进程的命令行,指明它是一个 EXE 文件和子

16、进程TCHAR szCmdLineMAX_PATH ;sprintf(szCmdLine, %schild , szFilename) ;/ 子进程的启动信息结构STARTUPINFO si;ZeroMemory(reinterpret_cast (&si),sizeof(si) ;si.cb = sizeof(si) ; / 应当是此结构的大小/ 返回的用于子进程的进程信息PROCESS_INFORMATION pi;/ 用同样的可执行文件名和命令行创建进程,并指明它是一个子进程 BOOL bCreateOK=CreateProcess(szFilename, /产生的应用程序的名称(本EX

17、E文件)szCmdLine, / 告诉我们这是一个子进程的标志NULL, / 用于进程的缺省的安全性NULL, / 用于线程的缺省安全性FALSE, / 不继承句柄NULL,/CREATE_NEW_CONSOLE, / 创建新窗口NULL, / 新环境NULL, / 当前目录&si, / 启动信息结构&pi ) ; / 返回的进程信息/ 释放指向子进程的引用if (bCreateOK)CloseHandle(pi.hProcess) ;CloseHandle(pi.hThread) ;void Parent()/ 创建互斥体HANDLE hMutexSuicide= CreateMutex(N

18、ULL, / 缺省的安全性TRUE, / 最初拥有的 g_szMutexName) ; / 为其命名if (hMutexSuicide != NULL)/ 创建子进程cout Creating the child process. endl;StartClone() ;/ 暂停Sleep(5000) ;/ 指令子进程自己终止cout Telling the child process to quit. endl;ReleaseMutex(hMutexSuicide) ;/ 消除句柄CloseHandle(hMutexSuicide) ;void Child()/ 打开互斥体HANDLE hMu

19、texSuicide = OpenMutex(SYNCHRONIZE, / 打开用于同步FALSE, / 不需要向下传递 g_szMutexName) ; / 名称 if (hMutexSuicide != NULL) / 报告我们正在等待指令endl;cout Child waiting for suicide instructions. WaitForSingleObject(hMutexSuicide, INFINITE) ;/ 准备好终止,清除句柄 cout Child quiting. 1 & strcmp(argv1 , child )= 0) Child() ; elsePare

20、nt() ;return 0;实验 2 经典同步问题实践实验内容 :学习Windows有关进程/线程同步的背景知识和 API,分析2个实验程序(事件 对象在进程间传送信号的应用和利用互斥体和临界区实现读者写者问题) ,观察 程序的运行情况并分析执行结果。实验目的 :在本实验中,通过对事件和互斥体对象的了解,来加深对 Windows 线程同步的 理解。(1) 了解事件和互斥体对象。(2) 通过分析实验程序,理解管理事件对象的 API 。(3) 理解在进程中如何使用事件对象。(4) 理解在进程中如何使用互斥体和临界区对象。(5) 理解父进程创建子进程的程序设计方法。实验要求:(1) 理解 Wind

21、ows 有关进程 /线程同步的背景知识和 API。(2) 按要求运行 2个程序,观察程序执行的结果,并给出要求的结果分析。(3) 参照 2-2 程序,写出一个实现单个生产者消费者问题的算法,可以使用单 个缓冲区,也可以使用缓冲池, 生产者随机产生任意形式的数据并放入缓冲区中, 消费者则以随机的时间间隔从缓冲区中取数据,随机时间请使用随机数产生。并发与同步的背景知识Windows 开发人员可以使用线程同步对象来协调线程和进程的工作, 以使其共享 信息并执行任务。此类对象包括互锁、临界区、事件、互斥体和信号等。多线程编程中关键的一步是保护所有的共享资源, 工具主要有互锁函数、 临界段和互斥体等;另

22、一个是协调线程使其完成应用程序的任务,为此,可利用内核中的事件对象和信号。在进程内或进程间实现线程同步的最方便的方法是使用事件对象,这组内核对象允许一个线程对其受信状态进行直接控制。而互斥体则是另一个可命名且安全的内核对象, 主要目的是引导对共享资源的访 问。拥有单一访问资源的线程创建互斥体,所有希望访问该资源的线程应该在实 际执行操作之前获得互斥体,而在访问结束时立即释放互斥体,以允许下一个等 待线程获得互斥体,然后接着进行下去。与事件对象类似,互斥体容易创建、打开、使用并清除。利用 CreateMutex() API 可创建互斥体,创建时可以指定一个初始的拥有权标志, 通过使用这个标志,只

23、 有当线程完成了资源的所有的初始化工作时,才允许创建线程释放互斥体。表2-1用于管理事件对象的APIAPI名称描述CreateEve nt()在内核中创建一个新的事件对象。此函数允许有安全性设置、手工还是自动重置的标志以及初始时已接受还是未接受信号状态的标志Open Event()创建对已经存在的事件对象的引用。此 API函数需要 名称、继承标志和所需的访问级别SetEve nt()将手工重置事件转化为已接受信号状态ResetEve nt()将手工重置事件转化为非接受信号状态PulseEve nt()将自动重置事件对象转化为已接受信号状态。当系统 释放所有的等待它的线程时此种转化立即发生为了获

24、得互斥体,首先,想要访问调用的线程可使用 OpenMutex() API来获得指 向对象的句柄;然后,线程将这个句柄提供给一个等待函数。 当内核将互斥体对 象发送给等待线程时,就表明该线程获得了互斥体的拥有权。 当线程获得拥有权 时,线程控制了对共享资源的访问一一必须设法尽快地放弃互斥体。 放弃共享资 源时需要在该对象上调用ReleaseMutex() API。然后系统负责将互斥体拥有权传递给下一个等待着的线程 (由到达时间决定顺序 )实验内容与步骤1. 事件对象清单 2-1 程序展示如何在进程间使用事件。父进程启动时,利用CreateEvent() API创建一个命名的、可共享的事件和子进程

25、, 然后等待子进程向事件发出信号并终止父进程。在创建时,子进程通过OpenEvent() API打开事件对象,调用SetEvent() API使其 转化为已接受信号状态。两个进程在发出信号之后几乎立即终止。清单 2-1 创建和打开事件对象在进程间传送信号/ eve nt 项目# include # include # include / 以下是句柄事件。实际中很可能使用共享的包含文件来进行通讯static LPCTSTR g_szContinueEvent =w2kdg.EventDemo.event.Continue;/ 本方法只是创建了一个进程的副本,以子进程模式(由命令行指定 ) 工作B

26、OOL CreateChild()/ 提取当前可执行文件的文件名TCHAR szFilenameMAX_PATH ;GetModuleFileName(NULL, szFilename, MAX_PATH) ;/ 格式化用于子进程的命令行,指明它是一个 EXE 文件和子进程TCHAR szCmdLineMAX_PATH ;sprintf(szCmdLine, %schild , szFilename) ;/ 子进程的启动信息结构STARTUPINFO si;ZeroMemory(reinterpret_cast(&si), sizeof(si) ;si.cb = sizeof(si); / 必

27、须是本结构的大小/ 返回的子进程的进程信息结构PROCESS_INFORMATION pi;/ 使用同一可执行文件和告诉它是一个子进程的命令行创建进程BOOL bCreateOK = CreateProcess( szFilename, / 生成的可执行文件名 szCmdLine, / 指示其行为与子进程一样的标志NULL, / 子进程句柄的安全性NULL, / 子线程句柄的安全性FALSE, / 不继承句柄0, / 特殊的创建标志NULL, / 新环境NULL, / 当前目录&si, / 启动信息结构&pi ) ; / 返回的进程信息结构/ 释放对子进程的引用if (bCreateOK)Cl

28、oseHandle(pi.hProcess);CloseHandle(pi.hThread);return(bCreateOK) ; / 下面的方法创建一个事件和一个子进程, 然后等待子进程在返回前向事件发出 信号void WaitForChild()HANDLE hEventContinue = CreateEvent(NULL, / 缺省的安全性,子进程将具有访问权限TRUE, / 手工重置事件FALSE, / 初始时是非接受信号状态g_szContinueEvent); / 事件名称if (hEventContinue != NULL)cout 事件对象已经建立 endl;/ 创建子进程

29、if ( CreateChild()cout 建立了一个子进程 endl;/ 等待,直到子进程发出信号cout Parent waiting on child. endl;WaitForSingleObject(hEventContinue, INFINITE);Sleep(1500); / 删除这句试试,或者改变数值cout parent received the envent signaling from child endl;/ 清除句柄CloseHandle(hEventContinue); hEventContinue=INVALID_HANDLE_V ALUE;/ 以下方法在子进程

30、模式下被调用,其功能只是向父进程发出终止信号 void SignalParent()/ 尝试打开句柄cout child process begining endl;HANDLE hEventContinue = OpenEvent( EVENT_MODIFY_STATE, / 所要求的最小访问权限 FALSE, / 不是可继承的句柄 g_szContinueEvent); / 事件名称 if(hEventContinue != NULL)SetEvent(hEventContinue);cout event signaled 1 & strcmp(argv1 , child )= 0)/ 向

31、父进程创建的事件发出信号SignalParent() ;else/ 创建一个事件并等待子进程发出信号WaitForChild();Sleep(1500);cout Parent released. 2-1 childchild process begining原因:执行Child只是完成该进程SignalParent()函数,甚至都打不开 OpenEvent()而终止操作系统实验3同步机制(2次)Debug2-1事件对象已经建立建立了一个子进程Pare nt wait ing on child.child process beginingeve nt sig naledpare nt rece

32、ived the envent sig nali ng from childPare nt released.2.互斥体对象清单2-2的程序中是读者写者问题的一个实现,满足读者优先原则,使用同步机 制的互斥体和临界区,对每个读者和写者分别用一个线程来表示。测试数据文件的数据格式说明:测试数据文件包括n行测试数据,每行描述创建的是用于产生读者还是写者的数据。每行测试数据包括4个字段,各字段间用空格分隔。第一字段为线程序号。第二字段表示相应线程角色,W表示写者,R表示读者。第三字段为线程延迟。第四字段为线程读写操作持续时间清单2-2禾I用互斥体和临界区实现读者写者问题#i nclude wi nd

33、ows.h#in elude vconi o.h#i nclude #in elude vfstream.h#i nclude #i nclude #i nclude #defi ne READER R/读者#defi ne WRITER W*/写者#define INTE PER SEC 1000/每秒时钟中断数目#define MAX THREAD NUM 64 / 最大线程数目#defi ne MAX_FILE_NUM 32/最大数据文件数目#defi ne MAX_STR_LEN 32/字符串长度intreadco unt = 0;/读者数目CRITICAL_SECTION RP_Wr

34、ite;/定义临界区struct ThreadI nfo /定义线程数据结构intserial; /线程序号charentity;/线程类别(判断是读者线程还是写者线程)doubledelay;/ 线程延迟doublepersist; /线程读写操作持续时间;/读者优先读者线程/ p:读者线程信息 void RP_ReaderThread(void *p)/ 互斥变量HANDLE h_Mutex;h_Mutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,mutex_for_readcount);DWORD wait_for_mutex;/ 等待互斥变量所有权DWOR

35、D m_delay;/ 延迟时间DWORD m_persist;/ 读文件持续时间int m_serial;/ 线程序号/从参数中获得信息m_serial = (ThreadInfo *)(p)-serial;m_delay = (DWORD)(ThreadInfo *)(p)-delay*INTE_PER_SEC); m_persist = (DWORD)(ThreadInfo*)(p)-persist*INTE_PER_SEC); Sleep (m_delay) ;/延迟等待printf(Reader thread %d sents the reading requiren,m_seria

36、l);等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1);/ 读者数目增加readcount+;if(readcount =1)/第一个读者,等待资源EnterCriticalSection(&RP_Write);ReleaseMutex(h_Mutex) ;/ 释放互斥信号/ 读文件printf(Reader thread %d begins to read file.n,m_serial); Sleep(m_persist) ;/ 退出线程printf(Reader thread %d fi

37、nished reading file.n,m_serial);等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1) ; /读者数目减少readcount- ;if(readcount = 0)/如果所有读者读完,唤醒写者LeaveCriticalSection(&RP_Write) ;ReleaseMutex(h_Mutex) ;/释放互斥信号/ 读者优先写者线程/ p:写者线程信息 void RP_WriterThread(void* p) DWORD m_delay;/延迟时间DWORD m

38、_persist;/写文件持续时间int m_serial; /线程序号/从参数中获得信息m_serial = (ThreadInfo *)(p)-serial;m_delay = (DWORD)(ThreadInfo *)(p)-delay*INTE_PER_SEC) ; m_persist = (DWORD)(ThreadInfo *)(p)-persist*INTE_PER_SEC) ; Sleep (m_delay);/延迟等待printf(Writer thread %d sents the writing require.n,m_serial);/ 等待资源EnterCritica

39、lSection (&RP_Write) ;/ 写文件printf(Writer thread %d begins to write to the file.n,m_serial); Sleep(m_persist) ;/ 退出线程printf(Writer thread %d finished writing to the file.n,m_serial); /释放资源LeaveCriticalSection(&RP_Write);/ 读者优先处理函数/ file :文件名void ReaderPriority(char *file)DWORD n_thread = 0; / 线程数目DWO

40、RD thread_ID; / 线程 IDDWORD wait_for_all; / 等待所有线程结束/ 互斥对象HANDLE h_Mutex;h_Mutex = CreateMutex(NULL,FALSE,mutex_for_readcount);/ 线程对象的数组HANDLE h_ThreadMAX_THREAD_NUM ;ThreadInfo thread_infoMAX_THREAD_NUM ;readcount = 0 ;/ 初始化 readcounttInitializeCriticalSection(&RP_Write) ; / 初始化临界区 ifstream inFile;

41、/ 打开文件 inFile.open(file) ;printf(Reader Priority:nn) ;while(inFile)/读人每一个读者、写者的信息 inFilethread_infon_thread.serial ;inFilethread_infon_thread.entity;inFilethread_infon_thread.delay; inFilethread_infon_thread+.persist; inFile.get();for(int i = 0; i (int)(n_thread); i+) if(thread_infoi.entity = READER

42、 | thread_infoi.entity = r)/ 创建读者线程h_Threadi = CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)(RP_ReaderThread), &thread_infoi,0,&thread_ID) ;else / 创建写者线程h_Threadi = CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)(RP_WriterThread), &thread_infoi,0 ,&thread_ID) ;/等待所有线程结束wait_for_all = WaitForMultipleOb

43、jects(n_thread,h_Thread,TRUE,-1) ; printf(All reader and writer have finished operating.n);/主函数int main(int argc, char* argv)char ch;while ( true )printf(*n);printf(1: Reader Priorityn) ;printf(2: Exit to Windowsn) ;printf(f*n);printf( Enter your choice (1 or 2): );/如果输入信息不正确,继续输入do ch = (char)_getch() ; while(ch != 1 & ch != 2);system(cls) ;/选择 2,返回if(ch = 2)return 0;/选择 l ,读者优先elseReaderPriority(thread.dat);/结束printf(nPress Any Key To Continue:);_getch() ;system(cls) ;return 0;步骤3:编译并建立2-2

温馨提示

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

评论

0/150

提交评论