计算机线程-外文翻译-外文文献-英文文献_第1页
计算机线程-外文翻译-外文文献-英文文献_第2页
计算机线程-外文翻译-外文文献-英文文献_第3页
计算机线程-外文翻译-外文文献-英文文献_第4页
计算机线程-外文翻译-外文文献-英文文献_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

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

文档简介

译文Chapter25ThreadBasicsWhyDoesWindowsSupportThreads?...………….…..…691ThreadOverhead…..…………………….…...692StoptheMadness…………..………….……...696CPUTrends……………………….…..….……699NUMAArchitectureMachines…..……………….….……..700CLRThreadsandWindowsThreads………………..……………….…….703UsingaDedicatedThreadtoPerformanAsynchronousCompute-BoundOperation…………….……704ReasonstoUseThreads……..……………...…………….….706ThreadSchedulingandPriorities……………….……..……………….…...708ForegroundThreadsversusBackgroundThreads………..713WhatNow?715Inthischapter,Iintroducethebasicconceptsconcerningthreads,andIofferawayfordeveloperstoconceptualizeaboutthemandtheiruse.I’llexplainwhyMicrosoftWindowsintroducedtheconceptofthreads,CPUtrends,therelationshipbetweencommonlanguageruntime(CLR)threadsandWindowsthreads,theoverheadassociatedwithusingthreads,howWindowsschedulesthreads,theMicrosoft.NETFrameworkclassesthatexposethreadproperties,andmuchmore.ThechaptersinPartVofthisbook,“Threading,”explainhowWindowsandtheCLRworktogethertoprovideathreadingarchitecture.Itismyhopethatafterreadingthesechapters,youwilltakeawayafoundationofknowledgethatwillallowyoutoeffectivelyusethreadstodesignandbuildresponsive,reliable,andscalableapplicationsandcomponents.WhyDoesWindowsSupportThreads?Backintheearlydaysofcomputers,operatingsystemsdidn’toffertheconceptofathread.Ineffect,therewasjustonethreadofexecutionthatranthroughouttheentiresystem,whichincludedbothoperatingsystemcodeandapplicationcode.Theproblemwithhavingonlyonethreadofexecutionwasthatalong-runningtaskwouldpreventothertasksfromexecuting.Forexample,inthedaysof16-bitWindows,itwasverycommonforanapplicationthatwasprintingadocumenttostalltheentiremachine,causingtheOSandallotherapplicationstostopresponding.And,sometimesapplicationswouldhaveabuginthem,resultinginaninfiniteloopthatalsostoppedtheentiremachinefromoperating.Atthispoint,theenduserwouldhavenochoicebuttorebootthecomputerbypressingtheresetbuttonorpowerswitch.Ofcourse,endusershateddoingthis(theystilldo,infact)becauseallrunningapplicationsterminated;moreimportantly,anydatathattheseapplicationswereprocessingwasthrownoutofmemoryandlost.Microsoftknewthat16-bitWindowswouldnotbeagoodenoughoperatingsystemtokeepMicrosoftrelevantasthecomputerindustryprogressed,sotheysetouttobuildanewOStoaddresstheneedsofcorporationsandindividuals.ThisnewOShadtoberobust,reliable,scalable,andsecure,andithadtoimprovethemanydeficienciesof16-bitWindows.ThisOSkerneloriginallyshippedinMicrosoftWindowsNT.Overtheyears,thiskernelhashadmanytweaksandfeaturesaddedtoit.ThelatestversionofthiskernelshipsinthelatestversionsoftheMicrosoftclientandserverWindowsoperatingsystems.WhenMicrosoftwasdesigningthisOSkernel,theydecidedtoruneachinstanceofanapplicationinwhatiscalledaprocess.Aprocessisjustacollectionofresourcesthatisusedbyasingleinstanceofanapplication.Eachprocessisgivenavirtualaddressspace,ensuringthatthecodeanddatausedbyoneprocessisnotaccessibletoanotherprocess.Thismakesapplicationinstancesrobustbecauseoneprocesscannotcorruptcodeordatabeingusedbyanother.Inaddition,theOS’skernelcodeanddataarenotaccessibletoprocesses;therefore,it’snotpossibleforapplicationcodetocorruptoperatingsystemcodeordata.Sonow,applicationcodecannotcorruptotherapplicationsortheOSitself,andthewholecomputingexperienceismuchbetterforendusers.Inaddition,thesystemismoresecurebecauseapplicationcodecannotaccessusernames,passwords,creditcardinformation,orothersensitiveinformationthatisinusebyanotherapplicationortheoperatingsystemitself.Thisisallwellandgood,butwhatabouttheCPUitself?Whatifanapplicationentersaninfiniteloop?Well,ifthereisonlyoneCPUinthemachine,thenitexecutestheinfiniteloopandcannotexecuteanythingelse,sowhilethedatacannotbecorruptedandismoresecure,thesystemcouldstillstoprespondingtotheenduser.Microsoftneededtofixthisproblem,too,andthreadsweretheanswer.AthreadisaWindowsconceptwhosejobistovirtualizetheCPU.Windowsgiveseachprocessitsveryownthread(whichfunctionssimilartoaCPU),andifapplicationcodeentersaninfiniteloop,theprocessassociatedwiththatcodefreezesup,butotherprocesses(whichhavetheirownthreads)arenotfrozen;theykeeprunning!ThreadOverheadThreadsareawesomebecausetheyenableWindowstoberesponsiveevenwhenapplicationsareexecutinglong-runningtasks.Also,threadsallowtheusertouseoneapplication(likeTaskManager)toforciblykillanapplicationthatappearsfrozenbecauseitisexecutingalong-runningtask.Butaswitheveryvirtualizationmechanism,threadshavespace(memoryconsumption)andtime(runtimeexecutionperformance)overheadassociatedwiththem.Let’sexplorethisoverheadinmoredetailnow.Everythreadhasoneofeachofthefollowing:ThreadkernelobjectTheOSallocatesandinitializesoneofthesedatastructuresforeachthreadcreatedinthesystem.Thedatastructurecontainsabunchofproperties(discussedlaterinthischapter)thatdescribethethread.Thisdatastructurealsocontainswhatiscalledthethread’scontext.ThecontextisablockofmemorythatcontainsasetoftheCPU’sregisters.WhenWindowsisrunningonamachinewithanx86CPU,thethread’scontextusesabout700bytesofmemory.Forx64andIA64CPUs,thecontextisabout1,240and2,500bytesofmemory,respectively.Threadenvironmentblock(TEB)TheTEBisablockofmemoryallocatedandinitializedinusermode(addressspacethatapplicationcodecanquicklyaccess).TheTEBconsumes1pageofmemory(4KBonx86andx64CPUs,8KBonanIA64CPU).TheTEBcontainstheheadofthethread’sexception-handlingchain.Eachtryblockthatthethreadentersinsertsanodeintheheadofthischain;thenodeisremovedfromthechainwhenthethreadexistsinthetryblock.Inaddition,theTEBcontainsthethread’sthread-localstoragedataaswellassomedatastructuresforusebyGraphicsDeviceInterface(GDI)andOpenGLgraphics.User-modestackTheuser-modestackisusedforlocalvariablesandargumentspassedtomethods.Italsocontainstheaddressindicatingwhatthethreadshouldexecutenextwhenthecurrentmethodreturns.Bydefault,Windowsallocates1MBofmemoryforeachthread’suser-modestack.Kernel-modestackThekernel-modestackisalsousedwhenapplicationcodepassesargumentstoakernel-modefunctionintheoperatingsystem.Forsecurityreasons,Windowscopiesanyargumentspassedfromuser-modecodetothekernelfromthethread’suser-modestacktothethread’skernel-modestack.Oncecopied,thekernelcanverifythearguments’values,andsincetheapplicationcodecan’taccessthekernelmodestack,theapplicationcan’tmodifythearguments’valuesaftertheyhavebeenvalidatedandtheOSkernelcodebeginstooperateonthem.Inaddition,thekernelcallsmethodswithinitselfandusesthekernel-modestacktopassitsownarguments,tostoreafunction’slocalvariables,andtostorereturnaddresses.Thekernel-modestackis12KBwhenrunningona32-bitWindowssystemand24KBwhenrunningona64-bitWindowssystem.DLLthread-attachandthread-detachnotificationsWindowshasapolicythatwheneverathreadiscreatedinaprocess,allDLLsloadedinthatprocesshavetheirDllMainmethodcalled,passingaDLL_THREAD_ATTACHflag.Similarly,wheneverathreaddies,allDLLsintheprocesshavetheirDllMainmethodcalled,passingitaDLL_THREAD_DETACHflag.SomeDLLsneedthesenotificationstoperformsomespecialinitializationorcleanupforeachthreadcreated/destroyedintheprocess.Forexample,theC-RuntimelibraryDLLallocatessomethread-localstoragestatethatisrequiredshouldthethreadusefunctionscontainedwithintheC-Runtimelibrary.IntheearlydaysofWindows,manyprocesseshadmaybe5or6DLLsloadedintothem,buttoday,someprocesseshaveseveralhundredDLLsloadedintothem.Rightnow,onmymachine,MicrosoftOfficeOutlookhasabout250DLLsloadedintoitsprocessaddressspace!ThismeansthatwheneveranewthreadiscreatedinOfficeOutlook,250DLLfunctionsmustgetcalledbeforethethreadisallowedtodowhatitwascreatedtodo.Andthese250functionsmustbecalledagainwheneverathreadinOutlookdies.Wow—thiscanseriouslyaffecttheperformanceofcreatinganddestroyingthreadswithinaprocess.Sonow,youseeallthespaceandtimeoverheadthatisassociatedwithcreatingathread,lettingitsitaroundinthesystem,anddestroyingit.Butthesituationgetsevenworse—nowwe’regoingtostarttalkingaboutcontextswitching.AcomputerwithonlyoneCPUinitcandoonlyonethingatatime.Therefore,WindowshastosharetheactualCPUhardwareamongallthethreads(logicalCPUs)thataresittingaroundinthesystem.Atanygivenmomentintime,WindowsassignsonethreadtoaCPU.Thatthreadisallowedtorunforatime-slice(sometimesreferredtoasaquantum).Whenthetime-sliceexpires,Windowscontextswitchestoanotherthread.EverycontextswitchrequiresthatWindowsperformsthefollowingactions:1.SavethevaluesintheCPU’sregisterstothecurrentlyrunningthread’scontextstructureinsidethethread’skernelobject.2.Selectonethreadfromthesetofexistingthreadstoschedulenext.Ifthisthreadisownedbyanotherprocess,thenWindowsmustalsoswitchthevirtualaddressspaceseenbytheCPUbeforeitstartsexecutinganycodeortouchinganydata.3.Loadthevaluesintheselectedthread’scontextstructureintotheCPU’sregisters.Afterthecontextswitchiscomplete,theCPUexecutestheselectedthreaduntilitstime-sliceexpires,andthenanothercontextswitchhappensagain.Windowsperformscontextswitchesaboutevery30ms.Contextswitchesarepureoverhead;thatis,thereisnomemoryorperformancebenefitthatcomesfromcontextswitches.Windowsperformscontextswitchingtoprovideenduserswitharobustandresponsiveoperatingsystem.Now,ifanapplication’sthreadentersintoaninfiniteloop,Windowswillperiodicallypreemptthatthread,assignadifferentthreadtoanactualCPU,andletthisotherthreadrunforawhile.ThisotherthreadcouldbeTaskManager’sthreadandnow,theendusercanuseTaskManagertokilltheprocesscontainingthethreadthatisinaninfiniteloop.Whendoingthis,theprocessdiesandallthedataitwasworkingonisdestroyed,too,butallotherprocessesinthesystemcontinuetorunjustfinewithoutlosingtheirdata.Ofcourse,theuserdoesn’thavetoresetthemachineandreboot,socontextswitchesarerequiredtoprovideenduserswithamuchbetteroverallexperienceatthecostofperformance.Infact,theperformancehitismuchworsethanyoumightthink.Yes,aperformancehitoccurswhenWindowscontextswitchestoanotherthread.ButtheCPUwasexecutinganotherthread,andthepreviouslyrunningthread’scodeanddataresideintheCPU’scachessothattheCPUdoesn’thavetoaccessRAMmemoryasmuch,whichhassignificantlatencyassociatedwithit.WhenWindowscontextswitchestoanewthread,thisnewthreadismostlikelyexecutingdifferentcodeandaccessingdifferentdatathatisnotintheCPU’scache.TheCPUmustaccessRAMmemorytopopulateitscachesoitcangetbacktoagoodexecutionspeed.Butthen,about30mslater,anothercontextswitchoccurs.ThetimerequiredtoperformacontextswitchvarieswithdifferentCPUarchitecturesandspeed.AndthetimerequiredtobuildupaCPU’scachedependsonwhatapplicationsarerunninginthesystem,thesizeoftheCPU’scaches,andvariousotherfactors.Soitisimpossibleformetogiveyouanabsolutefigureorevenanestimateastowhattimeoverheadisincurredforeachcontextswitch.Sufficeittosaythatyouwanttoavoidusingcontextswitchesasmuchaspossibleifyouareinterestedinbuildinghigh-performingapplicationsandcomponents.ImportantAttheendofatime-slice,ifWindowsdecidestoschedulethesamethreadagain(ratherthanswitchingtoanotherthread),thenWindowsdoesnotperformacontextswitch.Instead,thethreadisallowedtojustcontinuerunning.Thisimprovesperformancesignificantly,andavoidingcontextswitchesissomethingyouwanttoachieveasoftenaspossiblewhenyoudesignyourcode.ImportantAthreadcanvoluntarilyenditstime-sliceearly,whichhappensquitefrequentlybecausethreadstypicallywaitforI/Ooperations(keyboard,mouse,file,network,etc.)tocomplete.Forexample,Notepad’sthreadusuallysitsidlewithnothingtodo;thisthreadiswaitingforinput.IftheuserpressestheJkeyonthekeyboard,WindowswakesNotepad’sthreadtohaveitprocesstheJkeystroke.ItmaytakeNotepad’sthreadjust5mstoprocessthekey,andthenitcallsaWin32functionthattellsWindowsthatitisreadytoprocessthenextinputevent.Iftherearenomoreinputevents,thenWindowsputsNotepad’sthreadintoawaitstate(relinquishingtheremainderofitstime-slice)sothatthethreadisnotscheduledonanyCPUuntilthenextinputstimulusoccurs.ThisimprovesoverallsystemperformancesincethreadsthatarewaitingforI/OoperationstocompletearenotscheduledonaCPUanddonotwasteCPUtime;otherthreadscanbescheduledontheCPUinstead.Inaddition,whenperformingagarbagecollection,theCLRmustsuspendallthethreads,walktheirstackstofindtherootstomarkobjectsintheheap,walktheirstacksagain(updatingrootstoobjectsthatmovedduringcompaction),andthenresumeallthethreads.Soavoidingthreadswillgreatlyimprovetheperformanceofthegarbagecollector,too.Andwheneveryouareusingadebugger,Windowssuspendsallthreadsintheapplicationbeingdebuggedeverytimeabreakpointishitandresumesallthethreadswhenyousingle-steporruntheapplication.Sothemorethreadsyouhave,thesloweryourdebuggingexperiencewillbe.Fromthisdiscussion,youshouldconcludethatyoumustavoidusingthreadsasmuchaspossiblebecausetheyconsumealotofmemoryandtheyrequiretimetocreate,destroy,andmanage.TimeisalsowastedwhenWindowscontextswitchesbetweenthreadsandwhengarbagecollectionsoccur.However,thisdiscussionshouldalsohelpyourealizethatthreadsmustbeusedsometimesbecausetheyallowWindowstoberobustandresponsive.IshouldalsopointoutthatacomputerwithmultipleCPUsinitcanactuallyrunmultiplethreadssimultaneously,increasingscalability(theabilitytodomoreworkinlesstime).WindowswillassignonethreadtoeachCPUcore,andeachcorewillperformitsowncontextswitchingtootherthreads.Windowsmakessurethatasinglethreadisnotscheduledonmultiplecoresatonetimebecausethiswouldwreakhavoc.Today,computersthatcontainmultipleCPUs,hyperthreadedCPUs,ormulti-coreCPUsarecommonplace.ButwhenWindowswasoriginallydesigned,single-CPUcomputerswerecommonplace,andWindowsaddedthreadstoimprovesystemresponsivenessandreliability.Today,threadsarealsobeingusedtoimprovescalability,whichcanhappenonlyoncomputersthathavemultiplecoresinthem.TheremainingchaptersinthisbookdiscussthevariousWindowsandCLRmechanismsthatexistsothatyoucaneffectivelywrestlewiththetensionofcreatingasfewthreadsaspossiblewhilestillkeepingyourcoderesponsiveandallowingittoscaleifyourcodeisrunningonamachinewithmultiplecores.译文第25章线程基础Windows为什么要支持线程线程开销停止疯狂CPU发展趋势NUMA架构的机器CLR线程和Windows线程使用专用线程执行异步的计算限制操作使用线程的理由线程调度和优先级前台线程和后台线程继续学习本章将介绍线程的基本概念,帮助开发人员理解线程及其使用。我将解释MicrosoftWindows为什么引入线程的概念、CPU发展趋势、CLR线程和Windows线程之间的关系、与线程的使用关联的开销、Windows如何调度线程、公开了线程属性的Microsoft.NETFramework类等。本书第Ⅴ部分”线程处理”的各个章节将解释Windows和CLR如何协同提供一个线程处理架构。通过这些内容,希望能帮你建立一个良好的基础,使你学会高效率地使用线程来设计和构建反应灵敏的、可靠的、可伸缩的应用程序和组件。25.1Windows为什么要支持线程在计算机的早期岁月,操作系统没有提供线程的概念。事实上,整个系统只运行着一个执行线程,其中同时包含操作系统代码和应用程序代码。只用一个执行线程的问题在于,长时间运行的任务会阻止其他任务执行。例如,在16位Windows的那些日子,打印一个文档的应用程序很容易”冻结”整个机器,造成OS249和其他应用程序停止响应。有的应用程序含有bug,会造成无限循环,这同样会造成整个机器停止工作。遇到这个问题,用户只好按Reset键或电源开关重启计算机。用户们对此感到深恶痛绝(事实上,他们现在一样会),因为所有正在运行的应用程序都会终止。更重要的是,这些应用程序正在处理的数据都会无端地丢失。Microsoft明白16位Windows不是一个理想的操作系统。随着计算机工业的持续进步,它不足以保持Microsoft的领先地位。所以,他们计划构建一个新的OS来满足企业和个人的需要。这个新的OS必须健壮、可靠、易于伸缩以及安全,而且它必须改进16位Windows的许多不足。这个OS内核最初是在MicrosoftWindowsNT中发布的。经过多年的发展,这个内核已进行了大量改进,添加了大量功能。Microsoft每次发布客户端和服务器Windows操作系统的最新版本时,都会在其中采用了这个内核的最新版本。Microsoft设计这个OS内核时,他们决定在一个进程中运行应用程序的每个实例。进程不过是应用程序的一个实例要使用的资源的一个集合。每个进程都被赋予了一个虚拟地址空间,确保一个进程使用的代码和数据无法由另一个进程访问。这就确保了应用程序实例的健壮性,因为一个进程无法破坏另一个进程使用的代码或数据。除此之外,OS的内核代码和数据是进程访问不到的;所以,应用程序代码破坏不了操作系统代码或数据。由于应用程序代码破坏不了其他应用程序或者OS自身,所以用户的计算体验变得更好了。除此之外,系统变得比以往更安全,因为应用程序代码无法访问另一个应用程序或者OS自身使用的用户名、密码、信用卡资料或者其他敏感信息。听起来似乎不错,但CPU本身呢?如果一个应用程序进入无限循环,会发生什么?如果机器中只有一个CPU,它会执行无限循环,不能执行其他任何东西。所以,虽然数据无法被破坏,而且更安全,但系统仍然可能停止响应。Microsoft需要修正这个问题,他们拿出的方案就是线程。作为一个Windows概念,线程的职责是对CPU进行虚拟化。Windows为每个进程都提供了该线程专用的线程(功能相当于一个CPU,可将线程理解成一个逻辑CPU)。如果应用程序的代码进入无限循环,与那个代码关联的进程会”冻结”,但其他进程(它们有自己的线程)不会冻结;它们会继续执行!25.2线程开销线程是非常强悍的一个概念,因为它们使Windows即使在执行长时间运行的任务时也能随时响应。另外,线程允许用户使用一个应用程序(比如”任务管理器”)强制终止似乎已经冻结的一个应用程序(它也有可能正在执行一个长时间运行的任务)。但是,和一切虚拟化机制一样,线程会产生空间(内存耗用)和时间(运行时的执行性能)上的开销。下面让我们更详细地探讨这种开销。在每个线程中,下面这些东西一样都有一个:线程内核对象(Threadkernelobject)OS为系统中创建的每个线程都分配并初始化这种数据结构之一。在数据结构中,包含一组对线程进行描述的属性(本章后面讨论)。数据结构中还包含所谓的线程上下文(threadcontext)。上下文是一个内存块,其中包含了CPU的寄存器集合。Windows在一台使用x86CPU的计算机上运行时,线程上下文使用约700字节的内存。对于x64和IA64CPU,上下文分别使用约1240字节和2500字节的内存。线程环境块(Threadenvironmentblock,TEB)TEB是在用户模式(应用程序代码能快速访问的地址空间)中分配和初始化的一个内存块。TEB耗用1个内存页(x86和x64CPU中是4KB,IA64CPU中是8KB)。TEB包含线形程的异常处理链首(head)。线程进入的每个try块都在链首插入一个节点。线程退出try块时,会从链中删除该节点。除此之外,TEB还包含线程的”线程本地存储”数据,以及由GDI(图形设备接口)和OpenGL图形使用的一些数据结构。用户模式栈(User-modestack)用户模式栈用于存储传给方法的局部变量和实参。它还包含一个地址;指出当前方法返回时,线程接着应该从什么地方开始执行。默认情况下,Windows为每个线程的用户模式栈分配1MB内存。内核模式栈应用程序代码向操作系统中的一个内核模式的函数传递实参时,还会使用内核模式栈。出于安全方面的原因,针对从用户模式的代码传给内核的任何实参,Windows都会把它们从线程的用户模式栈复制到线程的内核模式栈。一经复制,内核就可验证实参的值。由于应用程序代码不能访问内核模式栈,所以应用程序无法修改验证之后的实参值。OS内核代码将开始对复制的值进行处理。除此之外,内核会调用它自己内部的方法,并利用内核模式栈传递它自己的实参、存储函数的局部变量以及存储返回地址。在32位Windows上运行时,内核模式栈大小为12KB;在64位Windows上运行时,大小则为24KB。DLL线程连接(attach)和线程分离(detach)通知Windows的一个策略是,任何时候在进程中创建一个线程,都会调用那个进程中加载的所有DLL的DllMain方法,并向该方法传递一个DLL_THREAD_ATTACH标志。类似地,任何时候一个线程终止,都会调用进程中的所有DLL的DllMain方法,并向该方法传递一个DLL_THREAD_DETACH标志。有的DLL需要利用这些通知,为进程中创建/销毁的每个线程执行一些特殊的初始化或(资源)清理操作。例如,C-Runtime库DLL会分配一些线程本地存储状态。线程使用C-Runtime库中包含的函数时,需要用到这些状态。在Windows的早期岁月,许多进程只加载了5个或者6个DLL。但如今,有的进程可能加载几百个DLL。就拿目前来说,在我的机器上,MicrosoftOfficeOutlook在它的进程地址空间中加载了大约250个DLL!这意味着每次在OfficeOutlook中创建一个新线程,都必须先调用250个DLL函数,然后线程才能开始做它设计做的事情。Outlook中的线程终止时,这250个函数还要再调用一遍。这严重影响了在进程中创建和销毁线程时的性能。251现在,你已经知道了创建线程、让它进驻系统以及最后销毁它所需要的全部空间和时间开销。但还没完——现在让我们开始讨论上下文切换。单CPU的计算机一次只能做一件事情。所以,Windows必须在系统中的所有线程(逻辑CPU)之间共享物理CPU。在任何给定的时刻,Windows只将一个线程分配给一个CPU。那个线程允许运行一个”时间片”(有时也称为”量”或者”量程”,即quantum)。一旦时间片到期,Windows就上下文切换到另一个线程。每

温馨提示

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

评论

0/150

提交评论