基於X86架構的OS核心設計之雜記(五)

2021-10-10 04:58:14 字數 1893 閱讀 4770

解決前一篇博文所述問題,execve在釋放與父程序的頁表共享關係時導致核心重啟問題(順便糾正一下前一篇博文的描述,是我的核心出現了重啟,並不是bochs重啟了)。

先說明一下,核心在啟動分頁之前,把核心虛擬位址0xc0000000-0xc0800000對映到0x00000000-0x0080000(物理記憶體前8m),此後核心想要訪問記憶體最前端的8m位址,必須通過頁表轉換機制。

而我們的程序在execve時,將0-3gb的程序空間全部解除對映,即程序頁目錄表的前768項清零,如果execve此時訪問0-3gb的空間是,必定會產生page fault。

通過仔細的檢查了exeve的**,排除了所有編碼錯誤導致核心態直接訪問0-3g空間的疑點,但最後依然還是重啟,哎,完全沒了脾氣,無可奈何,只能用bochs單步除錯彙編指令的方法(沒有ide,十二分難受),艱難地跟蹤**執行,最後把問題定位在使用者空間的一條系統呼叫指令: int 0x80

核心通iret指令進入使用者態(move_to_user_mode)後,立刻進行一次fork系統呼叫產生init程序,通過跟蹤除錯,cpu在fork()呼叫陷入核心態後,很奇怪的,bochs顯示的**位址居然錯誤了:

虛擬位址由0x1b:0xc010d91a變為了0x08:0x001092c0,看出來cs段暫存器確實由r3進入了r0,但是虛擬位址居然偏移了0xc0000000,然而init程序與系統第乙個程序0同屬於核心**,位址都應該再0xc0000000以上才對,現在變為了0xc0000000,肯定存在問題。 無意中,通過bochs的info idt指令檢視了一下cpu的idt表,這不看不知道,一看嚇一跳:

所有已填充的表項,除了第32項,33項的位址是正確的,其他的項(第128項系統呼叫沒有截圖)中位址全是錯誤的,難怪。問題肯定處在這裡,找到idt的初始化,對比grap gate和interrupt gate初始化的區別(分別是通過三個巨集來定義):

#define set_igate_descriptor(n, _dpl,entry) \

dowhile(0)

#define set_trap_descriptor(n, _dpl,entry) \

dowhile(0)

#define set_system_descriptor(n,_dpl,entry)\

dowhile(0)

仔細對比這個3個巨集定義,發現grap gate的entry位址比interrupt gate少了最高4bit,導致32位位址最高4位缺失,原本應該是0xc01092c0,結果變成了0x001092c0,。 導致init程序進入核心態後,訪問的位址空間全部缺少了0xc0000000這個固定偏移,成為了使用者程序空間,且由於init程序在被fork時,頁表被mm_copy從task 0完整地複製了一次,使用者空間低8m正常對映,所以訪問該位址並不會出現問題,而當init程序再fork出子程序,子程序通過execve執行新的映象時,子程序的使用者空間被mm_free釋放掉,此時在核心空訪問0xc0000000以下的空間時,由於核心缺頁,導致一連串的問題出現。 還是手賤的問題。最後修改正確的巨集定義如下:

#define set_igate_descriptor(n, _dpl,entry) \

dowhile(0)

#define set_trap_descriptor(n, _dpl,entry) \

dowhile(0)

#define set_system_descriptor(n,_dpl,entry)\

dowhile(0)

總算平靜下來了。。。。

x86架構中特權級

特權級,可以分為三種 第 一 描述符中的特權級dpl,表示這個段的特權 第 二 選擇子的rpl表示請求方的特權級 第 三 當前特權級,表示正在執行的 段所具有的特權 下面有關特權級知識的總結 第一 對於資料段來說,特權級dpl表示了可以訪問該資料的最低特權。若資料段的dpl為1,那麼只有特權級為0或...

x86架構和arm構架

x86是英特爾公司開發的並且通治了幾十年.x86反應快在pc應用廣泛.86與arm最大不同在於指令集上.x86跟硬體發揮優勢.但是帶來的功耗大.arm構架指令簡單執行起來快功耗也低.現在智慧型手機和平板很火.平板電腦要求便攜和續航能力.arm構架具有低功耗.使之有了市場.那麼為什麼沒有得到普及原因主...

x86架構下的函式引數

這裡就拿x86 64架構下來舉例子,在這個架構下分別用rdi,rsi,rdx,rcx,r8,r9作為第1 6個引數。rax作為返回值 當我們去呼叫函式的時候 long test long a,long b,long c long sum long a,long b,long c,long d,lon...