MOCOR平臺內存管理介紹及案例分析_第1頁
MOCOR平臺內存管理介紹及案例分析_第2頁
MOCOR平臺內存管理介紹及案例分析_第3頁
MOCOR平臺內存管理介紹及案例分析_第4頁
MOCOR平臺內存管理介紹及案例分析_第5頁
已閱讀5頁,還剩62頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

.12022/12/19MOCOR平臺內存管理介紹MOCOR內存管理的基本架構

ThreadX的內存管理MOCOR的內存管理MOCOR內存bug實例分析.22022/12/19MOCOR內存管理的基本架構一般的嵌入式系統中最基本的內存管理方案有兩種——靜態分配和動態分配。靜態分配是指在編譯或鏈接時將程序所需的內存空間分配好。采用這種分配方案的內存段,其大小一般在編譯時就能夠確定。靜態分配比較簡單,一般不需要特殊的管理。動態分配是指系統運行時根據需要動態地分配內存,為實現動態分配,系統里需要有一套完善的管理機制。本文中所指的內存管理,就是指動態分配內存的管理。.32022/12/19MOCOR內存管理的基本架構MOCOR內存管理體系的一個大致的調用層次如下圖所示:.42022/12/19MOCOR內存管理的基本架構從可用的內存資源的角度,還可以得到下面的一個內存分配圖。.52022/12/19MOCOR平臺內存管理介紹MOCOR內存管理的基本架構ThreadX的內存管理

MOCOR的內存管理MOCOR內存bug實例分析.62022/12/19ThreadX的內存管理

