前情提要
延續上一篇,這篇記錄Project主要內容的實作過程。
題目的要求是:For each page directory entry with an index located in the group of indexes specified by the parameters, this system call shows the value of the present field of the entry.
簡單說就是新增一個system call
讓它可以取得當前process的page global directory entry中的present bit
參數包含兩個integer代表起始和結尾index
和一個陣列指標參數,存放結果
過程
新增system call和compile kernel的方法都在上一篇中,這邊不再贅述。
首先我們得先知道kernel中有個current指標能取得目前執行process的task_struct
而current->mm則會取得跟這個process memory management相關的mm_struct
current->mm->pgd就指向我們page directory table的開頭位址
再來我們先觀察Linux在32位元下的Linear address
Directory有10 bits、page table 10 bits、offset 22 bits
最左邊10 bits其實就可看作page directory的index
總共1024個page directory
我們的目標就是directory中entry的present
要得到某個page directory table中的entry可以用下面這種方式:current->mm->pgd[index]
它是一條長度1024的pgd_t陣列
有了page directory entry後
page directory entry的value第一位bit其實就是present bit
那就可以像下面這樣子取得present bit:pgd_val(current->mm->pgd[index]) & 0x01
pgd_val是取得pgd_t實際的值
最後的程式碼:
然後編譯kernel時PAE記得關
不然結果會不正確
make meunconfig時取消PAE(Ubuntu這版本預設有開)Processor type and features -> High Memory Support -> off
結果
從768以下的present bit結果可觀察出三份程式中
都各有一段連續的present bit是1
但所在位置都不同,這段連續的1其實就是對應到a[SIZE]
仔細觀察可發現三份code的a[SIZE]陣列剛好分別在stack、bss、heap段
而從present bit分布狀況來看的確符合不同區段的相對位置
註1: 這邊必須設定過a[SIZE]陣列中的元素才會使pgd present bit被設定
例如:for(int i = 0; i < SIZE; ++i) a[i] = i; 即可
註2: 因為原本SIZE有點小,可以設大一點方便觀察結果,例如設10000000
但因為SIZE很大,所以可能會Segmentation fault,可以用ulimit -s
來增大stack size
(這部分感謝jxcode大神指點)
註3: 觀察可發現三份code在index 32那個pgd present bit都是1
是因為code也需要有地方存放,那其實就是存放code的區段
而三個程式在entry 768以上的present bit都是相同的
驗證了我們學過的: Kernel是映射到0xc0000000
以上
(0xc0000000 >> 22 = 768)
整體似乎沒啥難度,主要是編kernel太花時間還有細節很多要注意的地方…
當初熬夜3天才做完QQ