操作系統【四】分頁存儲管理

連續分配方式的缺點:
固定分區分配:缺乏靈活性,產生大量的內部碎片,內存的利用率較低
動態分區分配:會產生許多外部碎片,雖然可以用緊湊技術處理,但是緊湊技術的時間代價較高

基本分頁存儲管理

思想:把內存分為一個個相等的小分區,再按照分區大小將進程拆分成一個個小部分。

分區:頁框/頁幀/內存塊/物理塊
每一個頁框有一個編號,叫做頁框號/頁幀號/內存塊號/物理塊號,從0開始

我們將用戶進程的地址空間也分為與頁框大小相等的一個個區域,成為“頁”/“頁面”,每個頁面也有一個編號,叫做頁號。也是從0開始。

操作系統以頁框為單位為各個進程分配內存空間,進程的每個頁面分別放入一個頁框中。各個頁面不必連續存放,也不必按先后順序來,可以放到不相鄰的各個頁框中。

適用分頁存儲管理如何實現從邏輯地址到物理地址的轉換呢?

  1. 算出邏輯地址對應的頁號 頁號=邏輯地址/頁面長度(整除)
  2. 知道頁號對應頁面在內存中的起始地址 操作系統用某種數據結構記錄各個頁面的起始地址
  3. 算出邏輯地址在頁面中的偏移量 頁內偏移量=邏輯地址%頁面長度
  4. 物理地址=頁面地址+頁面偏移量

在計算機中為了方便計算頁號、頁內偏移量頁面的大小一般為2的整數冪

以32位邏輯地址為例,我們假設頁面的大小位4KB(4096B=212B),那么頁號就是前20位,頁內偏移量就是后12位。即如果頁面的大小為2kB,地址總共為n位,那么后k位是頁內偏移量,前面的n-k位就是頁號,這樣就解決了1、3問題。

頁內偏移量最大等于頁面大小等于頁框大小。一個進程最多有2n-k個頁(因為內存就這么大)

那如何知道頁號對應頁面在內存中的起始地址呢?

為了能夠知道進程的每個頁面在內存中存放的位置,操作系統要為每個進程創建一張頁表。

  1. 一個進程對應一張頁表
  2. 進程的每一頁對應一個頁表項
  3. 每個頁表項由頁號(一般不用儲存)和塊號組成,這一頁表項對應的起始地址=塊號*內存塊的大小+頁表首地址
  4. 頁表記錄進程頁面和實際存放內存塊之間的對應關系

內存/頁面大小=內存塊號的最大值
每個頁表項占字節數N=┌(log2內存塊號最大值)/8┐N = \ulcorner (log_2內存塊號最大值)/8 \urcornerN=(log2?)/8(因為每個字節是8B)

頁表的首地址為XXX
頁號YYY對應的頁表項的地址為X+N?YX+N*YX+N?Y

基本地址變換機構

頁表寄存器(PTR:存放頁表的起始地址F和頁表長度M)
進程未執行時,頁表的起始地址和頁表長度放在進程控制塊(PCB)中,當進程被調度時,操作系統內核會將他們放入頁表寄存器中。

在這里插入圖片描述

頁面大小為LLL,邏輯地址AAA到物理地址EEE的變換:

  1. 計算頁號P=A/LP=A/LP=A/L 頁內偏移量W=AmodLW=A \bmod LW=AmodL
  2. 比較頁號PPP和頁表寄存器PTRPTRPTR中頁表長度M(存儲了該進程有多少個頁),如果P>=MP>=MP>=M,則發生越界中斷,否則繼續執行
  3. 頁號P對應的頁表項地址=頁表起始地址F(存儲在PTR中)+P*頁表項長度(每個頁表項占多大的空間),取出頁表項內容b,即為該頁表所對應的頁框號/頁幀號/內存塊好。
  4. E=b?L+WE=b*L+WE=b?L+W(如果是二進制則直接拼接)

頁內偏移量 = 頁面大小