內存字節池(BTYEPOOL)內存塊池(BLOCKPOOL).72022/12/19ThreadX的內存管理內存字節池(BTYEPOOL).82022/12/19ThreadX的內存管理---內存字節池1.基本概念:內存字節池是一個連續的內存塊。在字節池中,內存的分配以字節為單位,任意大小的內存都可以在字節池上分配(受限于內存的容量)。內存字節池類似于C語言里的堆(heap),所以,字節池我們也可以把它叫做字節堆,代碼里我們也可以看到創建的字節池通常以heap來命名。但與一般意義上的堆的不同在于,ThreadX里的字節池可以有多個,MOCOR平臺也是利用了這一特性,根據不同的需求而創建了多個heap。每一個字節池都有一個相應的字節池控制塊,通常是一個全局結構。控制塊包括對內存池的定義和狀態,比如內存池的名字,可用的字節數等。該結構的定義如下:.92022/12/19ThreadX的內存管理---內存字節池.102022/12/19ThreadX的內存管理---內存字節池2.分配方式:從字節池中分配內存類似于C語言的malloc調用,該調用返回所需內存的數量(以字節為單位)。分配的原則是“首次符合”原則,就是說,當第一個空閑內存塊的大小滿足需求時,就從該內存塊分配內存,然后將該內存塊的剩余內存轉換成一個新塊。字節池在初始狀態下,只有一個空閑塊,以后隨著隨著分配的進行,內存塊會隨之增多。除了上述的分配原則之外,字節池里還定義了一個值BYTE_POOL_SLIP_SIZE。這是在代碼里實現指定的一個具體數值,在分配內存時,如果要分配的內存大小大于這一數值,則從字節池的底部開始分配。采用這種分配方式是為了減少內存碎片的產生,盡量把大內存的分配區域和小內存的分配區域分開。目前系統里定義的BYTE_POOL_SLIP_SIZE為80K。.112022/12/19ThreadX的內存管理---內存字節池3.內存布局:以一個分配了兩次的字節池為例,在內存中的情況如下:.122022/12/19ThreadX的內存管理---內存字節池注意:首先要注意的問題是碎片,一個字節池可能有2000字節的可用空間,但不保證一定能分配到2000字節的連續空間,內存池對連續字節的數量不做保證。分配一塊內存所需要的時間跟分配內存的大小,字節池中的碎片數等因素有關,如果字節池有2000字節的空閑塊,花多長時間找到這塊內存也是沒有保證的。因此,在時間要求苛刻的任務中應避免使用字節池。字節池不能在中斷函數里使用,也不能在timer回調函數里使用。.132022/12/19ThreadX的內存管理---內存字節池思考:假定系統中有一個內存字節池,并且已經從中分配了幾次內存。當內存池中還有500字節的剩余內存時,應用程序申請200字節的內存,在什么情況下,這樣的申請不能滿足?.142022/12/19ThreadX的內存管理內存塊池(BLOCKPOOL).152022/12/19ThreadX的內存管理---內存塊池1.基本概念:內存塊池也是一個連續的字節塊,但它是由一定數量的固定szie的內存塊組成的。因此,從一個內存塊池中分配出的內存總是固定大小的。相比字節池,內存塊池的兩個主要優勢是:沒有碎片。因為內存塊池是固定size的塊構成,所以沒有碎片的產生。分配和釋放的速度很快。所需的時間相當于簡單的鏈表操作,分配時不需要搜索整個內存塊列表,它總是使用鏈表頭部的內存塊來分配。內存塊池的主要缺點是缺乏靈活性。固定尺寸既是它的優點也是它的缺點。如果一個內存塊池的尺寸足夠大,可以滿足用戶最極限的內存分配需求,那么,這個內存塊池上分配許多不同尺寸的內存會導致嚴重的內存浪費。一種解決辦法是同時創建幾個不同的內存塊池,每個內存塊池分別容納不同尺寸的內存塊。目前MOCOR平臺就是這樣做的,具體我們后面再討論。同字節池一樣,內存塊池也有一個控制塊結構,其中有該內存塊的相關信息,該結構如下:.162022/12/19ThreadX的內存管理---內存塊池.172022/12/19ThreadX的內存管理---內存塊池2.分配方式:內存塊池中分配內存是非常快的,主要得益于內存塊池中的所有空閑內存塊組成一個鏈表(即上面結構中的tx_block_pool_available_list)。每次分配時只需要取鏈表頭即可,無須遍歷內存塊池來找到空閑塊。.182022/12/19ThreadX的內存管理---內存塊池3.內存布局:.192022/12/19ThreadX的內存管理---內存塊池思考如何計算一個內存塊池所占用的物理內存大小?.202022/12/19MOCOR平臺內存管理介紹MOCOR內存管理的基本架構ThreadX的內存管理MOCOR的內存管理MOCOR內存bug實例分析.212022/12/19MOCOR內存管理MOCOR平臺在ThreadX內存管理的基礎上,又做了進一步的封裝,這樣可以更便于上層應用調用。前面我們已經了解了ThreadX是如何對內存進行管理的,下面我們從底層來到上層,看一看MOCOR是如何利用Threadx的內存管理機制來建立自己的內存管理方式。之前的MOCOR文檔里,將內存字節池稱為堆(heap),而將內存塊池稱為內存池(pool),我們也延續這種說法,請注意不要混淆。.222022/12/19MOCOR內存管理1.堆內存(heap)管理:MOCOR平臺的堆內存就是前面講到的內存字節池。最早的MOCOR平臺只有一個內存堆,但在實際使用中發現,程序運行時往往要交錯的分配一些動態內存和常駐內存,這樣會產生很多無法消除的內存碎片。同時base等通訊模塊同上層應用又是并發的,這樣無規律的分配也會造成很多內存碎片。為了解決這種情況,后來MOCOR版本將內存堆分成了三塊,也就是創建了三個內存字節池作為heap。這三個字節池的分別是:dynamicbaseheap,staticheap和dynamicappheap。同樣,對應著三個heap也有三個不同的接口,分別是:SCI_ALLOC_BASE,SCI_ALLOC_CONSTSCI_ALLOC_APP。.232022/12/19MOCOR內存管理三個heap:Baseheap:主要給PS,Layer1等使用。這個heap我們一般不用關心。Staticheap:主要用于分配常駐的內存,即一旦分配就不再釋放的內存。Appheap:其他不屬于以上兩種情況的內存都在這里分配。.242022/12/19MOCOR內存管理三個heap的大小都定義在mem_cfg.c里:#defineMAX_STATIC_HEAP_SIZE (600*1024)#defineMAX_DYNAMIC_BASE_HEAP_SIZE(60*1024)#defineMAX_DYNAMIC_APP_HEAP_SIZE (1430*1024)#define BYTE_HEAP_SIZE(MAX_STATIC_HEAP_SIZE+MAX_DYNAMIC_BASE_HEAP_SIZE+MAX_DYNAMIC_APP_HEAP_SIZE).252022/12/19MOCOR內存管理系統assert之后,選擇菜單5,可以看到所有heap上的內存分配信息,類似這樣:.262022/12/19MOCOR內存管理思考:前面講了MOCOR里有三個不同用途的heap,想一想哪些內存是要在staticheap里分配的,如果這些內存改在appheap上會有什么問題?嘗試舉出幾個實際的例子來說明。.272022/12/19MOCOR內存管理2.內存池管理:這個所說的內存池(pool)就是特指前面提到的內存塊池。之前我們提到過,為了避免浪費內存,通常是分配多個內存池,分別對應不同的大小。MOCOR平臺一共創建了12個內存池,其對應的大小和包含的內存塊的數目都定義在mem_cfg.c里:#definePOOL_1_BLOCK_SIZE16//pool'sblocksize#definePOOL_1_BLOCK_NUM480//pool'sblocknumber#definePOOL_2_BLOCK_SIZE24//pool'sblocksize#definePOOL_2_BLOCK_NUM320//pool'sblocknumber#definePOOL_3_BLOCK_SIZE40//pool'sblocksize#definePOOL_3_BLOCK_NUM650//pool'sblocknumber#definePOOL_4_BLOCK_SIZE60//pool'sblocksize#definePOOL_4_BLOCK_NUM500//pool'sblocknumber#definePOOL_5_BLOCK_SIZE112//pool'sblocksize#definePOOL_5_BLOCK_NUM80//pool'sblocknumber#definePOOL_6_BLOCK_SIZE180//pool'sblocksize#definePOOL_6_BLOCK_NUM280//pool'sblocknumber#definePOOL_7_BLOCK_SIZE300//pool'sblocksize#definePOOL_7_BLOCK_NUM80//pool'sblocknumber#definePOOL_8_BLOCK_SIZE600//pool'sblocksize#definePOOL_8_BLOCK_NUM120//pool'sblocknumber#definePOOL_9_BLOCK_SIZE800//pool'sblocksize#definePOOL_9_BLOCK_NUM100//pool'sblocknumber#definePOOL_A_BLOCK_SIZE1100//pool'sblocksize#definePOOL_A_BLOCK_NUM98//pool'sblocknumber#definePOOL_B_BLOCK_SIZE1300//pool'sblocksize#definePOOL_B_BLOCK_NUM10//pool'sblocknumber#definePOOL_C_BLOCK_SIZE1600//pool'sblocksize#definePOOL_C_BLOCK_NUM12//pool'sblocknumber(以上的定義不同版本的MOCOR可能并不一致,經常會有調整).282022/12/19MOCOR內存管理什么時候在heap上分配,什么時候在內存池上分配?MOCOR對分配內存的位置有如下的約定:只有分配的內存的大小超過mem_cfg.c里定義的最大的內存塊池的大小,內存才會在heap里分配,否則就在內存塊池里分配。目前MOCOR平臺定義的最大的內存塊池是1600字節,也就是大于1600字節的內存才在heap里分配。.292022/12/19MOCOR內存管理MOCOR在內存池上的分配策略是:最小適配原則:按從小到大的順序,遍歷所有的內存池,直到找到一個內存池,其大小大于欲分配內存的大小,就在該內存池分配內存。如果該內存池已被用盡,則繼續向下遍歷,找到下一個適合的內存池。如果全部遍歷完都沒有找到可用的內存池,則改為在heap上分配內存。上面的策略對于上層的申請者是透明的,申請者只要傳入欲分配的內存大小即可,無須關心內存究竟是在哪里分配的。.302022/12/19MOCOR內存管理系統assert之后,選擇菜單5,可以看到當前所有pool的信息,類似這樣:.312022/12/19MOCOR內存管理3.內存Debug信息:為了方便在出現內存問題的時候調試,通常在分配內存的時候(heap和pool),會額外的多分配一個header,放在每一塊分配內存的開始。header的結構定義如下:結構成員的意義如下:pre,succ:兩個指向header結構的指針,目的是將所有的header串成一張雙向鏈表。file_name,line:分配該塊內存的文件名和行號size:內存大小(不包括header)block_num:系統分配的內存塊總計此外,為了能檢查內存越界,在每一塊分配內存的最后也會額外多分配一個字節做為ENDFLAG,內存分配時該字節會被寫入0xAA。當該內存被釋放時,會檢查該標志位,如果不為0xAA,則說明出現異常,系統ASSERT。.322022/12/19MOCOR內存管理加入debug信息后的內存如下:.332022/12/19MOCOR內存管理因為有額外加了這些debug信息,所以如果我們要分配N個字節的內存,那么實際上分配的大小是:N+sizeof(MEM_HEADER_T)+1.再考慮到字節對齊的需要,實際的空間比上面的數字可能還要大一點。比如16字節的內存池,其中每個內存塊的大小其實是:16+24+4(本應是加1,加4是為了字節對齊)Header里的pre指向前一塊分配的內存,next指向后一塊分配的內存,所有分配的內存,都通過header里的pre和succ指針串起來,構成一張雙向鏈表。每分配一塊新的內存,就將這塊內存的header加到鏈表的最后。通過遍歷header構成的鏈表,我們可以得到當前所有分配的內存塊的信息。.342022/12/19MOCOR內存管理系統assert之后,選擇菜單4,就可以打印出這些信息,類似這樣:.352022/12/19MOCOR內存管理思考:應用里分配一塊大小為N字節的內存,實際在內存里占了多少空間?.362022/12/19MOCOR內存管理練習:前面我們已經講了MOCOR平臺各類內存的分配情況,下面需要你親自動手加深理解。使用我們的樣機,連上log,主動assert,輸入3,dump出當前的內存。輸入5,打出當前的內存信息。然后打開內存dump文件,找到appheap的起始地址,從起始地址開始,推出整個appheap的所有內存塊的信息,然后用剛才打印出的信息驗證一下你的推導是否正確。.372022/12/19MOCOR內存管理4.物理內存:內存管理的最終的對象就是物理內存,但是,物理內存并不能全部用于動態分配,因為一些全局變量,代碼等需要占用物理內存,這些相當于靜態分配。而我們通常說的內存管理是指動態的對內存進行分配和釋放。那么哪些物理內存是我們能夠動態分配使用的呢,我們是如何知道可以動態分配的物理內存的地址范圍呢?以6600L芯片為例,L所用的NORMCP中的SRAM通常是4M,這4M就是我們所能夠用到的所有物理內存。OS啟動后,會把物理內存SRAM的地址映射到0x04000000到0x04400000這個區域。.382022/12/19MOCOR內存管理Heap和pool對應的物理內存的位置和大小:uint32pool_1_addr[POOL_XX_SIZE(POOL_1_BLOCK_SIZE,POOL_1_BLOCK_NUM)];uint32pool_2_addr[POOL_XX_SIZE(POOL_2_BLOCK_SIZE,POOL_2_BLOCK_NUM)];uint32pool_3_addr[POOL_XX_SIZE(POOL_3_BLOCK_SIZE,POOL_3_BLOCK_NUM)];………uint32pool_B_addr[POOL_XX_SIZE(POOL_B_BLOCK_SIZE,POOL_B_BLOCK_NUM)];uint32pool_C_addr[POOL_XX_SIZE(POOL_C_BLOCK_SIZE,POOL_C_BLOCK_NUM)];uint32BYTE_HEAP_ADDR[byte_head_size>>2];.392022/12/19MOCOR內存管理5.內存委托管理:委托內存管理實質就是給了模塊創建自己的heap和pool的機會。通常情況下我們使用的heap和pool都是系統創建的。但有些模塊也想先從系統的heap里分出一塊大內存,然后在這塊大內存上,再根據自己的需要細分出一些內存塊來供本模塊使用。在沒有委托內存管理之前,這種細分的工作實際由各模塊自己來完成,實現的手法也五花八門。有了委托內存管理,模塊可以在分配的大內存的基礎上,再創建自己的heap和pool,這些heap和pool的實現機制,同我們之前講的系統的機制是基本一樣的。.402022/12/19MOCOR內存管理6.BLOCKMEM:關于BLOCKMEM可以參考《MOOCR應用模塊內存使用接口》的第二章,如果還不清楚blockmem的目的和用法的,請務必先學習上面這篇文檔。.412022/12/19MOCOR內存管理幾個容易混淆的地方:1.BLOCKMEM并不是在內存中實際分配出一塊區域來進行管理(雖然舊的MOCOR版本上確實是這樣的),BLOCKMEM的分配依然是在appheap上完成的。既然是在appheap上分配的,那么assert之后按5,從appheap的信息里是可以找到當前分配的blockmem的,比如這樣:.422022/12/19MOCOR內存管理.432022/12/19MOCOR內存管理2.BLOCKMEM的管理機制中,為各塊mem都定義了一個offset,但這個offset純粹是一個邏輯概念,它的作用是在分配blockmem時判斷是否存在mem沖突。一個block在內存中的實際位置同這個offset沒有任何關系。.442022/12/19MOCOR內存管理MOCOR內存管理的基本架構ThreadX的內存管理MOCOR的內存管理MOCOR內存bug實例分析.452022/12/19MOCOR內存bug實例分析內存不足:

