日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OS- -内存之地址空间

發(fā)布時間:2024/4/11 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OS- -内存之地址空间 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

OS- -內存之地址空間

文章目錄

  • OS- -內存之地址空間
    • 一、內存
      • 1.無存儲器抽象
        • 運行多個程序
      • 2.一種存儲器抽象:地址空間
        • 地址空間的概念
        • 基址寄存器和變址寄存器
        • 交換技術
        • 交換過程
        • 空閑內存管理

一、內存

  • 主存(RAM)是一件非常重要的資源,必須要認真對待內存。雖然目前大多數(shù)內存的增長速度要比舊M7094要快的多,但是,程序大小的增長要比內存的增長還快很多。
  • 不管存儲器有多大,程序大小的增長 速度比內存容量的增長速度要快的多。

下面我們就來探討一下操作系統(tǒng)是如何創(chuàng)建內存并管理他們的。

  • 經(jīng)過多年的研究發(fā)現(xiàn),科學家提出了一種 分層存儲器體系(memory hierarchy),下面是分層體系的 分類
  • 位于頂層的存儲器速度最快,但是相對容量最小,成本非常高。層級結構向下,其訪問速度會變慢,但是容量會變大,相對造價也就越便宜。(所以個人感覺相對存儲容量來說,訪問速度是更重要的)
  • 操作系統(tǒng)中管理內存層次結構的部分稱為內存管理器(memory manager),它的主要工作是有效的管 理內存,記錄哪些內存是正在使用的,在進程需要時分配內存以及在進程完成時回收內存。所有現(xiàn)代操 作系統(tǒng)都提供內存管理。

下面我們會對不同的內存管理模型進行探討,從簡單到復雜,由于最低級別的緩存是由硬件進行管理 的,所以我們主要探討主存模型和如何對主存進行管理。

1.無存儲器抽象

  • 最簡單的存儲器抽象是無存儲器。

  • 早期大型計算機(20世紀60年代之前),小型計算機(20世紀 70年代之前)和個人計算機(20世紀80年代之前)都沒有存儲器抽象。

  • 每一個程序都直接訪問物理 內存。當一個程序執(zhí)行如下命令:

MOV REGISTER1, 1000
  • 計算機會把位置為1000的物理內存中的內容移到REGISTER1中。因此呈現(xiàn)給程序員的內存模型就 是物理內存,內存地址從開始到內存地址的最大值中,每個地址中都會包含一個8位位數(shù)的內存單元。
  • 所以這種情況下的計算機不可能會有兩個應用程序同時在內存中。如果第一個程序向內存地址2000 的這個位置寫入了一個值,那么此值將會替換第二個程序2000位置上的值

所以,同時運行兩個應用 程序是行不通的,兩個程序會立刻崩潰。

  • 不過即使存儲器模型就是物理內存,還是存在一些可變體的。下面展示了三種變體:
  • 在上圖a中,操作系統(tǒng)位于RAM(Random Access Memory)的底部,或像是圖b —樣位于ROM(Read-Only Memory)頂部;而在圖c中,設備驅動程序位于頂端的ROM中,而操作系統(tǒng)位于 底部的RAM中。
  • 圖a的模型以前用在大型機和小型機上,但現(xiàn)在已經(jīng)很少使用了;圖b中的模型一般 用于掌上電腦或者是嵌入式系統(tǒng)中。第三種模型就應用在早期個人計算機中了。
  • ROM系統(tǒng)中的一部分 成為BIOS (Basic Input Output System)。模型a和c的缺點是用戶程序中的錯誤可能會破壞 操作系統(tǒng),可能會導致災難性的后果。
  • 按照這種方式組織系統(tǒng)時,通常同一個時刻只能有一個進程正在運行。一旦用戶鍵入了一個命令,操作 系統(tǒng)就把需要的程序從磁盤復制到內存中并執(zhí)行;當進程運行結束后,操作系統(tǒng)在用戶終端顯示提示符 并等待新的命令。收到新的命令后,它把新的程序裝入內存,覆蓋前一個程序。
  • 在沒有存儲器抽象的系統(tǒng)中實現(xiàn)并行性一種方式是使用多線程來編程。
  • 由于同一進程中的多線程內部 共享同一內存映像,那么實現(xiàn)并行也就不是問題了。但是這種方式卻并沒有被廣泛采納,因為人們通常 希望能夠在同一時間內運行沒有關聯(lián)的程序,而這正是線程抽象所不能提供的。