在分頁儲存管理(頁式管理)的系統中,只要確定了每個頁面的大小,邏輯地址結構就確定了。因此,頁式管理中地址是一維的。即, 只要給出一個邏輯地址,系統就可以自動算出頁號、頁內偏移量兩個部分,并不需要顯式告訴系統這個邏輯地址中,頁內偏移量占多少位。

上面計算出頁表項長度就可以表示內存塊號的范圍,但是為了方便頁表的查詢,常常讓一個頁表項占2kB,使得每個頁面恰好可以裝得下整數個頁表項也不至于當頁表長度超過一個頁框可以裝下的范圍的時候出現計算困難的問題。

例如:假設一個頁面4KB,32位的操作系統。則共有220個內存塊,即我們至少需要3個字節來保存內存塊的地址,每個頁表項長度為3B。頁表也是儲存在頁框中的。那么一個頁框可以存儲4096/3=1365個頁表項,最后會剩下一個字節。但是一個進程最多可以有220個頁表項,因此我們有可能需要跨頁框進行儲存。可是上一個頁框剩下的那一個字節我們不能夠再適用了,那么第1365個頁表的初始地址就不能簡單的計算為頁表起始地址+3頁號,在這里應該是頁表起始地址+3頁號+1。為了解決這個問題我們不妨讓每個頁表項占4KB,這樣就可以整除,雖然浪費了一些空間,但是計算上更加方便。

實際查詢兩次內存:第一次查詢頁表(相當于查找指針),第二次訪問內存(指針對應的值)

具有塊表的地址變換機構

局部性原理

時間局部性:如果在程序中執行了某條指令(訪問了某個數據),那么不久后這條指令(這個數據)很可能再次被訪問。(因為程序中存在大量的循環)

空間局部性:一旦程序訪問了某個儲存單元,不久之后,其附近的存儲單元也有可能被訪問。(因為很多數據在內存中都是連續存放的)

由于局部性原理,可能連續很多次查到的都是同一個頁表項。

快表

快表,又稱作聯想寄存器(TLB),是一種訪問速度比內存快很多的高速緩沖存儲器,用來存放當前訪問的若干頁表項,以加速地址變換的過程。與此對應,內存中的頁表常稱為慢表。

在這里插入圖片描述

  1. CPU給出邏輯地址,由某個硬件算得頁號、頁內偏移量,將頁號與快表中的所有頁號進行比較。
  2. 如果找到匹配的頁號,說明要訪問的頁表項在快表中有副本,則直接從中取出該頁對應的內存塊號,再將內存塊號與頁內偏移量拼接形成物理地址,最后訪問該物理地址對應的內存單元。因此,若快表命中,則訪問某個邏輯地址僅需要一次訪存即可。
  3. 如果在快表中沒有找到匹配的頁號,則需要訪問內存中的頁表,找到對應頁表項,得到頁面存放的內存塊號,,再將內存塊號與頁內偏移量拼接形成物理地址,最后訪問該物理地址對應的內存單元。(需要兩次訪存)在找到頁表項以后,應同時將其存入快表,以便后面可能的再次訪問。但若快表已滿,則必須按照一定的算法對舊的頁表項進行替換。

如果快表命中就可以節省很多時間。
在這里插入圖片描述快表和慢表同時查找:對于查詢快表和慢表的操作是同時進行的,如果在快表中查詢到,則會停止在慢表中的查詢。

兩級頁表

單級頁表存在的問題

問題1:如果計算機按字節尋址,支持32位邏輯地址,采用分頁存儲管理,頁面大小為4KB(212),頁表項長度為4B。那么一個進程最多有1M(220)個頁面,那么頁表的大小為222B,每一個頁框大小同樣為4KB,那么總共需要1K的頁框存儲這個頁表。這就要求所有的頁表都是連續的。這是比較困難的。

問題2:沒有必要讓整個頁表常駐內存,因為進程在一段時間內可能只需要訪問幾個特定的頁面

為了解決上面的問題,我們為頁表建立一個頁表,成為頁目錄表(外層頁表、頂層頁表),讓每一個內存塊存放一些頁表項。

