paging in linux,Linux Operating System

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

Paging in Linux

由於x86在32bit下有兩層的page table(PAE沒開情況下),而在64bit下有更多層,因此linux為了要在兩種處理器底下都能跑選擇了較高層的paging level。在2.6.10版本linux paging level有三層,從2.6.11版本之後增加到了四層page table。

如果四層都會用到的話,依照virtual address轉換到physical address的順序依序為:Page Global Directory、Page Upper Directory、Page Middle Directory、Page Table。如下圖所示:

e2529ba45b1139fcc4908398565bb07a.png

會用到這四層主要是x86_64的處理器需要用到,那對於32bit PAE沒有開啟情況以及Pentium這些只有兩層就夠的該如何處理呢?Linux這邊直接將中間兩層的大小設為0,也就是Page Upper Directory跟Page Middle Directory這兩層table消失,讓Page Global Directory直接指向第四層的page table,如下圖:

6cc54f61f9ac0fe9d091aa0cb91817f6.png

而在32bit下PAE開啟的話有三層page table,此時對應到的linux四層table如下:

ec4c5c9666f77127940ea04e7ef441b0.png

每個process都有屬於他的Page Global Directory以及page tables,當process switch發生時會將執行到一半的process的cr3暫存器的值存到descriptor中,然後再從GDT中找出將要執行的process的descriptor存到cr3,如此便能正確的指到page table。

Memory Addressing

接下來要講linux kernel的初始化,而實體記憶體當中有些位置是被保留的,就算是kernel也不能放在那些保留的位置中,這些被保留的位置放置了BIOS以及一些I/O Port,如下圖所配置:

eeec2c361cff7da6f7dab49c48bd394d.png

在主機板上的BIOS程式所放置的實體記憶體位置為0xF0000到0xFFFFF,而一些其他的硬體設備像是graphics cards的BIOS放置的位置則是在0xc0000到0xc7fff之間。而一些device的IO share memory則是會放置在0xa0000到0xfffff之間,這些程式是在OS起來之前所需要的,也就是剛開機時所執行的程式,雖然OS起來後就不會用到BIOS,但是下一次開機還是會用到,因此這些程式無論如何都不能被動到,不然你下次都開不了電腦了….而這些code都在0xfffff之前,也就是佔用了實體記憶體中的前16MB,因此這16MB的空間都不能動到,linux kernel會從16MB後開始放置kernel的東西。

How Kernel Initializes Its Own page tables

kernel在初始page table會有兩個階段,在phase one時會初始化kernel code data segment,以及page table跟動態資料結構。kernel code+data總共有7MB,而在剛開機時是靠bootmen allocator來配置記憶體,bootmen allocator所佔的記憶體空間為1MB,所以phase one當中會有24MB的virtual address需要mapping:

50900de799f0e2cebc0758686684f6a3.png

24MB的virtual address需要有6個entry來mapping到physical address,由於在paging機制開啟之前virtual address等於physical address,而在phase one當中會遭遇到從沒有paging到paging開啟這段過程,因此為了讓physical address一致,這邊會希望在phase one時mapping後的address會跟沒有paging時直接轉換的address相等。下圖為physical address layout:

0bcc2864f97b67f3a6a04b2d45695da3.png

而在phase one中會呼叫到一些位置在0xc0000000之後的code,而我們希望mapping到physical時也會再前24MB的地方,因此我們的paging table有些特別,它會讓0x00000000與0xc0000000指到同一塊physical address:

fe6be5b069a735795ba33abe645a3df5.png

相當於在0xc0000000之後的virtual address只要減去0xc0000000就會變成physical address。那要如何做到呢?在linux kernel中Page Global Directory會存在initial_page_table,而第二層的Page Tables會存在 _brk_base,配合剛所講的24MB會需要6個entry,因此設定entry 0~5以及768 ~ 773以外的entry為0,而entry0跟entry 768所指向的_brk_base會是同一個entry,故相當於768 entry以後的address都會減掉0xc0000000的offset了:

0f7d9f6277947a1eba0d54c412db7b6f.png

接下來看整個initial page table過程,首先在paging機制還沒開啟前,virtual address等於physical address,linux kernel程式都會在0x00000000到0x00800000:

e87f6035157d07d63cec9fa70e28ced1.png

在這個startup_32()中會把paging叫起來,它將initial_page_table load到cr3暫存器當中,接著將cr0的PG flag enable,因此paging開始在處理器上運行,此時virtual address轉換到physical address時會經過paging unit:

273bd2a75892a23a354f2867731cebfc.png

而在initial過程中它乎叫了i386_start_kernel()程式,這是C程式,放置的位置是在0xc0000000之後,因此可以看到我們剛剛所設計的page table用意在此:

35f9d63f7f403b559fd18288bad0544b.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值