cpu和記憶體之間有三根匯流排,位址,資料,和控制匯流排。
這是在說位址之間的問題。cpu和記憶體之間用位址來查詢資料,但是兩者的位址並不總是一樣的,cpu產生的是邏輯位址,而記憶體的就是實體地址。通常都是不一樣的,所以需要位址對映。
正好是從程式設計人員的角度看,(不考慮解釋執行)程式總是經過源程式編譯,連線,執行三個階段。在這個過程中,指令和資料就要調到記憶體。
位址**的三種形式:
編譯時:編譯時就生成了絕對位址。ms-dos的com程式就是這樣的。
載入時:編譯時編譯器生成可重定位**,在載入時**。
執行時:執行時才能繫結。
上面說的都是記憶體中的實體地址,對於編譯時和載入時的位址,實體地址和cpu產生的邏輯位址都是一樣的。但是對於執行時的繫結,邏輯位址(又稱虛擬位址)和實體地址是不一樣的。這時候就需要有乙個位址對映的問題,這個問題由mmu(記憶體管理單元)來完成。
這個實現其實就像是分段定址一樣,有乙個重定位暫存器,其實就是基址暫存器,cpu生成的都是邏輯位址,也就是說都是個偏移量,當要把資料放到記憶體裡時,總是要將偏移量加上基址才是真正的實體地址。
使用者處理的也都是邏輯位址,也就是說我們程式設計時檢視的位址都是邏輯位址。
動態載入:
就是說只有當執行時,並且程式呼叫子程式時,鏈結程式才將子程式調到記憶體裡,否則總是放到磁碟上儲存的。它也是先檢查是否子程式已經被載入,沒有的時候才載入。
執行時才進行鏈結。否則程式需要的模組都將被調入到記憶體,浪費空間。
記憶體的空間並不是很大,尤其它必須要裝載作業系統核心和使用者程序。當程序分配的空間不夠大時,有兩種策略:覆蓋和交換。
覆蓋就是將記憶體中不再需要的空間覆蓋掉,用來存放需要的資料。
交換就是將暫時不用的空間的資料交換出去到輔存,需要時再調回來。
但是仍然,對記憶體空間的合理分配是必要的,不同方法:
連續分配記憶體。
分頁技術:不需要連續的記憶體。
分段:使用者思考。
連續分配記憶體:
將記憶體劃分為固定大小的很多分割槽,規定每個分割槽存放乙個程序的資料。
這是基本思路,它的推廣就是將分割槽想象成諸多的孔(hole),總是找合適的孔來存放程序。用孔的概念就是來說明它的一定的靈活性,孔是由一些大小不等的孔組成的,但是你看起來還是乙個孔,如果程序比較小,就劃出乙個小孔,其他的不用,程序大的話就組成乙個大孔。如果程序太多就等待,直到可以容納為止。有一點動態分配的意思。
所以它是變長分割槽的,而不用乙個固定分割槽存放乙個程序。
但是本質是一樣的,程序分配的記憶體空間總是連續的。這樣有好處,乙個程序總是被固定在一定的範圍之內,這樣有利於程序保護:當程序出錯時,它能影響的也只是自己所在的那一塊記憶體,而不會導致大量的錯誤。
但是這樣會產生碎片。也就是兩個程序之間總有些空間是沒有使用也無法使用的。
所以有了分頁的方法:
它允許程序的位址可以是非連續的。
物理記憶體中還是分為固定大小的片段,叫做幀,對應的,邏輯記憶體(也就是cpu產生的邏輯位址的空間)也分為同樣大的片段,叫做頁,再同樣的,輔存中對應的叫做塊。
由於cpu產生的都是邏輯的位址,於是我們完全可以使它是連續的,因為使用者使用的都是邏輯位址,所以我們在檢視位址時看到的總是連續的,我們看到的就是邏輯記憶體。但是在實際的記憶體中它可以不是這樣的。
想想吧,那麼我們程式設計時檢視的連續的記憶體,以及我們畫的長方形的記憶體圖,都是邏輯記憶體,物理記憶體我們是沒法知道的,因為那是作業系統根據幀表分配的。幀表是什麼呢?幀是物理記憶體中的記憶體片段,它是對應頁的,所以幀表就是記錄那些被使用的頁。比如用1表示,另外不用的用0表示,當新的程序要求分配記憶體空間時,作業系統就檢視幀表就行了,哪些部分是1,忙著呢,哪些部分是0,好可以用!
這些連續的東西對應到實際的記憶體的物理空間,如果用連續記憶體分配的方法,就是一塊位址完全對應。但是用分頁呢,邏輯位址看上去是連續的,但是它對映到實體地址上就可以有一些處理方法了,這裡用的就是一張頁表,很簡單的記錄著cpu上邏輯的位址對應著記憶體中的哪個實體地址。好像很多事我們都是這樣做的。剩下的就是頁的大小的問題了,想想吧,如果頁太大,比如大到完全容納乙個程序,那麼就和連續記憶體分配一樣了,但是如果頁太小,小到記憶體中乙個記憶體單元就是乙個片段,是不是也好像沒問題?但是這樣的話頁表就太可怕了,1g的記憶體需要1g項個位址麼?不能也不需要,所以總要設定乙個合適的頁大小。
其實這樣的方法也就是一種重定位,邏輯位址是乙個偏移量,不同的頁就是不同的基址,然後基址加偏移就是實體地址了。
採用分頁的好處呢?它不會產生外部碎片。但是如果到最後乙個頁內,它很可能會產生內部碎片的。另外,頁表也需要額外的開銷。
分段:我們分析程式時,總是考慮它在記憶體中是怎樣的。我們知道全域性變數和常量是放在一起的。**段是放在棧區的,動態分配的資料是放在堆區的。但是這些區真的存在麼?即使不存在,我們檢視記憶體時,棧區的位址都是連續的,堆區的位址也都是連續的,好像它就是各個區佔一部分連續記憶體的。
但是你從前面方法中能看得出來麼?連續記憶體分配是將整個程序的資料都一排溜的放在一起,分頁只是分了記憶體片段,但是對於具體資料它是透明的,它沒有對各種資料,指令還是純資料做不同的處理。
分段的技術允許編譯器定義自己的段,我們說的堆區,棧區就是一種編譯器設定的。也就是這樣,編譯器才能夠識別程式設計**。這樣它的很多功能就可以實現了,比如指令和資料放在不同的地方,資料是屬於使用者的可以修改,指令卻是屬於作業系統的,它可以被定義為唯讀,不能被改變。
分段仍然需要邏輯位址和實體地址的對映。只不過它需要的是段表,段表記錄不同的資料位於什麼「段」,它當然也是用位址標記的,但就好象是給記憶體的段取個名字一樣。位址從幾到幾,**段,從幾到幾,堆區……是不是已經很好理解了?
其實它和分頁是差不多的,分頁也可以這麼理解。只不過分頁是固定大小的。而分段卻是動態分配的,並且它有不同的「使命」;
分段也會有記憶體碎片。
分段和分頁各有優缺點,段表和頁表都需要額外的開銷。分頁不會產生外部碎片,但是它隔離了邏輯位址和實體地址,並且毫無章法,完全動態。分段會產生外部碎片,但是它從我們的思考考慮,給記憶體加了別名。現在的思路總是取長補短,兩者合併,分段加分頁。
硬體支援:到底採用什麼方法來進行記憶體管理最大的決定因素是硬體支援。邏輯位址到實體地址的對映都是靠硬體來實現的。無論是連續分配還是段表還是頁表,都是一幫子位址暫存器,基址暫存器記錄記憶體片段的開始,而另乙個暫存器儲存長度資訊等等,程式設計中的變長陣列(其實就是堆)就是這麼做的。
碎片:
固定大小分配單元(分頁)會產生內部碎片。而不定長的方法(多分割槽和分段)會產生外部碎片。
共享:
分段和分頁時程序總是分為了多個模組,如果它們儲存的是特定的功能,那麼這些模組可以是共享的。而連續分配總是一段資料都是屬於乙個程序。
保護:
仍然是分段和分頁的多個模組,如果它們儲存的是特定的功能,可以設定是否唯讀,這就是保護。
HPS FPGA之間的位址對映學習
位址對映要用到mmap函式,對映實體地址到記憶體空間 即虛擬位址,因為作業系統只能訪問虛擬位址 應用層 相關的虛擬位址已經可以直接到應用的層級,相關的設定已經在embedded中給出 輕量級別的由匯流排下來的第乙個偏移位址已經由別人提供,是hps.h中的alt lwfpgaslvs ofst。在此基...
虛擬位址和實體地址之間的對映關係
1 虛擬位址和實體地址之間的對映是以頁 4kb 為單位進行對映的 2 每乙個程序中都有乙個程序控制塊 pcb 裡面包含了一些程序的資訊 頁目錄,狀態,控制代碼表,id,pid 3 對映過程 32位系統下 首先pcb中有乙個指向一級分頁表的指標,每乙個頁表的大小均為4096b 4kb 可以儲存1024...
程式 CPU 記憶體之間的關係
程式是什麼?程式是計算機每一步動作的一組指令,程式由指令和資料組成,正在執行的程式一般是從輔存載入到主存上的。在計算機裡,由cpu承擔對程式的解釋和執行。cpu是什麼?central processing unit 處理器 內部由數億個電晶體組成,這個玩意兒叫積體電路 integrated circ...