五:內存和磁盤的親密關係

0、開篇:

(1)存儲程序方式指的是什麼?
     在存儲裝置中保存程序,並逐一運行的方式
(2)經過使用內存來提升磁盤訪問速度的機制稱爲何?
     磁盤緩存
(3)把磁盤的一部分做爲假想內存來使用的機制稱爲何?
     虛擬內存
(4)Windows中,在程序運行時,存儲着能夠動態加載調用的函數和數據的文件稱爲何?
     動態連接庫
(5)在EXE程序文件中,靜態加載函數的方式稱爲何?
     靜態連接
(6)在Windows計算機中,通常磁盤的1個扇區是多少字節?
     512字節
 

一、不讀入內存就沒法運行

  程序保存在存儲設備中,經過有序地被讀出來實現運行,這一點你們都很清楚。這一機制稱爲存儲程序方式(程序內置方式)。
       然而,在磁盤中保存的原始程序是沒法直接運行的,由於負責解析和運行程序內容的CPU,須要經過內部程序計數器來指定內存地址,而後才能讀出程序。即便CPU能夠直接讀出並運行磁盤中保存的程序,因爲磁盤讀取速度慢,程序的運行速度仍是會下降。總之,存儲在磁盤中的程序須要讀入到內存後才能運行。
  

二、磁盤緩存加快了磁盤訪問速度

  磁盤緩存指的是把從磁盤中讀出的數據存儲到內存空間中的方式。這樣一來,當接下來須要讀取同一數據時,就不用經過實際的磁盤,而是從磁盤緩存中把內容讀出。使用磁盤緩存能夠大大改善磁盤數據的訪問速度。編程

  

三、虛擬內存把磁盤做爲部份內存來使用 

     虛擬內存是指把磁盤的一部分做爲假想的內存來使用。這與磁盤緩存是假想的磁盤(其實是內存)相對,虛擬內存是假想的內存(其實是磁盤)。
     經過藉助虛擬內存,在內存不足時也能夠運行程序。例如,在只剩下5MB內存空間的狀況下也能運行10MB大小的程序。不過,就如本章開頭所講述的那樣,CPU只能執行加載到內存中的程序。虛擬內存雖然說是把磁盤做爲內存的一部分來使用,但實際上正在運行的程序部分,在這個時間點上是必須存在內存中的。也就是說,爲了實現虛擬內存,就必須把實際內存(也稱爲物理內存)的內容,和磁盤上的虛擬內存的內容進行部分置換(swap),並同時運行程序。
     虛擬內存的方式有分頁式和分段式兩種。Windows採用的是分頁式。該方式是指,在不考慮程序構造的狀況下,把運行的程序按照必定大小的頁(Page)進行分割,並以頁位單位在內存和磁盤間進行置換。在分頁式中,咱們把磁盤的內容讀出到內存稱爲Page In,把內存的內容寫入磁盤稱爲Page Out。通常狀況下,Windows計算機的頁的大小是4KB。也就是說,把大程序用4KB的頁來進行切分,並以頁爲單位放入磁盤(虛擬內存)或內存中。
  

