標籤:c style class blog code a
本文主要介紹Linux0.12核心memory.c中的函數
1.void free_page(unsigned long addr)//釋放物理地址addr處的一頁記憶體。用於free_page_tables()函數void free_page(unsigned long addr){//首先判定給定物理地址的合理性。如果物理地址addr小於記憶體低端1M,對此不///予處理。如果addr>=記憶體最高端,則顯示出錯並且核心停止工作if(addr<LOW_MEM) return;if(addr>=HIGH_MEMORY)panic("trying to free nonexistent page");//如果對參數驗證通過,那麼就根據這個物理地址換算出從記憶體低端開始計算的//記憶體頁面號。頁面號=(addr-LOW_MEM)/4096。可見頁面號從0號開始計起。此///時addr中存放著頁面號。如果該頁面號對應的頁面映射位元組不等於0,則減1返//回。此時映射位元組值應該是0,表示頁面已經釋放。如果對應頁面位元組原本就///是0,表示該物理頁面本來就是閒置,說明核心代碼出問題,於是顯示出錯///並停機。addr-=LOW_MEM;addr>>=12;if(mem_map[addr]--) return;mem_map[addr]=0;panic("trying to free page);}2.int free_page_tables(unsigned long from,unsigned long size)//該函數釋放頁表連續的記憶體塊,只處理4MB長度的記憶體塊//根據指定的線性地址和限長(頁表個數),釋放對應記憶體頁表指定的記憶體塊共置表項//空閑。頁目錄位於物理地址0開始處,共1024項,每項4位元組,共佔4KB。每個目錄//項指定一個頁表。核心頁表從物理地址0x1000處開始,共4個頁表。每個頁表有10//24項,每項4B,因此也佔4KB記憶體。每個頁表最多可以映射1KB*4B=4M的實體記憶體。//參數:from--起始線性地址;size--釋放的位元組長度int free_page_tables(unsigned long from,unsigned long size){unsigned long *pa_table;unsigned long *dir,nr;//首先檢測參數from是否在4MB的邊界上,因為該函數只能處理這種情況。若fr//om=0,則出錯,說明釋放核心和緩衝所佔空間if(from & 0x3fffff)panic("free_page_tables called with wrong alignment")if(!from)panic("Trying to free up swapper memory space");//然後計算參數size給出的長度所佔的頁目錄項目數(4MB的進位整數倍),也即所佔頁表數。因為一個頁表可管理4MB實體記憶體,所以這裡用右移22位的方式把需要複製的記憶體長度值除以4MB。其中加上0x3fffff(即4MB-1)用於得到進位整數倍結果。即除操作若有餘數則進1。例如原size=4.01MB,那麼可到結果size=2。接著計算給出的線性地址對應的起始目錄項。對應的目錄項號=from>>22。因為每項佔4位元組,並且由於頁目錄表從物理地址0開始存放,因此實際目錄項指標=目錄項號<<2,也即from>>20。size=(size+0x3fffff)>>22;dir=(unsigned long *)((from>>20) & 0xffc);//此時size是釋放的頁表個數,即頁目錄項數,而dir是起始目錄項指標。現在開始迴圈操作頁目錄項,依次釋放每個頁表中的頁表項(??具體什麼操作叫釋放)。如果目前的目錄項無效(p=0),表示該目錄項沒有使用(對應的頁表不存在),則繼續處理下一個目錄項。否則從目錄項中取出頁表地址pg_table,並對該頁表中1024個表項進程處理,釋放有效頁表項對應的實體記憶體頁面,或者從交換裝置中釋放無效頁表項對應的頁面,即釋放交換裝置中對應的記憶體頁面。for(;size-->0;dir++){if(!(1 & *dir))continue;pg_table=(unsigned long *)(0xfffff000 & *dir);for(nr=0;nr<1024;nr++){if(*pg_table){if(1 & *pg_table){free_page(0xfffff000 & *pg_table)}elseswap_free(*pg_table>>1);*pg_table=0;}pg_table++;}free_page(0xfffff000 & *dir);*dir=0;//對應頁表的頁目錄項清零}invalidate();return 0;}
總結:
1.free_page()用於釋放指定物理地址處的一頁實體記憶體。假如物理地址對應的頁號是addr,那麼何謂釋放?實體記憶體就在那裡,我們所謂的擷取實體記憶體,其實就是使用一個標誌,說明我們佔用了他,相對應的,所謂的釋放就是清除表示,說明我們我們釋放了記憶體,釋放的本質就是:mem_map[addr]--。
2.free_page_tables()以一個頁表對應的實體記憶體為單位,釋放指定線性地址和長度(頁表個數)對應的實體記憶體頁塊。不僅對管理線性地址的頁目錄項和頁表中的頁表項內容進行修改(修改其實就是清0),同時會釋放對應的頁表記憶體和頁表項對應的實體記憶體。