早期計(jì)算機(jī)都是直接訪問(wèn)物理內(nèi)存的,這樣想在內(nèi)存中同時(shí)運(yùn)行兩個(gè)程序是不可能的,想想為什么?
下面給出三種存儲(chǔ)模型:

第一種和第三種均不常用了,因?yàn)橛脩舫绦蛞坏┏霈F(xiàn)錯(cuò)誤,可能會(huì)銷毀OS,當(dāng)按上述方式裝載程序時(shí),新裝載的程序會(huì)覆蓋掉先前裝載的程序。唯一能并行的方法就是使用多線程,但是會(huì)共享信息,所以不可行。
后來(lái)提出內(nèi)存鍵的概念來(lái)區(qū)分在內(nèi)存中多道程序,此時(shí)內(nèi)存中可以裝載多道程序,但是一個(gè)程序可能因?yàn)閖mp指令跳轉(zhuǎn)到另一個(gè)程序從而發(fā)生程序崩潰。這都是因?yàn)槭褂昧私^對(duì)地址產(chǎn)生的問(wèn)題,一種解決辦法是采用靜態(tài)重定位的方法,比如一個(gè)程序裝入到16000地址位,則程序中地址數(shù)都要加上16000這個(gè)常數(shù),雖然這種方法一般來(lái)講是可行的,但是無(wú)法辨別它是重定位的地址還是不是重定位的地址,來(lái)了一個(gè)訪問(wèn)地址,那這個(gè)訪問(wèn)地址加不加16000,而且該方法會(huì)減慢裝載速度。
一種存儲(chǔ)器的抽象:地址空間
要想多個(gè)程序同時(shí)處于內(nèi)存中就需要解決兩個(gè)問(wèn)題:保護(hù)和重定向。我們希望每個(gè)程序都有自己獨(dú)立的一套地址空間。
一個(gè)簡(jiǎn)單的方法是使用動(dòng)態(tài)重定位,利用基址寄存器(存放程序開(kāi)始地址)和界限寄存器(存放程序大小),當(dāng)指令讀或?qū)憯?shù)據(jù)字前,CPU硬件會(huì)將其發(fā)送到內(nèi)存總線前與基址寄存器中的值相加,并判斷相加后的指令是否越界。但是每次都要做加法運(yùn)算和比較運(yùn)算就會(huì)顯得很慢。
交換技術(shù)的出現(xiàn)
將所有進(jìn)程都裝載入內(nèi)存是不大可能的,一種策略是將空閑進(jìn)程存入磁盤,將需要使用的進(jìn)程整個(gè)裝入內(nèi)存;另一種策略是虛擬內(nèi)存

交換在內(nèi)存中產(chǎn)生了多個(gè)空閑區(qū),通過(guò)把所有內(nèi)存盡可能向下移動(dòng),有可能將這些小的內(nèi)存區(qū)合并為大的內(nèi)存區(qū),這稱為內(nèi)存壓縮,但通常不進(jìn)行該操作,因?yàn)榉浅:臅r(shí),而且OS需要準(zhǔn)確的按其需要的大小分配內(nèi)存。
但是如果數(shù)據(jù)段可以增長(zhǎng),例如,很多程序語(yǔ)言都允許從堆中動(dòng)態(tài)分配內(nèi)存。所以我們可以為其預(yù)留一部分空間。

其中,堆棧存放私有變量和返回地址,向下增長(zhǎng)。數(shù)據(jù)段作為堆使用供變量動(dòng)態(tài)分配和釋放,向上增長(zhǎng)。
空閑內(nèi)存區(qū)管理-位圖方法
內(nèi)存可能被劃分為小到幾個(gè)字,大到幾千字節(jié)的分配單元,每個(gè)分配單元對(duì)應(yīng)位圖中的一位,0表示空閑,1表示占用。在分配一個(gè)k個(gè)分配單元的進(jìn)程時(shí),需要在位圖中查找k個(gè)連續(xù)的分配單元進(jìn)行分配,這是非常耗時(shí)的。
空閑內(nèi)存區(qū)管理-鏈表
還有一個(gè)方法是維護(hù)一個(gè)記錄已分配的內(nèi)存段和空閑內(nèi)存段的鏈表,設(shè)當(dāng)X進(jìn)程結(jié)束后同時(shí)需要合并內(nèi)存。

當(dāng)然,這里有很多算法可以分配內(nèi)存,有首次適配法,下次適配法,最佳適配法(會(huì)生成更多的小的空閑區(qū),可以考慮最差適配法)等。
虛擬內(nèi)存
為了防止某程序過(guò)大,最開(kāi)始采用覆蓋塊的方法,即手動(dòng)切割程序成一個(gè)個(gè)小塊,但是怎么切割是個(gè)問(wèn)題。于是這個(gè)問(wèn)題干脆交給計(jì)算機(jī)去做,虛擬內(nèi)存就誕生了。其基本思想是:
每個(gè)程序都有自己的基本空間,這個(gè)空間被分成多個(gè)塊,每個(gè)塊稱作一頁(yè)和頁(yè)面。(注意:虛擬內(nèi)存就是利用磁盤空間來(lái)擴(kuò)大內(nèi)存,所以稱為虛擬)
放張圖就明白了:

這里,我們通過(guò)頁(yè)表(基址+偏移量)來(lái)管理頁(yè)面,也可以加上TLB(塊表),計(jì)算機(jī)組成原理的內(nèi)容吧。有時(shí),單個(gè)頁(yè)表是不夠表示頁(yè)面的,所以我們可以采用二級(jí)頁(yè)表或多級(jí)頁(yè)表,來(lái)看下面一張圖:

有頁(yè)面自然也有頁(yè)面置換算法,這些算法有最優(yōu)頁(yè)面置換算法,最近未使用置換算法,先進(jìn)先出置換算法等

在考慮如何交換時(shí),如果考慮換出單個(gè)進(jìn)程中最小生存時(shí)間的頁(yè)面稱為局部頁(yè)面置換算法,考慮換出整個(gè)內(nèi)存中最小生存時(shí)間的頁(yè)面稱為全局頁(yè)面置換算法。通常情況下全局算法較好。另一種途徑是為進(jìn)程平均分配頁(yè)面,剩余放入公共池里面。
我們也可以采用測(cè)試缺頁(yè)中斷率的方法。
同時(shí),我們也應(yīng)該選則合適的頁(yè)面大小,在共享方面,一般只讀的頁(yè)面可以作為共享頁(yè)面來(lái)減少內(nèi)存消耗。
共享庫(kù)
在靜態(tài)鏈接.o程序時(shí),會(huì)造成很大的內(nèi)存消耗,因?yàn)橐溄硬煌瑤?kù)文件,這些庫(kù)文件直接裝載至內(nèi)存。但是共享庫(kù)(又稱動(dòng)態(tài)鏈接庫(kù),DLL),只會(huì)裝載一小段能夠在運(yùn)行時(shí)綁定被調(diào)用函數(shù)的存根例程,即用什么函數(shù),才裝入對(duì)應(yīng)的頁(yè)面而不是整個(gè)文件裝入。當(dāng)然,如果其它程序裝載了該共享庫(kù),則本程序就不需要裝載它了。
另外,如果DLL文件更新了,其并不需要重新編譯執(zhí)行,用戶只需要下載更新的DLL文件下次啟動(dòng)時(shí)即可使用。
來(lái)看兩個(gè)進(jìn)程使用共享庫(kù),需要用相對(duì)地址:

共享庫(kù)實(shí)際上是內(nèi)存映射文件的一個(gè)特例。
如何進(jìn)行缺頁(yè)中斷處理?

審核編輯:劉清
-
寄存器
+關(guān)注
關(guān)注
31文章
5608瀏覽量
129998 -
存儲(chǔ)器
+關(guān)注
關(guān)注
39文章
7739瀏覽量
171676 -
中斷處理
+關(guān)注
關(guān)注
0文章
96瀏覽量
11481
發(fā)布評(píng)論請(qǐng)先 登錄
請(qǐng)問(wèn)STM32下的LWIP同時(shí)使用TCP作為服務(wù)器支持熱插拔,SNTP進(jìn)行網(wǎng)絡(luò)對(duì)時(shí),同時(shí)運(yùn)行就會(huì)內(nèi)存溢出,獨(dú)立運(yùn)行沒(méi)問(wèn)題
——求 單片機(jī)如何讓兩個(gè)程序同時(shí)運(yùn)行 求 高手解決———
51單片機(jī)的兩個(gè)定時(shí)器可以同時(shí)運(yùn)行嗎?
怎么讓while循環(huán)里的兩個(gè)程序同時(shí)運(yùn)行?
ucosii如何實(shí)現(xiàn)兩個(gè)任務(wù)同時(shí)運(yùn)行而非按優(yōu)先級(jí)調(diào)度
Labview中可以同時(shí)運(yùn)行兩個(gè)不同的任務(wù)嗎?
如何同時(shí)運(yùn)行兩個(gè)niDaq模塊
51單片機(jī)驅(qū)動(dòng)4個(gè)電機(jī)同時(shí)運(yùn)行比一個(gè)或兩個(gè)運(yùn)行的轉(zhuǎn)速低
請(qǐng)問(wèn)F28377S的內(nèi)核和CLA可以同時(shí)運(yùn)行嗎?
如何用labview控制兩個(gè)程序同時(shí)運(yùn)行同時(shí)結(jié)束?
Harmony可以同時(shí)運(yùn)行兩個(gè)本地用戶嗎?
如何用IMXRT1176同時(shí)運(yùn)行兩個(gè)PAL攝像機(jī)?
在IMXRT1176-EVK上同時(shí)運(yùn)行兩個(gè)USB端口可行嗎?
什么是區(qū)塊鏈不可能三角為什么不可突破
單片機(jī)的程序在內(nèi)存和FLASH中應(yīng)該如何進(jìn)行空間分配
為什么在內(nèi)存中同時(shí)運(yùn)行兩個(gè)程序是不可能的
評(píng)論