內存不足是經常遇到的問題,內存不足根據產生的原因,還可以分為內存泄露引起的不足,內存碎片引起的不足,以及真正的內存不足。下面我們以幾個具體的例子來分析。.462022/12/19MOCOR內存bug實例分析1.內存泄漏:內存泄露是指分配了一塊內存在使用完后卻沒有釋放,造成系統中可用內存越來越少,最后死機。內存泄露引起的死機很容易定位,只要在死機后輸入4,打出當前所有分配的內存信息,查看是否有大量的重復的內存分配就可以知道。實例:某客戶項目,測試中反復撥號出現死機,死機信息為:File:RTOS\source\src\c\threadx_mem.cLine:494ASSERT(ASSERT:Error0x10(Nomemory,unabletoallocate!),mmipb_wintab.c,line=11550,param=0x4650)打出當前所有分配的信息,發現異常,有一條分配信息出現多次:.472022/12/19MOCOR內存bug實例分析.482022/12/19MOCOR內存bug實例分析2.內存碎片:如果系統中存在內存碎片,可能會出現雖然剩余的總內存數是足夠的,但依然分配不出內存的情況。實例,某客戶項目,后臺運行QQ,進入DC后死機。File:RTOS\source\src\c\threadx_mem.cLine:494ASSERT(ASSERT:Error0x10(Nomemory,unabletoallocate!),block_mem.c,line=563,param=0x113004)從死機信息可以看出,要分配的內存大小為0x113004(1126404),這么大的內存只可能從heap上分配,查看appheap的信息如下:.492022/12/19MOCOR內存bug實例分析.502022/12/19MOCOR內存bug實例分析我們重點關注畫紅圈的三塊內存,可以看到,剩余的總內存1495344,大于欲分配的內存,但是編號1和3的兩塊空閑內存正好被編號2的內存隔開了,1,和3的大小都不超過1126404,所以無法分配,這就是一個典型的內存碎片造成內存不足的場景。要解決這個問題,我們就要想辦法把兩塊空閑內存連在一起,主要就是要調整這幾塊內存的分配和釋放的順序。我們不妨用逆向思維來分析,先看一下造成內存碎片的順序是怎樣的,然后我們只要避免這種順序就可以了。首先在最初時,1,2,3這三塊內存實際是一整塊空閑內存。前面我們提過,字節池分配內存時有一個反向分配的概念,當要分配的的內存大于80K時,是從底向上分配的。所以分配和釋放的順序是:第一步:分配內存3;第二步:分配內存2;第三步:釋放內存3由此可以自然的想到解決的辦法,就是調整上面的3個步驟,具體可以有兩種辦法:內存塊2先于3分配,這樣3釋放后自然同1連在一起。內存塊2在3釋放之后再分配,這樣2占了內存3的位置,剩余的內存也是連續的。具體用什么方法,就要根據實際的具體情況,看哪一種方法是最可行的。在客戶的這個問題中,內存塊3是一個第三方桌面插件分配的,內存塊2是QQ分配的。所以第2種方法最可行,在分配QQ的內存前,先釋放掉第三方桌面插件的內存,問題由此解決。.512022/12/19MOCOR內存bug實例分析注意:并不是所有的內存碎片問題都能夠通過這樣的調整來得到解決。系統運行的過程中,一些內存碎片的產生是無法避免的,這種情況下內存碎片無法得到消除或消除的難度很大。.522022/12/19MOCOR內存bug實例分析3.實際內存不足:如果出現剩余的內存不夠分配,此時查看內存分配的情況也沒有異常(也就是說已經排除了內存泄露和碎片的原因),這種情況就是真正的內存不足了。遇到這種情況,一般有這些思路:要求客戶裁剪功能,減少內存的使用,通常客戶會對平臺版本進行一些定制,比如增加一些第三方應用等等,這些新增的模塊往往會造成內存使用的增加。如果某些操作很耗內存,那么執行這些操作時最好將其他操作退出,盡量避免并發。以上都不行的話最后只能通過增大heapsize來解決。.532022/12/19MOCOR內存bug實例分析某客戶上報問題,進文件管理器,選擇一張gif圖片發彩信時出現內存不足死機:File:RTOS\source\src\c\threadx_mem.cLine:494ASSERT(ASSERT:Error0x10(Nomemory,unabletoallocate!),block_mem.c,line=521,param=0x25804)從上面的信息可以看到欲分配的內存大小是0x25804(153604)。查看appheap的使用情況如下.542022/12/19MOCOR內存bug實例分析.552022/12/19MOCOR內存bug實例分析