四、節約內存的編程方法  

     許多人可能會認爲,經過藉助磁盤虛擬內存就能夠解決內存不足的問題。而虛擬內存也確實能避免因內存不足致使的應用沒法啓動。不過,因爲使用虛擬內存時發生的Page In和Page Out每每伴隨着低速的磁盤訪問,所以在這個過程當中,應用的運行會變得遲鈍起來。總的來講,虛擬內存沒法完全解決內存不足的問題。
     爲了從根本上解決內存不足的問題,須要增長內存的容量,或者儘可能把運行的應用文件變小。接下來會向你們介紹兩個把應用文件變小的編程方法。
 (1)經過DLL文件實現函數共有
       DLL(動態連接庫),顧名思義就是在程序運行時能夠動態加載Library(函數和數據的集合)的文件。此外,還有一個須要你們注意的地方,那就是多個應用能夠共有同一個DLL文件。而經過共有一個DLL文件則能夠達到節約內存的效果。
     例如咱們編寫了一個具備某些處理功能的函數MyFunc()。應用A和應用B都會使用這個函數,若是將這個函數內置(靜態連接),同時運行這兩個應用,內存中就存在了具備同一函數的兩個程序。這會致使內存的利用率變低。
  

  若是函數MyFunc()是獨立的DLL文件而不是應用的執行文件(EXE文件)。因爲同一個DLL文件的內容在運行時能夠被多個應用共有,所以內存中存在的函數MyFunc()的程序就只有1個,這樣一來,內存的利用效率就提升了。小程序

  

   Windows的操做系統自己也是多個DLL文件的集合體。DLL還有一個優勢就是在不變動EXE文件的狀況下,只經過升級DLL文件就能夠更新。緩存

  (2)經過調用_stdcall來減少程序文件的大小函數

    C語言中,在調用函數後,須要執行棧清理處理指令。棧清理處理是指,把不須要的數據從接收和傳遞函數的參數時使用的內存上的棧區域中清理出去。該命令不是程序記述的,而是在程序編譯時由編譯器自動附加到程序中的。編譯器默認將該處理附加在函數調用方。操作系統

  

  上面代碼中,函數main()中調用了函數MyFunc()。按照默認設定,棧的清理處理會附加在函數main()這一方。在同一個程序中,一樣的函數可能會被屢次反覆調用。而若是是一樣的函數,棧清理處理的內容也是同樣的。因爲該處理是在調用函數的一方,所以就會致使同一處理被反覆調用。這就形成了內存的浪費。blog

  在下圖的彙編語言:
  

  在32位CPU中,1次push指令能夠存儲4個字節的數據。在上面的代碼清單中,因爲使用了兩次push指令把兩個參數(456和123)存入到了棧中,所以總的來講就是存儲了8字節的數據。經過call指令調用函數MyFunc()後,棧中存儲的數據就再也不須要了。因而這時就經過add esp 8這個指令,是存儲着棧數據的esp寄存器前進8位來進行數據清理。內存

  棧清理處理,比起在函數調用方進行,在反覆被調用的函數一方進行時,程序總體要小一些。這時所使用的就是_stdcall。在函數前加上_stdcall,就能夠把棧清理處理變爲在被調用函數一方進行。
  

五、磁盤的物理結構

  磁盤的物理結構是指磁盤存儲數據的形式。編譯器

     磁盤是經過把其物理表面劃分紅多個空間來使用的。劃分的方式有扇區方式和可變長方式兩種,前者是指將磁盤劃分爲固定長度的空間,後者則是指把磁盤劃分爲長度可變的空間。通常Windows計算機所使用的硬盤和軟盤,採用的都是扇區方式。扇區方式中,把磁盤表面分紅若干個同心圓的空間就是磁道,把磁道按照固定大小(能存儲的數據長度相同)劃分而成的空間就是扇區。編譯

  

  扇區是對磁盤進行物理讀寫的最小單位。Windows中使用的磁盤,通常1個扇區是512字節。不過,Windows在邏輯方面(軟件方面)對磁盤進行讀寫的單位是扇區整數倍簇。根據磁盤容量的不一樣,1簇能夠是512字節(1簇=1扇區),1KB(1簇=2扇區),2KB,4KB,8KB,16KB,32KB(1簇=64扇區)。磁盤的容量越大,簇的容量也越大。效率

  

  這是我計算機上C盤的狀況  採用的是4KB。不論是硬盤仍是軟盤,不一樣的文件是不能存儲在同一個簇中的,不然就會致使只有一方的文件不能被刪除。所以,無論多麼小的文件,都會佔用1簇的空間。因此說,全部的文件都會佔用1簇的整數倍的磁盤空間。

  以簇位單位進行讀寫時,1簇中沒有填滿的區域會保持不被使用的狀態。雖然這看起來有點浪費,不過該機制就是如此規定的,因此咱們也沒有什麼好辦法。另外,若是減小簇的容量,磁盤訪問次數就會增長,就會致使讀寫文件的時間變長。因爲在磁盤表面上,表示扇區區分的領域是必要的,所以,若是簇的容量太小,磁盤的總體容量也會減小。扇區和簇的大小,是由處理速度和存儲容量的平衡來決定的。
相關文章
相關標籤/搜索