在上面的例子中,一個內存塊(頁面)可以存放1K個頁表項。最多需要1K個這樣的內存塊,每個內存塊的地址為4B,剛好可以放在一個頁面中,而這個頁面就是頁目錄表。

在這里插入圖片描述
將邏輯地址轉換為物理地址:

  1. 按照地址結構將邏輯地址拆分為三部分
  2. 從PCB中讀出頁目錄表地址,再根據一級頁號查頁目錄表,找到下一級頁表在內存中的存放位置
  3. 再根據二級頁號以及該頁號所在的內存塊得到邏輯地址對應的內存塊
  4. 結合頁內偏移量得到物理地址:內存塊*內存塊大小+頁內偏移量

注意事項

  1. 若采用多級頁表機制,則各級頁表的大小不能超過一個頁面
    在這里插入圖片描述
  2. 兩級頁表的訪存次數分析(假設沒有快表機構)
    第一級訪存:訪問內存中的頁目錄表
    第二次訪存:訪問內存中的二級頁表
    第三次訪存:訪問目標中內存單元
    n級頁表的訪存次數是n+1次

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383659.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383659.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383659.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

聊聊同步、異步、阻塞與非阻塞

近來遇到了一些常見的概念,尤其是網絡編程方面的概念,如:阻塞、非阻塞、異步I/O等等,對于這些概念自己也沒有太清晰的認識,只是很模糊的概念,說了解吧也了解,但是要讓自己準確的描述概念方面的具…

操作系統【五】分段內存管理+段頁式內存管理

基本分段存儲管理 與分頁最大的區別:離散分配時所分配地址空間的基本單位不同 進程的地址空間:按照程序自身的邏輯關系劃分為若干個段,每個段都有一個段名,每段從0開始編址 內存分配規則:以段位單位進行分配&#xff…

計算機網絡【六】網絡層協議

網絡層負責在不同網絡之間盡力轉發數據包(基于數據包的IP地址轉發)。不負責丟失重傳,也不負責順序(每一個數據包都是單獨選擇路徑)。 可靠傳輸是由傳輸層實現。 網絡設備和OSI參考模型 通過分層,屏蔽了…

epoll 水平觸發與邊緣觸發

https://blog.csdn.net/lihao21/article/details/67631516?refmyread epoll也是實現I/O多路復用的一種方法,為了深入了解epoll的原理,我們先來看下epoll水平觸發(level trigger,LT,LT為epoll的默認工作模式&#xff…

計算機網絡【3】網絡層

主要任務時把分組從源端發送到目的端,為分組交換網上的不同主機提供服務。網絡層傳輸單位是數據報 功能: 路由選擇與分組轉發(最佳路徑 )異構網絡互聯擁塞控制 數據交換方式 電路交換:通信時延小、有序傳輸、沒有沖…

C++空類的大小

https://blog.csdn.net/lihao21/article/details/47973609 本文中所說是C的空類是指這個類不帶任何數據,即類中沒有非靜態(non-static)數據成員變量,沒有虛函數(virtual function),也沒有虛基類(virtual base class)。 直觀地看&#xff0c…

Linux探秘之用戶態與內核態

https://www.cnblogs.com/bakari/p/5520860.html 一、 Unix/Linux的體系架構 如上圖所示,從宏觀上來看,Linux操作系統的體系架構分為用戶態和內核態(或者用戶空間和內核)。內核從本質上看是一種軟件——控制計算機的硬件資源&…

哈夫曼算法證明+哈夫曼編碼譯碼程序實現

哈夫曼算法證明 哈夫曼算法是一種貪心算法,我們考慮證明其最優子結構和貪心選擇性質: 最優子結構:假設一個樹是哈夫曼樹,則以其任意節點為根節點的最大子樹也是哈夫曼樹。 證明:子樹的根節點的值是其所有葉子節點出現…

Python3小知識

對于迭代器對象,Python默認賦值是將引用賦值,即指向同一片內存空間。為了實現對內存空間的賦值,我們可以使用分片進行深復制。例如: 當定義元組的時候,我們一般使用小括號將元素包圍起來,也可以不使用括號…

