日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

操作系统原理第八章:内存管理

發布時間:2025/6/17 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 操作系统原理第八章:内存管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 1 內存管理背景
  • 2 固定分區分配
  • 3 動態內存分配
    • 3.1 首先適應 (First-fit)
    • 3.2 最佳適應 (Best-fit)
    • 3.3 外碎片問題
  • 4 分頁
  • 5 分頁硬件支持
  • 6 分段管理

1 內存管理背景

下圖是計算機系統中存儲層次結構:

本文主要討論的是其中的 主存 (primary storage) 部分。計算機程序在執行過程中,所有程序必需放入內存并放入一個進程才能被執行,程序是磁盤中的一個靜態的實體,通常對應著一個文件,所以的程序都是在輸入隊列中等待的,所謂輸入隊列就是磁盤上等待進入內存并執行的進程的集合。用戶程序在執行之前必需經歷很多步驟,這里可以以C語言為例參考我的這篇文章 C語言-用gcc指令體驗C語言編譯過程,如下圖所示:

在程序裝入內存中,存在著邏輯地址到物理地址的映射問題,即在邏輯地址中x的地址是200,但在物理地址中x的地址是1200,因為實際內存中不可能都是從地址0開始的,如下圖:

因此需要地址之間的綁定以便于指令能夠找到實際的物理地址,指令和數據綁定到內存地址可以在三個不同的階段發生:

  • 編譯時期:如果內存位置已知,可生成絕對代碼;如果開始位置改變,需要重新編譯代碼;
  • 裝入時期:如果存儲位置在編譯時不知道,則必須生成可重定位代碼,實際上進程在內存中是不可以移動的,若要移動進程則需要重新定位;
  • 執行時期:如果進程在執行時可以在內存中移動,則地址綁定要延遲到運行時。需要硬件對地址映射的支持,例如基址和限長寄存器。

下圖是三種綁定階段的示例圖。在編譯時綁定,則在編譯后就明確指出操作的物理地址,即move 1156 3表示把count的值放到地址為1156的位置;在加載時綁定,則在編譯后就明確指出操作的邏輯地址,即move 156 3,在加載到內存后進行變換,變換到1156的位置;在運行時綁定,則在編譯后也是只能給出邏輯地址,在加載到內存時,依然保存的是邏輯地址,但是當執行到這條語句時,再執行該指令的地址變換1000+156=1156。

上文所提及的邏輯地址物理地址兩個概念會貫穿于整個內存管理內容中,他們的定義如下:

  • 邏輯地址:由CPU產生;也叫做虛擬空間;
  • 物理地址:內存設備所讀入的地址。

在上面的圖中,指令move 1156 3中的1156就是邏輯地址,內存中的1156地址塊就是物理地址,可以發現在編譯時綁定和加載時綁定中,邏輯地址和物理地址是相同的,但在運行時綁定中,邏輯地址和物理地址是不同的。

我們把將程序裝入到與其地址空間不一致的物理空間,所引起的一系列地址變換過程叫做地址重定位,地址重定位分為如下兩種:

  • 靜態地址重定位:在裝入一個作業時,把作業中的指令地址全部轉換為絕對地址,在作業執行過程中就無須再進行地址轉換工作,如下圖:
  • 動態地址重定位:動態地址重地位是在程序執行過程中,在CPU訪問內存之前,將要訪問的程序或數據地址轉換成內存地址。動態重定位依靠硬件地址變換機構完成,如下圖:

    通過硬件把虛擬地址映射到物理地址,所需的硬件叫做內存管理單元(MMU),在MMU策略中,基址寄存器中的值被加入到用戶進程所產生的每個地址中,在其送入內存的時候,用戶程序所對應到的是邏輯地址,物理地址對它從來都不可見,如下圖:

2 固定分區分配

上一節中講的主要內容是如何把程序放入內存,即要實現邏輯地址到物理地址的映射,使之能夠正確的運行,這一節所講的主要內容是研究放入內存后如何給它分配內存空間,通常來說會為一個程序分配一段連續的內存空間,主要有:

  • 單一連續區管理方式:主要針對單道批處理系統,只有一個作業進入內存,內存被分為兩塊,一塊用來存放操作系統,一塊用來存放用戶程序,我們只要保證用戶程序不會影響到操作系統即可,使用基址寄存器策略來保護用戶進程(同其他進程和改變的操作系統代碼和數據分開),基址寄存器包含最小物理地址的值,即起始地址;限長寄存器包含邏輯地址的范圍,每個邏輯地址必需比限長寄存器的值小,即不能地址越界,判斷地址合法流程圖如下:
  • 多分區管理方式:是一種可用于多道程序的較簡單的存儲管理方式,它又分為固定分區方式可變分區方式。