運行多個程序

  • 但是,即便沒有存儲器抽象,同時運行多個程序也是有可能的。操作系統(tǒng)只需要把當前內存中所有內容 保存到磁盤文件中,然后再把程序讀入內存即可。只要某一時刻內存只有一個程序在運行,就不會有沖 突的情況發(fā)生。
  • 在額外特殊硬件的幫助下,即使沒有交換功能,也可以并行的運行多個程序。

舊M 360的早期模型就是 這樣解決的

  • 在舊M 360中,內存被劃分為2KB的區(qū)域塊,每塊區(qū)域被分配一個4位的保護鍵,保護鍵存儲在 CPU的特殊寄存器(SFR)中。
  • 一個內存為1MB的機器只需要512個這樣的4位寄存器,容量總共為 256字節(jié)
    PSW(Program StatusWord,程序狀態(tài)字)中有一個4位碼。
  • 一個運行中的進程如果訪問鍵與其PSW中保存的碼不同,360硬件會捕獲這種情況。
  • 因為只有操作系統(tǒng)可以修改保護鍵,這樣就可以防止進程之間、用戶進程和操作系統(tǒng)之間的干擾。

這種解決方式是有一個缺陷。如下所示,假設有兩個程序,每個大小各為16 KB

  • 從圖上可以看出,這是兩個不同的16KB程序的裝載過程,a程序首先會跳轉到地址24,那里是一條MOV指令,然而b程序會首先跳轉到地址28,地址28是一條CMP指令。
  • 這是兩個程序被先后加載到內存中的情況,假如這兩個程序被同時加載到內存中并且從0地址處開始執(zhí)行,內存的狀態(tài)就如上面c圖所示,程序裝載完成開始運行,
  • 第一個程序首先從0地址處開始運行,執(zhí)行JMP24指令,然后依次執(zhí)行后面的指令(許多指令沒有畫出),一段時間后第一個程序執(zhí)行完畢,然后開始執(zhí)行第二個
    程序。
  • 第二個程序的第一條指令是28,這條指令會使程序跳轉到第一個程序的ADD處,而不是事先設定好的跳轉指令CMP,由于這種不正確訪問,可能會造成程序崩潰。
  • 上面兩個程序的執(zhí)行過程中有一個核心問題,那就是都引用了絕對物理地址,這不是我們想要看到的。
  • 我們想要的是每一個程序都會引用一個私有的本地地址。舊M 360在第二個程序裝載到內存中的時候會 使用一種稱為靜態(tài)重定位(static relocation)的技術來修改它。它的工作流程如下:
  • 當一個程序被加載到16384地址時,常數(shù)16384被加到每一個程序地址上(所以JMP 28會變?yōu)镴MP 16412)。
  • 雖然這個機制在不出錯誤的情況下是可行的,但這不是一種通用的解決辦法,同時會減慢裝載速度。
  • 更近一步來講,它需要所有可執(zhí)行程序中的額外信息,以指示哪些包含(可重定位)地址,哪些不包含(可重定位)地址。
  • 畢竟,上圖b中的JMP28可以被重定向(被修改),而類似MOV REGISTER’28會把數(shù)字28移到REGISTER中則不會重定向。
  • 所以,裝載器(loader)需要一定的 能力來辨別地址和常數(shù)。