匯編:實現日歷星期數查詢工具

編制一個簡單日歷查詢工具,輸入年、月、日,能夠判斷當日的星期數,并進行輸出,數據的輸入和結果的輸出要有必要的提示,且提示獨占一行。 查閱資料 ? 經過查閱資料,發現有兩個相關的算法可以解決這個問題&…

一個通用純C隊列的實現

https://blog.csdn.net/kxcfzyk/article/details/31728179 隊列并不是很復雜的數據結構,但是非常實用,這里實現一個隊列是因為在我的另一篇博客非常精簡的Linux線程池實現中要用到。 隊列API定義如下: //queue.h #ifndef QUEUE_H_INCLUDED…

Dijkstra算法介紹+正確性證明+性能分析

算法介紹 源點s,數組d[u]表示s到u的最短距離,空集S,點集Q初始化:將源點s從點集中去掉,加入S,d[s]0,?v∈Q,d[v]w[s][v]\forall v\in Q ,d[v]w[s][v]?v∈Q,d[v]w[s][v]將Q中d[v]最小的點去掉加入S,并對u∈…

Linux C 實現一個簡單的線程池

https://www.cnblogs.com/GyForever1004/p/9185240.html 線程池的定義 線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然后在創建線程后自動啟動這些任務。線程池線程都是后臺線程。每個線程都使用默認的堆棧大小,以默認的優先級…

斐波那契數列求解+尾遞歸

1.普通遞歸 這里觀察f[4]的遞歸樹代替f[10]的遞歸樹(后者比較大,畫不下)。 使用遞歸求解的時候復雜度為T(n)T(n?1)T(n?2)T(n)T(n-1)T(n-2)T(n)T(n?1)T(n?2),觀察遞歸樹,發現降速最快的是最右邊每次減2&#xff0c…

循環服務器,并發服務器模型以及I/O多路轉接模型

https://blog.csdn.net/xinianbuxiu/article/details/53455784 一、基于TCP/IP協議的基本循環服務器 tcp_server.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #incl…

c++繼承父類的子類,如何調用父類的同名函數?

https://blog.csdn.net/qq_26399665/article/details/52080215 子類調用父類的同名函數&#xff1a; 子類和父類返回值參數相同&#xff0c;函數名相同&#xff0c;有virtual關鍵字&#xff0c;則由對象的類型決定調用哪個函數。 子類和父類只要函數名相同&#xff0c;沒有vi…

LCS最長公共子串

問題介紹 LCS問題(longest common subsequence problem)指的是求解兩個字符串最長公共子序列問題。這里的子序列是可以不連續的。LCS問題廣泛地出現在計算生物學中&#xff08;DNA序列、系統生成樹等等&#xff09;。這里介紹如何解決LCS問題&#xff0c;以及算法的正確性證明…

將字符串中的空格用%20替換

如果不需要原地操作&#xff0c;則一遍遍歷&#xff0c;將非空串復制&#xff0c;遇到空格加上%20&#xff0c;如果需要原地操作&#xff0c;首先進行遍歷出空格的個數x,然后擴容2x,從后往前遍歷實現。如果非空格字符串比空格字符串多的多的時候而且字符串非常長的時候使用原地…

12步輕松搞定python裝飾器

http://python.jobbole.com/81683/ 呵呵&#xff01;作為一名教python的老師&#xff0c;我發現學生們基本上一開始很難搞定python的裝飾器&#xff0c;也許因為裝飾器確實很難懂。搞定裝飾器需要你了解一些函數式編程的概念&#xff0c;當然還有理解在python中定義和調用函數…

操作系統【六】虛擬內存

傳統存儲管理方式的不足 一次性&#xff1a;作業必須一次性全部裝入內存后才能開始運行。這會造成&#xff1a;當作也很大時不能全部裝入內存&#xff1b;當大量作業要求運行時&#xff0c;由于內存無法容納所有作業&#xff0c;因此只有少量作業能夠運行&#xff0c;導致多道…