對于固定分區分配方式,固定式分區是在作業裝入之前,內存就被劃分成若干個固定大小的連續分區,劃分工作可以由系統管理員完成,也可以由操作系統實現,一旦劃分完成,在系統運行期間不再重新劃分,即分區的個數不可變,分區的大小不可變,所以,固定式分區又稱為靜態分區劃分分區的方法如下:

  • 分區大小相等:比如有100MB內存,分五個分區,每個分區20MB,只適用于多個相同程序的并發執行(處理多個類型相同的對象),缺乏靈活性,會造成內碎片問題;

內碎片:比如一個分區大小是20MB,但是進程只需要16MB,多出的4MB用不上,而別的進程也無法使用,這4MB大小的空間就叫做內碎片。

  • 分區大小不等:多個小分區、適量的中等分區、少量的大分區。根據程序的大小,分配當前空閑的、適當大小的分區,兩種劃分方法示意圖如下圖所示:

一般將內存的用戶區域劃分成大小不等的分區,可適應不同大小的作業的需要。當作業到來時,系統有一張分區說明表,每個表目說明一個分區的大小、起始地址和是否已分配的使用標志,分區說明表和內存分配圖如下圖所示:

總結來說固定分區分配的優點是易于實現,開銷小;缺點是分區大小固定,會造成內碎片問題,同時由于分區總數固定,會限制并發執行的進程數目。

3 動態內存分配

在動態分區分配中,分區的劃分是動態的,不是預先確定的,當某個進程到來,它需要多少內存就給它分配多少內存,所以造成不同大小的分區分布在整個內存中,分配過程如下圖:

在這種方式下,操作系統也是需要知道內存的狀態的,可以采用空閑分區表空閑分區鏈兩種方式,如下圖:

在可變分區分配時要設計分區分配算法來尋找某個空閑分區,其大小需大于或等于程序的要求。若是大于要求,則將該分區分割成兩個分區,其中一個分區為要求的大小并標記為“占用”,而另一個分區為余下部分并標記為“空閑”。分區的先后次序通常是從內存低端到高端。同時也要設計分區釋放算法把相鄰的空閑分區合并成一個空閑分區。(這時要解決的問題是:合并條件的判斷)。

那么怎樣從一個空的分區序列中滿足一個申請需要?有如下三種方式:

  • 首先適應 (First-fit):分配最先找到的合適的分區;
  • 最佳適應 (Best-fit):搜索整個序列,找到適合條件的最小的分區進行分配;
  • 最差適應 (Worst-fit):搜索整個序列,尋找最大的分區進行分配。

很顯然,在速度和存儲的利用上,首先適應和最佳適應要比最差適應好。

3.1 首先適應 (First-fit)

首先適應的思想是從空閑分區表的第一個表目開始查找,把找到的第一個滿足要求的空閑區分配給作業,目的在于減少查找時間。通常將空閑分區表(空閑區鏈)中的空閑分區要按地址由低到高進行排序,它有如下特點:

  • 分配和釋放的時間性能較好,較大的空閑分區可以被保留在內存高端;
  • 隨著低端分區不斷劃分而產生較多小分區,每次分配時查找時間開銷會增大;
  • 在系統不斷地分配和回收中,必定會出現一些不連續的小的空閑區,稱為外碎片。雖然可能所有碎片的總和超過某一個作業的要求,但是由于不連續而無法分配。

外碎片:比如一塊內存中依次分配了三個進程 P1P_1P1?P2P_2P2?P3P_3P3?,其中 P2P_2P2? 占 20MB,此時 P2P_2P2? 運行結束了,釋放掉了自己的內存,然后來了一個新進程 P4P_4P4?P4P_4P4? 需要 18MB 的內存,恰好剛剛釋放掉了 P2P_2P2? 的20MB內存可以存放,但是會有 P4P_4P4?P3P_3P3? 之間會有一個 2MB 的內存,由于它太小了,很難分配到它,所以這 2MB 內存就叫做外碎片。

3.2 最佳適應 (Best-fit)