2.一種存儲器抽象:地址空間

  • 把物理內存暴露給進程會有幾個主要的缺點
  • 第一個問題是,如果用戶程序可以尋址內存的每個字節(jié),它們就可以很容易的破壞操作系統(tǒng),從而使系統(tǒng)停止運行(除非使用RM 360那種lock-and-key模式或者特殊的硬件進行保護)。即使在只有一個用戶進程運行的情況下,這個問題也存在。
  • 第二點是,這種模型想要運行多個程序是很困難的(如果只有一個CPU那就是順序執(zhí)行)。
  • 在個人計 算機上,一般會打開很多應用程序,比如輸入法、電子郵件、瀏覽器,這些進程在不同時刻會有一個進 程正在運行,其他應用程序可以通過鼠標來喚醒。在系統(tǒng)中沒有物理內存的情況下很難實現(xiàn)。

地址空間的概念

  • 如果要使多個應用程序同時運行在內存中,必須要解決兩個問題:保護和重定位。
  • 我們來看舊M 360是如何解決的:
  • 第一種解決方式是用保護密鑰標記內存塊,并將執(zhí)行過程的密鑰與提取的每個存儲 字的密鑰進行比較。這種方式只能解決第一種問題(破壞操作系統(tǒng)),但是不能解決多進程在內存中同 時運行的問題。
  • 還有一種更好的方式是創(chuàng)造一個存儲器抽象:地址空間(the address space)
  • 就像進程的概念創(chuàng)建 了一種抽象的CPU來運行程序,地址空間也創(chuàng)建了一種抽象內存供程序使用。地址空間是進程可以用 來尋址內存的地址集。每個進程都有它自己的地址空間,獨立于其他進程的地址空間,但是某些進程會 希望可以共享地址空間。

基址寄存器和變址寄存器

  • 最簡單的辦法是使用動態(tài)重定位(dynamic relocation)技術,它就是通過一種簡單的方式將每個進程的地址空間映射到物理內存的不同區(qū)域。
  • 從CDC 6600(世界上最早的超級計算機)到Intel 8088(原始IBM PC的核心)所使用的經(jīng)典辦法是給每個CPU配置兩個特殊硬件寄存器,通常叫做基 址寄存器(basic register)和變址寄存器(limit register)
  • 當使用基址寄存器和變址寄存器 時,程序會裝載到內存中的連續(xù)位置并且在裝載期間無需重定位。當一個進程運行時,程序的起始物理 地址裝載到基址寄存器中,程序的長度則裝載到變址寄存器中。
  • 在上圖c中,當一個程序運行時,裝載 到這些硬件寄存器中的基址和變址寄存器的值分別是0和16384。
  • 當?shù)诙€程序運行時,這些值分別是 16384和32768。
  • 如果第三個16 KB的程序直接裝載到第二個程序的地址之上并且運行,這時基址寄存器和變址寄存器的值會是32768和16384
  • 那么我們可以總結下

  • ?基址寄存器:存儲數(shù)據(jù)內存的起始位置

  • ?變址寄存器:存儲應用程序的長度

  • 每當進程引用內存以獲取指令或讀取、寫入數(shù)據(jù)時,CPU都會自動將基址值添加到進程生成的地址 中,然后再將其發(fā)送到內存總線上。

  • 同時,它檢查程序提供的地址是否大于或等于變址寄存器 中的 值。如果程序提供的地址要超過變址寄存器的范圍,那么會產生錯誤并中止訪問。

