??????? 這節(jié)我們討論linux是如何利用x86結(jié)構(gòu)中的段機(jī)制的,更確切的說(shuō)是如何繞過(guò)linux的段機(jī)制的。
??????? 我們決定從linux的可移植性開始討論。我們說(shuō)linux是一個(gè)廣泛移植的操作移動(dòng),它支持x86,Alpha,arm等多種體系結(jié)構(gòu)。但是很多的結(jié)構(gòu)其實(shí)都是不支持段機(jī)制的,比如arm,Alpha等,但是他們都支持分頁(yè)機(jī)制。linux為了能移植到x86上,做了不少工作。
??????? 首先我們說(shuō),x86是肯定有段機(jī)制的,那么我們要在x86上運(yùn)行程序,那不可避免要用到段機(jī)制。于是我們想到我們先前所想到的段描述符中有一個(gè)表示以字節(jié)為單位還是以頁(yè)為單位表示一個(gè)段長(zhǎng)度的屬性位。我們當(dāng)時(shí)說(shuō),當(dāng)G=1時(shí)表示以頁(yè)(4KB)為單位,那么一個(gè)段最大長(zhǎng)度能到4GB。根據(jù)這一點(diǎn),我們把一個(gè)段的段基址固定設(shè)置為0,然后讓G=1,于是我們一個(gè)段的最大長(zhǎng)度就是4GB了,吶,這個(gè)很顯然就能和我們4GB的線性地址空間一一映射了。通過(guò)這樣的處理,我們說(shuō)現(xiàn)在x86的段機(jī)制已經(jīng)形同虛設(shè)了,邏輯地址和線性地址可以混為一談了。
??????? 但是x86還規(guī)定說(shuō),必須為代碼段和數(shù)據(jù)段創(chuàng)建不同的段,所以linux為代碼段和數(shù)據(jù)段分別創(chuàng)建了一個(gè)基地址為0,段長(zhǎng)度為4GB的段描述符。不僅如此,由于linux內(nèi)核運(yùn)行在特權(quán)級(jí)0,用戶程序運(yùn)行在特權(quán)級(jí)3,x86規(guī)定說(shuō)特權(quán)級(jí)為3的用戶程序是不能訪問特權(quán)級(jí)為0的內(nèi)核代碼的,所以linux又分別為內(nèi)核和用戶程序分別創(chuàng)建代碼段和數(shù)據(jù)段。
??????? 于是在arch/x86/include/asm/segment.h中這樣定義四個(gè)段(即在機(jī)器啟動(dòng)過(guò)程中段寄存器中放的值):
#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS*8) #define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8) #define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8+3) #define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8+3)
??????? 其中:
#define GDT_ENTRY_DEFAULT_USER_CS 14 #define GDT_ENTRY_DEFAULT_USER_DS 15 #define GDT_ENTRY_KERNEL_BASE (12) #define GDT_ENTRY_KERNEL_CS (GDT_ENTRY_KERNEL_BASE+0) #define GDT_ENTRY_KERNEL_DS (GDT_ENTRY_KERNEL_BASE+1)
?
??????? 于是上邊的定義的結(jié)果是下邊這樣:
#define __KERNEL_CS 0x00C0 /*內(nèi)核代碼段,index=12,TI=0,RPL=0*/ #define __KERNEL_DS 0x00D0 /*內(nèi)核代碼段,index=13,TI=0,RPL=0*/ #define __USER_DS 0x00E3 /*用戶代碼段,index=14,TI=0,RPL=3*/ #define __USER_CS 0x00F3 /*用戶代碼段,index=15,TI=0,RPL=3*/
?
??????? 于是我們可以用12,13,14,15四個(gè)索引來(lái)找到我們四個(gè)段所對(duì)應(yīng)的段描述符,并且我們把內(nèi)核代碼段的特權(quán)聲明為0,用戶代碼段的特權(quán)為3,TI為0表示我們總是訪問全局描述符表。
??????? 在我們對(duì)應(yīng)的段描述符中我們把G設(shè)置為1,段上限規(guī)定為0xfffff,就巧妙的繞過(guò)了x86的段機(jī)制。
??????? 但在這里我不能忽略的一個(gè)問題就是,我們把四個(gè)段的上限全部設(shè)置為4G,那就完全破壞了段的保護(hù),就是說(shuō),我們有可能隨隨便便就修改了我們的其他段的數(shù)據(jù)。所幸,我們現(xiàn)在還是個(gè)線性地址,所幸此時(shí)我們還沒把數(shù)據(jù)裝載進(jìn)內(nèi)存,因此,我們就有處理這個(gè)問題的辦法,這就是下面要講的分頁(yè)機(jī)制了。
?
???????
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