最佳適應的思想是從全部空閑區中找出能滿足作業要求的、且最小的空閑分區,能使碎片盡量小。為了提高查找效率,空閑分區表(空閑區鏈)中的空閑分區要按從小到大進行排序, 自表頭開始查找到第一個滿足要求的自由分區分配,它有如下特點:

  • 從個別來看,外碎片較小,但從整體來看,會形成較多無法利用的碎片;
  • 較大的空閑分區可以被保留。

下面是一個具體的例子,加入要分配一個16KB分區:

3.3 外碎片問題

在可變分區系統不斷地分配和回收中,必定會出現一些不連續的小的空閑區,稱為外碎片。雖然可能所有碎片的總和超過某一個作業的要求,但是由于不連續而無法分配。解決碎片的方法是拼接(或稱緊湊),即向一個方向(例如向低地址端)移動已分配的作業,使那些零散的小空閑區在另一方向連成一片,但分區的拼接技術,一方面要求能夠對作業進行動態重定位,另一方面系統在拼接時要耗費較多的時間,下圖是一個拼接的例子,存在著400K,300K,200K三個外碎片,可以將其朝高地址拼接,也可以移動某個進程,也可以在中間拼接:

4 分頁

上面所提到的用拼接解決外碎片問題在實現的時候還是有很多障礙的,我們需要思考還有沒有別的方法來解決外碎片問題,我們首先來看動態分區產生外碎片的原因是什么?這是因為這種分配要求把作業必須安置在一連續存儲區內的緣故;那么如果允許物理地址空間非連續,是否可以解決?分頁存儲管理是解決存儲碎片的一種方法,要避開連續性要求,允許進程的物理地址空間不連續

分頁的基本思想是進程的物理地址空間可以是不連續的,如果有可用的物理內存,它將分給進程。我們把物理內存分成大小固定的塊。把邏輯內存也分為固定大小的塊,叫做頁,要求頁的大小和塊的大小是一樣的,如下圖所示:

根據上圖可以看出,把邏輯內存劃分為塊之后,可以離散的分布在物理內存中。當然在這種情況下,操作系統需要知道哪些頁是空閑的,運行一個有N頁大小的程序,需要找到N個空的頁框讀入程序,還要解決的問題就是邏輯地址到物理地址的映射,我們是通過建立一個頁表,把邏輯地址轉換為物理地址。此外,由于內存塊的劃分是采用固定大小分配的,所以不可避免的會在最后一個頁中產生內碎片,地址映射如下圖所示:

我們知道由CPU產生的地址是邏輯地址,CPU 產生的地址被分為:

  • 頁號 p (Page number):它包含每個頁在物理內存中的基址,用來作為頁表的索引,也就是一個程序會被劃分為多個塊,對應在物理地址中是多個頁,頁號指明了具體是哪個頁;
  • 偏移 d (Page offset):同基址相結合,用來確定送入內存設備的物理內存地址,也就是一個頁內有很多地址,偏移是確定具體是哪個地址。

通過頁號和偏移確定物理地址的過程如下圖,通過頁號 p 去查找頁表 page table,找到在頁表中的哪個頁 f,然后把 f 取出來再加上偏移 d,就可以映射到所在的物理地址:

總結來說分頁解決了外碎片問題,但是會有內碎片,不過每個內碎片不會超過頁的大小,這個開銷相比之前的方法來說是可以接受的。一個程序不必連續存放,但也要求程序全部裝入內存才能執行。

5 分頁硬件支持

回顧分頁的過程,如下圖,在頁數比較小的時候可以直接把頁表放入寄存器,但當頁數很多的時候,顯然是要將頁表放入內存中:

將頁表放入內存后,要知道放在了內存的哪個地方,這里引入了兩個寄存器來保存頁表的位置:

  • 頁表基址寄存器 Page-table base register (PTBR):頁表基址寄存器指向頁表的起始地址;
  • 頁表限長寄存器 Page-table length register (PRLR):頁表限長寄存器表明頁表的長度。

在這個機制中,每一次的數據/指令存取需要兩次內存存取,一次是存取頁表,一次是存取數據,兩次的存取顯然性能不高,解決辦法是通過一個聯想寄存器 translation look-aside buffers (TLBs),可以解決兩次存取的問題。

聯想寄存器類似于一個快速緩存,每次查找一個頁的時候,都記錄下頁和頁的起始地址,當下次查詢的時候可以直接在聯想寄存器中尋找,找不到的時候再去查找頁表,此時地址映射的過程如下,相比在第四節中最后的那張圖多了一個聯想寄存器的查找步驟:

我們知道寄存器的存取速度是比內存快的,因此用這種方法能大大提高查找效率,舉個例子,我們假設聯想寄存器的查找需要時間 εεε,內存一次存取要111微秒,我們稱如果在聯想寄存器中找到了對應的頁地址的話,叫做“命中”,那么命中率 ααα 就為在聯想寄存器中找到頁號的比率,比率與聯想寄存器的大小有關,此時有效的存取時間 T=(1+ε)α+(2+ε)(1–α)=2+ε–αT=(1 + ε) α + (2 + ε)(1 – α)=2 + ε – αT=(1+ε)α+(2+ε)(1α)=2+εα

可以帶入具體數值來看一看,例如,假設檢索聯想存儲器的時間為 20ns20ns20ns ,訪問內存的時間為 100ns100ns100ns ,訪問聯想存儲器的命中率為 85% ,則 CPU 存取一個數據的平均時間為 T=0.85?120+0.15?220=135nsT=0.85*120+0.15*220=135nsT=0.85?120+0.15?220=135ns,訪問時間只增加 35%。如果不引入聯想存儲器,其訪問將延長一倍(達 200ns200ns200ns

下圖是分頁地址變換機構工作原理圖,首先按頁的大小分離出頁號和位移量,放入有效地址寄存器中,再將頁號與頁表長度進行比較,如果頁號大于頁表長度,越界中斷;再以頁號為索引查找頁表:將頁表始址與頁號和頁表項長度的乘積相加,便得到該表項在頁表中的位置,于是可從中得到該頁的物理塊號;然后將該物理塊號裝入物理地址寄存器的高址部分;最后將有效地址寄存器中的位移量直接復制到物理地址寄存器的低位部分,從而形成內存地址:

下面是一個具體的例子,圖中省略了越界判斷,先分離出了頁號和偏移,分別為 2 和 1C4,然后查找頁表,得到塊號地址為 8,然后將 8 放在物理地址寄存器的高位,把偏移 1C4 放在物理地址寄存器的低位,這個地址就是物理地址:

6 分段管理

上面所討論的分頁方式有效的解決了外碎片問題,但是實際上并沒有考慮用戶的觀點,也就是它在分頁的時候都是硬性的按照等大小來劃分,并不關心頁中存放的是程序還是數據。本節中引入的分段方式就是一種支持用戶觀點的內存管理機制。

一個程序是一些段的集合,一個段是一個邏輯單位,如主程序、子過程、函數、局部變量、全局變量等等內容,在用戶的眼里是把程序看作各個有機的部分,如下圖:

把程序的各個部分放入內存實際上也就是把這每個部分看成各個段,然后放入內存,如下圖:

在分段管理方式下要解決的問題依舊是邏輯地址到物理地址的映射問題,與分頁類似,分段管理方式下也有段表,和段偏移。由于分頁的每一頁都是固定大小的,所以只需要起始地址,但是分段的每一段大小是不等長的,所以這里定義了兩個變量:

  • 基址 (base):包括內存中段物理地址的起始地址;
  • 限長 (limit):指定段的長度;

從邏輯地址到物理地址的映射過程如下圖所示,段表中保存著每一段的起始地址和線長地址,這樣就在內存中唯一確定了段的地址范圍:

下圖是實現地址映射的物理結構流程圖,其過程和分頁的過程十分類似:

在分頁方式中,頁表是要保存在內存中的,所以當時定義了頁表基址寄存器(PTBR)和頁表限長寄存器 (PRLR)來指明頁表的位置,同樣在分段方式中,也定義了類似的兩個寄存器:

  • 段表基址寄存器 Segment-table base register (STBR):段表基址寄存器指向段表在內存中的地址;
  • 段表限長寄存器 Segment-table length register (STLR):段表限長寄存器表明被一個程序所使用的段的數目。

此時地址變化過程如下圖,首先系統將邏輯地址中的段號 S 與段表長度 TL 進行比較。若 S≥TL,訪問越界,若未越界,則根據段表的始址和該段的段號,計算出該段對應段表項的位置,從中讀出該段在內存中的起始地址;然后再檢查段內地址 d 是否超過該段的段長 SL 。若超過,即 d≥SL,同樣發出越界中斷信號;若未越界,則將該段的基址與段內地址 d 相加,得到要訪問的內存物理地址。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的操作系统原理第八章:内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。