這樣,對上圖c中執(zhí) 行JMP 28這條指令后,硬件會把它解釋為JMP 16412 ,所以程序能夠跳到CMP指令,過程如下:

  • 使用基址寄存器和變址寄存器是給每個進程提供私有地址空間的一種非常好的方法,因為每個內存地址 在送到內存之前,都會先加上基址寄存器的內容。
  • 在很多實際系統(tǒng)中,對基址寄存器和變址寄存器都會 以一定的方式加以保護,使得只有操作系統(tǒng)可以修改它們。
  • 在CDC 6600中就提供了對這些寄存器的 保護,但在Intel 8088中則沒有,甚至沒有變址寄存器。
  • 但是,Intel 8088提供了許多基址寄存 器,使程序的代碼和數(shù)據(jù)可以被獨立的重定位,但是對于超出范圍的內存引用沒有提供保護。
  • 所以你可以知道使用基址寄存器和變址寄存器的缺點,在每次訪問內存時,都會進行ADD和CMP 運算。CMP指令可以執(zhí)行的很快,但是加法就會相對慢一些,除非使用特殊的加法電路,否則加法因 進位傳播時間而變慢。

交換技術

  • 如果計算機的物理內存足夠大來容納所有的進程,那么之前提及的方案或多或少是可行的。
  • 但是實際 上,所有進程需要的RAM總容量要遠遠高于內存的容量。
  • 在Windows. OS X、或者Linux系統(tǒng)中, 在計算機完成啟動(Boot)后,大約有50 - 100個進程隨之啟動。
  • 例如,當一個Windows應用程序 被安裝后,它通常會發(fā)出命令,以便在后續(xù)系統(tǒng)啟動時,將啟動一個進程,這個進程除了檢查應用程序 的更新外不做任何操作。
  • 一個簡單的應用程序可能會占用5 - 10MB的內存。其他后臺進程會檢查電 子郵件、網(wǎng)絡連接以及許多其他諸如此類的任務。
  • 這一切都會發(fā)生在第一個用戶啟動之前。
  • 如今,像 是Photoshop這樣的重要用戶應用程序僅僅需要500 MB來啟動,但是一旦它們開始處理數(shù)據(jù)就需 要許多GB來處理。
  • 從結果上來看,將所有進程始終保持在內存中需要大量內存,如果內存不足,則無 法完成。
  • 所以針對上面內存不足的問題,提出了兩種處理方式:最簡單的一種方式就是交換(swapping)技術,即把一個進程完整的調入內存,然后再內存中運行一段時間,再把它放回磁盤。空閑進程會存儲在磁盤中,所以這些進程在沒有運行時不會占用太多內存
  • 另外一種策略叫做虛擬內存(virtual memory),虛擬內存技術能夠允許應用程序部分的運行在內存中。

下面我們首先先探討一下交換

交換過程

下面是一個交換過程:

  • 剛開始的時候,只有進程A在內存中,然后從創(chuàng)建進程B和進程C或者從磁盤中把它們換入內存
  • 然 后在圖d中,A被換出內存到磁盤中,最后A重新進來。
  • 因為圖g中的進程A現(xiàn)在到了不同的位置, 所以在裝載過程中需要被重新定位,或者在交換程序時通過軟件來執(zhí)行;或者在程序執(zhí)行期間通過硬件 來重定位。
  • 基址寄存器和變址寄存器就適用于這種情況。
  • 交換在內存創(chuàng)建了多個 空閑區(qū)(hole),內存會把所有的空閑區(qū)盡可能向下移動合并成為一個大的空閑區(qū)。這項技術稱為內存緊縮(memory compaction)。
  • 但是這項技術通常不會使用,因為這項技術回消 耗很多CPU時間。
  • 例如,在一個16GB內存的機器上每8ns復制8字節(jié),它緊縮全部的內存大約要 花費16s。
  • 有一個值得注意的問題是,當進程被創(chuàng)建或者換入內存時應該為它分配多大的內存。
  • 如果進程被創(chuàng)建后 它的大小是固定的并且不再改變,那么分配策略就比較簡單:操作系統(tǒng)會準確的按其需要的大小進行分 配。
  • 但是如果進程的data segment能夠自動增長,例如,通過動態(tài)分配堆中的內存,肯定會出現(xiàn)問題

