操作系統——虛擬內存管理

面試問題彙總:

1.邏輯地址、線性地址,物理地址,虛擬地址分別是什麼

物理地址,CPU地址總線傳來的地址,物理地址中很大一部分是留給內存條中的內存的

線性地址Linear Address)也叫虛擬地址(virtual address)是邏輯地址到物理地址變換之間的中間層。在分段部件中邏輯地址是段中的偏移地址,然後加上基地址就是線性地址。

邏輯地址是在有地址變換功能的計算機中,訪內指令給出的地址 (操作數) 叫邏輯地址,也叫相對地址,也就是是機器語言指令中,用來指定一個操作數或是一條指令的地址。要經過尋址方式的計算或變換纔得到內存儲器中的實際有效地址即物理地址。一個邏輯地址由兩部份組成,段標識符: 段內偏移量。段標識符是由一個16位長的字段組成,稱爲段選擇符。

2. 段式管理和頁式管理的優缺點?

3.Linux中的物理和虛擬存儲空間佈局

http://blog.csdn.net/tianyahaijiaozd/article/details/6784239


1. Linux中虛擬地址與物理地址之間的轉換


80386中邏輯地址到物理地址的轉換分爲兩步:1.段轉換(segment convert):邏輯地址轉換爲線性地址;2.頁轉換(page convert):線性地址轉換爲物理地址

段轉換:首先根據sector找到descriptor table(GDT)中對應的位置,找到描述符descriptor,每個descriptor項中有base,LIMIT,Type,DPL等,根據base找到該段的起始地址(線性地址中),然後加上offset,得到線性地址

頁轉換:線性地址的前10位是page dircetory中的索引位置,page directory中存放了page table的物理地址,根據線性地址的第二個10位可以得其在page table中的索引位置,加上page table的物理地址,可以得到該地址的PTE。PTE中記錄了該地址對應的物理地址


2.全局描述符表GDT和局部描述符表LDT

1.概況

80386體系結構中地址的轉換(邏輯地址--->物理地址)分爲兩個階段:

(1) logical address --------> linear address(segment translation)

(2) linear address ---------> physical address (page translation) [optional]

如果沒有頁轉換,那麼線性地址就是物理地址(例如boot loader在開啓page translation之前,線性地址就是物理地址)


段地址轉換的過程中需要使用到全局描述符表GDT(Global Destriptor Table)和局部描述符表LDT(Local Destriptor Table)

A descriptor table is simply a memory array of 8-byte entries that contain descriptors


logical addresss |------selector-----|----------offset----------------|

邏輯地址的selector用於索引描述符表中的entry,每個entry爲8B,加上基地址,便可以得到描述符表的位置,並取其中的內容,得到段地址的位置


2.GDT和LDT以及兩者的關係

GDT(Global Destriptor Table):每個cpu對應一個GDT,它可以存放在內存中的任何位置,但入口地址(基地址)存放在register(GDTR)中,程序員可以使用LGDT和SGDT進行load 和 store GDT的入口地址

LDT(Local Destriptor Table):每個process一個LDT,入口地址存放在register(LDTR)中,程序員可以只用LLDT和SLDT進行load和store

兩者的關係:

可以將GDT理解爲一級描述符表,LDT爲二級描述符表,(類似一級頁表和二級頁表),每個進程的LDT也是一段內存,因此它也有一個段描述符,這個描述符就存放在GDT中

每個進程都有自己的程序段,數據段,heap段,stack段,有了LDT,可以將每個進程的code segment, data segment, heap segment, stack segment封裝在一起,通過尋找GDT中的不同進行的LDT的位置,然後改變LDTR,便可以實現不同進程見的切換


3.段寄存器(Segment Register)

cs(cose segment), ss, DS(data segment), ES, FS, GS,使用段寄存器的目的是避免進程每次訪問地址時都需要進行內存訪問



物理地址就是實際的物理內存的地址,邏輯地址是程序指令使用的地址。頁表的作用就是實現邏輯地址到物理地址的映射。