可以看到當前剩余的總內存也不過是141744,其中最大一塊空閑內存是0x1aa4c(109132),還差0x25804-0x1aa4c=0xADB8(44472)才夠分配。我們用剛才的幾種思路分析一下:裁剪功能,因為沒有第三方的東西,這個不考慮避免并發。通過分析內存,可以看到分配的內存實際上可以分為兩大塊(見上圖),一塊是上面紅框的部分,主要是由FMM分配的。另一塊是下面紅框部分,主要是由MMS分配,所以這里存在MMS和FMM并發的情況。如果我們在發送彩信之前就先退出FMM的話,可以解決此問題。增大heap。前面我們已經算出當前差了44472字節,修改mem_cfg.c,將appheap的大小增加至少44K。需要注意的是,如果要增大heap,首先要確認一下當然ram是否還有這么多可用的空間,可以通過查看map文件最后的幾行信息:

TotalROSize(Code+ROData)7530419(7353.92kB)TotalRWSize(RWData+ZIData)3944375(3851.93kB)TotalROMSize(Code+ROData+RWData)7586078(7408.28kB)

紅色的RWsize就是我們要關注的,可以看到當前RW使用了3851K,而RAM的總數是4096K,所以還有充足的空間,heap增加個幾十K沒有什么問題。可以看到使用2和3都可以解決問題,通常把增大heap作為最后的手段。.562022/12/19MOCOR內存bug實例分析內存覆蓋:內存覆蓋也是常見的一類內存問題,引起內存覆蓋的原因很多,往往沒有固定規律可循。而且有時出現覆蓋后并不立刻死機,這樣無法確認第一現場,增大了解決問題的難度。但在MOCOR平臺下,我們有一個非常有用的工具:BusMonitor。利用BusMonitor(后文簡稱BM),我們有一個解決覆蓋問題的一般性思路:首先確定被覆蓋內存的地址(可能是一個地址范圍),如果問題可以重現,且每次被覆蓋的地址比較固定,則可以用BM監控被覆蓋的地址,這樣當內存被覆蓋時會第一時間死機,可以迅速定位。BusMonitor的用法比較簡單,可以參考相關文檔。.572022/12/19MOCOR內存bug實例分析1.案例一內存寫入時越界是出現內存覆蓋的一個常見原因,相對來說也比較好查的,只要找到越界的那塊內存基本就可以定位,我們看下面的例子:客戶項目發現進入電話本偶而會出現死機,死機現場:File:RTOS\source\src\c\threadx_mem.cLine:364ASSERT(ASSERT:Error0x10(Nomemory,unabletoallocate!),wdp_customer.c,line=2098,param=0xFA4)初一看好像是個內存不足的,但實際不是,assert界面輸入4后打出當前分配的內存,就會發現有錯誤:.582022/12/19MOCOR內存bug實例分析.592022/12/19MOCOR內存bug實例分析

可以看到最后一行“memoryiscorrupted”,表明在遍歷memheader的鏈表時出錯,這意味著某一塊memory的header異常了,而且這塊內存的地址是0x40bcc3

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論