這里說一下什么是data segment吧。從邏輯層面操作系統(tǒng)把數(shù)據(jù)分成不同的段(不同的區(qū) 域)來存儲:

  • ?代碼段(codesegment/textsegment):

  • 又稱文本段,用來存放指令,運行代碼的一塊內存空間

  • 此空間大小在代碼運行前就已經(jīng)確定

  • 內存空間一般屬于只讀,某些架構的代碼也允許可寫

  • 在代碼段中,也有可能包含一些只讀的常數(shù)變量,例如字符串常量等。

  • ?數(shù)據(jù)段(datasegment):

  • 可讀可寫

  • 存儲初始化的全局變量和初始化的static變量

  • 數(shù)據(jù)段中數(shù)據(jù)的生存期是隨程序持續(xù)性(隨進程持續(xù)性)隨進程持續(xù)性:進程創(chuàng)建就存在,進程死亡就 消失

  • ?bss段(bsssegment):

  • 可讀可寫

  • 存儲未初始化的全局變量和未初始化的static變量

  • bss段中數(shù)據(jù)的生存期隨進程持續(xù)性

  • bss段中的數(shù)據(jù)一般默認為0

  • ?rodata 段:

  • 只讀數(shù)據(jù)也就是常量區(qū)。

  • 比如printf語句中的格式字符串和開關語句的跳轉表。
  • 例如,全局作用域中的 const int ival = 10, ival 存放在.rodata 段;
  • 再如,函數(shù)局部作用域中的 printf(“Hello world %d\n”, c); 語句中的格式字符串"Hello world%d\n",也存放在.rodata段。
  • ?棧(stack):

  • 可讀可寫

  • 存儲的是函數(shù)或代碼中的局部變量(非static變量)

  • 棧的生存期隨代碼塊持續(xù)性,代碼塊運行就給你分配空間,代碼塊結束,就自動回收空間

  • ?堆(heap):

  • 可讀可寫

  • 存儲的是程序運行期間動態(tài)分配的malloc/realloc的空間

  • 堆的生存期隨進程持續(xù)性,從malloc/realloc到free —直存在

下面是我們用Borland C++編譯過后的結果

  • 段定義(segment)是用來區(qū)分或者劃分范圍區(qū)域的意思。匯編語言的segment偽指令表示段定義的起始,ends偽指令表示段定義的結束。
  • 段定義是一段連續(xù)的內存空間,所以內存針對自動增長的區(qū)域,會有三種處理方式
  • ?如果一個進程與空閑區(qū)相鄰,那么可把該空閑區(qū)分配給進程以供其增大。
  • ?如果進程相鄰的是另一個進程,就會有兩種處理方式:要么把需要增長的進程移動到一個內存中空 閑區(qū)足夠大的區(qū)域,要么把一個或多個進程交換出去,已變成生成一個大的空閑區(qū)。
  • ?如果一個進程在內存中不能增長,而且磁盤上的交換區(qū)也滿了,那么這個進程只有掛起一些空閑空 間(或者可以結束該進程)
  • 上面只針對單個或者一小部分需要增長的進程采用的方式
  • 如果大部分進程都要在運行時增長,為了減 少因內存區(qū)域不夠而引起的進程交換和移動所產生的開銷,一種可用的方法是,在換入或移動進程時為 它分配一些額外的內存。
  • 然而,當進程被換出到磁盤上時,應該只交換實際上使用的內存,將額外的內 存交換也是一種浪費

下面是一種為兩個進程分配了增長空間的內存配置。

  • 如果進程有兩個可增長的段,例如,供變量動態(tài)分配和釋放的作為堆(全局變量)使用的一個數(shù)據(jù)段 (data segment),以及存放局部變量與返回地址的一個棧段(stack segment),就如圖b所 示。
  • 在圖中可以看到所示進程的堆棧段在進程所占內存的頂端向下增長,緊接著在程序段后的數(shù)據(jù)段向 上增長。
  • 當增長預留的內存區(qū)域不夠了,處理方式就如上面的流程圖(data segment自動增長的三種 處理方式)一樣了。