x86的32位地址,前20位用於查找頁表

3.頁表和頁表項


TLB作用

由於頁表存放在主存中,因此程序每次訪存至少需要兩次:一次訪存獲取物理地址,第二次訪存才獲得數據。想像一下x86_32架構下沒有TLB的存在時的情況,對線性地址的訪問,首先從PGD中獲取PTE(第一次內存訪問),在PTE中獲取頁框地址(第二次內存訪問),最後訪問物理地址,總共需要3次RAM的訪問。

如果有TLB存在,並且TLB hit,那麼只需要一次RAM訪問即可。當cpu要訪問一個虛擬地址/線性地址時,CPU會首先根據虛擬地址的高20位(20是x86特定的,不同架構有不同的值)在TLB中查找。如果是表中沒有相應的表項,稱爲TLB miss,需要通過訪問慢速RAM中的頁表計算出相應的物理地址。同時,物理地址被存放在一個TLB表項中,以後對同一線性地址的訪問,直接從TLB表項中獲取物理地址即可,稱爲TLB hit

TLB內部存放的基本單位是頁表條目,對應着RAM中存放的頁表條目。頁表條目的大小固定不變的,所以TLB容量越大,所能存放的頁表條目越多,TLB hit的機率也越大。但是TLB容量畢竟是有限的,因此RAM頁表和TLB頁表條目無法做到一一對應。因此CPU收到一個線性地址,那麼必須快速做兩個判斷:

1 所需的也表示否已經緩存在TLB內部(TLB miss或者TLB hit)

2 所需的頁表在TLB的哪個條目內




4.地址的保護機制

保護主要包括以下幾點:

  • 進程不允許修改其只讀文本段
  • 不允許它讀或修改任何內核中的代碼和數據結構
  • 不允許它它讀或者寫其他進程的私有存儲器
  • 不允許修改與其他進程共享的虛擬頁面,除非所有的共享者顯示地允許它這麼做




5.缺頁中斷過程

發成缺頁中斷後,執行了那些操作?

當一個進程發生缺頁中斷的時候,進程會陷入內核態,執行以下操作

1、檢查要訪問的虛擬地址是否合法 

2、查找/分配一個物理頁 

3、填充物理頁內容(讀取磁盤,或者直接置0,或者啥也不幹)

4、建立映射關係(虛擬地址到物理地址) 




6.Linux中虛擬存儲器的實現

task_struct中有一個條目mm_struct,它描述了虛擬存儲器的當前狀態。pgd和mmap兩個變量,pgd指向page directory,mmap指向一個vm_area_structs(區域結構,段)的鏈表,其中每個vm_area_structs都描述了當前虛擬地址的一個區域。當內核運行該進程時,它就將pgd存放在CR3控制寄存器中

vm_area_structs中:vm_start, vm_end,..





6.動態存儲器分配

1.malloc, vmalloc, kmalloc的區別

  1. kmalloc和vmalloc是分配的是內核的內存,malloc分配的是用戶的內存
  2. kmalloc保證分配的內存在物理上是連續的,vmalloc保證的是在虛擬地址空間上的連續,malloc不保證任何東西(這點是自己猜測的,不一定正確)
  3. kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大
  4. 內存只有在要被DMA訪問的時候才需要物理上連續
  5. vmalloc比kmalloc要慢

2.malloc分配器算法

(1)如何實現malloc和free,slab算法,buddy算法

(3) Malloc在什麼情況下調用mmap?

從操作系統角度來看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk和mmap(不考慮共享內存)。brk是將數據段(.data)的最高地址指針_edata往高地址推,mmap是在進程的虛擬地址空間中(一般是堆和棧中間)找一塊空閒的。這兩種方式分配的都是虛擬內存,沒有分配物理內存。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操作系統負責分配物理內存,然後建立虛擬內存和物理內存之間的映射關係。

在標準C庫中,提供了malloc/free函數分配釋放內存,這兩個函數底層是由brk,mmap,munmap這些系統調用實現的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章