空閑內存管理

  • 在進行內存動態(tài)分配時,操作系統(tǒng)必須對其進行管理。大致上說,有兩種監(jiān)控內存使用的方式
  • ?位圖(bitmap)
  • ? 空閑列表(free lists)

下面我們就來探討一下這兩種使用方式

  • 使用位圖的存儲管理

  • 使用位圖方法時,內存可能被劃分為小到幾個字或大到幾千字節(jié)的分配單元。每個分配單元對應于位圖 中的一位,0表示空閑,1表示占用(或者相反)。

一塊內存區(qū)域和其對應的位圖如下:

  • 圖a表示一段有5個進程和3個空閑區(qū)的內存,刻度為內存分配單元,陰影區(qū)表示空閑(在位圖中用0表示);圖b表示對應的位圖;圖c表示用鏈表表示同樣的信息

  • 分配單元的大小是一個重要的設計因素,分配單位越小,位圖越大。

  • 然而,即使只有4字節(jié)的分配單 元,32位的內存也僅僅只需要位圖中的1位。32n位的內存需要n位的位圖,所以1個位圖只占用 1/32的內存。

  • 如果選擇更大的內存單元,位圖應該要更小。如果進程的大小不是分配單元的整數(shù) 倍,那么在最后一個分配單元中會有大量的內存被浪費。

  • 位圖提供了一種簡單的方法在固定大小的內存中跟蹤內存的使用情況,因為位圖的大小取決于內存和 分配單元的大小。

  • 這種方法有一個問題是,當決定為把具有k個分配單元的進程放入內存時,內容管 理器(memory manager)必須搜索位圖,在位圖中找出能夠運行k個連續(xù)0位的串。

  • 在位圖中找出制 定長度的連續(xù)0串是一個很耗時的操作,這是位圖的缺點。(可以簡單理解為在雜亂無章的數(shù)組中,找 出具有一大長串空閑的數(shù)組單元)

  • 使用鏈表進行管理

  • 另一種記錄內存使用情況的方法是,維護一個記錄已分配內存段和空閑內存段的鏈表,段會包含進程或 者是兩個進程的空閑區(qū)域。可用上面的圖c來表示內存的使用情況。

  • 鏈表中的每一項都可以代表一個空閑區(qū)(H)或者是進程§的起始標志,長度和下一個鏈表項的位置。

  • 在這個例子中,段鏈表(segment list)是按照地址排序的。這種方式的優(yōu)點是,當進程終止或被交 換時,更新列表很簡單。

  • 一個終止進程通常有兩個鄰居(除了內存的頂部和底部外)。相鄰的可能是進 程也可能是空閑區(qū)

它們有四種組合方式:

  • 當按照地址順序在鏈表中存放進程和空閑區(qū)時,有幾種算法可以為創(chuàng)建的進程(或者從磁盤中換入的進 程)分配內存。
  • 我們先假設內存管理器知道應該分配多少內存,最簡單的算法是使用 首次適配(first fit)。
  • 內存管理器會沿著段列表進行掃描,直到找個一個足夠大的空閑區(qū)為止
  • 除非空閑區(qū)大小和要 分配的空間大小一樣,否則將空閑區(qū)分為兩部分,一部分供進程使用;一部分生成新的空閑區(qū)。
  • 首次適 配算法是一種速度很快的算法,因為它會盡可能的搜索鏈表。
  • 首次適配的一個小的變體是 下次適配(next fit)。
  • 它和首次匹配的工作方式相同,只有一個不同之 處那就是下次適配在每次找到合適的空閑區(qū)時就會記錄當時的位置,以便下次尋找空閑區(qū)時從上次結束 的地方開始搜索,而不是像首次匹配算法那樣每次都會從頭開始搜索。
  • Bays(1997)證明了下次算法 的性能略低于首次匹配算法。
  • 另外一個著名的并且廣泛使用的算法是 最佳適配(best fit)。
  • 最佳適配會從頭到尾尋找整個鏈表, 找出能夠容納進程的最小空閑區(qū)。
  • 最佳適配算法會試圖找出最接近實際需要的空閑區(qū),以最好的匹配請 求和可用空閑區(qū),而不是先一次拆分一個以后可能會用到的大的空閑區(qū)。
  • 比如現(xiàn)在我們需要一個大小為 2的塊,那么首次匹配算法會把這個塊分配在位置5的空閑區(qū),而最佳適配算法會把該塊分配在位置為 18的空閑區(qū)

如下:

  • 那么最佳適配算法的性能如何呢?最佳適配會遍歷整個鏈表,所以最佳適配算法的性能要比首次匹配算 法差。
  • 但是令人想不到的是,最佳適配算法要比首次匹配和下次匹配算法浪費更多的內存,因為它會產 生大量無用的小緩沖區(qū),首次匹配算法生成的空閑區(qū)會更大一些。
  • 最佳適配的空閑區(qū)會分裂出很多非常小的緩沖區(qū),為了避免這一問題,可以考慮使用 最差適配(worst fit)算法
  • 即總是分配最大的內存區(qū)域(所以你現(xiàn)在明白為什么最佳適配算法會分裂出很多小緩沖區(qū) 了吧),使新分配的空閑區(qū)比較大從而可以繼續(xù)使用。仿真程序表明最差適配算法也不是一個好主意。
  • 如果為進程和空閑區(qū)維護各自獨立的鏈表,那么這四個算法的速度都能得到提高。這樣,這四種算法的 目標都是為了檢查空閑區(qū)而不是進程。
  • 但這種分配速度的提高的一個不可避免的代價是增加復雜度和減 慢內存釋放速度,因為必須將一個回收的段從進程鏈表中刪除并插入空閑鏈表區(qū)。
  • 如果進程和空閑區(qū)使用不同的鏈表,那么可以按照大小對空閑區(qū)鏈表排序,以便提高最佳適配算法的速 度。
  • 在使用最佳適配算法搜索由小到大排列的空閑區(qū)鏈表時,只要找到一個合適的空閑區(qū),則這個空閑 區(qū)就是能容納這個作業(yè)的最小空閑區(qū),因此是最佳匹配。
  • 因為空閑區(qū)鏈表以單鏈表形式組織,所以不需 要進一步搜索。空閑區(qū)鏈表按大小排序時,首次適配算法與最佳適配算法一樣快,而下次適配算法在這 里毫無意義。
  • 另一種分配算法是快速適配(quick fit)算法,它為那些常用大小的空閑區(qū)維護單獨的鏈表。
  • 例 如,有一個n項的表,該表的第一項是指向大小為4 KB的空閑區(qū)鏈表表頭指針,第二項是指向大小為8KB的空閑區(qū)鏈表表頭指針,第三項是指向大小為12KB的空閑區(qū)鏈表表頭指針,以此類推。
  • 比如 21 KB這樣的空閑區(qū)既可以放在20KB的鏈表中,也可以放在一個專門存放大小比較特別的空閑區(qū)鏈 表中。
  • 快速匹配算法尋找一個指定代銷的空閑區(qū)也是十分快速的,但它和所有將空閑區(qū)按大小排序的方案一 樣,都有一個共同的缺點,即在一個進程終止或被換出時,尋找它的相鄰塊并查看是否可以合并的過程 都是非常耗時的。如果不進行合并,內存將會很快分裂出大量進程無法利用的小空閑區(qū)。

總結

以上是生活随笔為你收集整理的OS- -内存之地址空间的全部內容,希望文章能夠幫你解決所遇到的問題。

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