国产欧美一区二区精品行性色_91精品午夜在线观看_亚洲精品无码激情国产_91精品啪在线观看国产城中村_91看片国产一区二区色欲

始創(chuàng)于2000年 股票代碼:831685
咨詢熱線:0371-60135900 注冊(cè)有禮 登錄
  • 掛牌上市企業(yè)
  • 60秒人工響應(yīng)
  • 99.99%連通率
  • 7*24h人工
  • 故障100倍補(bǔ)償
全部產(chǎn)品
您的位置: 網(wǎng)站首頁(yè) > 幫助中心>文章內(nèi)容

深入理解Linux內(nèi)存映射機(jī)制 (3)

發(fā)布時(shí)間:  2012/8/15 18:18:47

向了第768個(gè)表項(xiàng)。

然后函數(shù)開(kāi)始一個(gè)循環(huán)即開(kāi)始填充從768到1024這256個(gè)目錄項(xiàng)的內(nèi)容。
one_md_table_init()函數(shù)根據(jù)pgd找到指向的pmd表。

它同樣在mm/init.c中定義:
static pmd_t * __init one_md_table_init(pgd_t *pgd)
{
pmd_t *pmd_table;

#ifdef CONFIG_X86_PAE
pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
if (pmd_table != pmd_offset(pgd, 0))
BUG();
#else
pmd_table = pmd_offset(pgd, 0);
#endif
return pmd_table;
}
可以看出, 如果內(nèi)核不啟用PAE選項(xiàng), 函數(shù)將通過(guò) pmd_offset返回pgd的地址。因?yàn)閘inux的二級(jí)映射模型,本來(lái)就是忽略pmd中間目錄表的。
接著又個(gè)判斷語(yǔ)句:
>> if (pfn >= max_low_pfn)
>> continue;
這個(gè)很關(guān)鍵, max_low_pfn代表著整個(gè)物理內(nèi)存一共有多少頁(yè)框。 當(dāng)pfn大于max_low_pfn的時(shí)候,表明內(nèi)核已經(jīng)把整個(gè)物理內(nèi)存都映射到了系統(tǒng)空間中, 所以剩下有沒(méi)被填充的表項(xiàng)就直接忽略了。因?yàn)閮?nèi)核已經(jīng)可以映射整個(gè)物理空間了, 沒(méi)必要繼續(xù)填充剩下的表項(xiàng)。
緊接著的第2個(gè)for循環(huán),在linux的3級(jí)映射模型中,是要設(shè)置pmd表的, 但在2級(jí)映射中忽略, 只循環(huán)一次,直接進(jìn)行頁(yè)表pte的設(shè)置。
>> address = pfn * PAGE_SIZE PAGE_OFFSET;
address是個(gè)線性地址, 根據(jù)上面的語(yǔ)句可以看出address是從0xc000000開(kāi)始的,也就是從內(nèi)核空間開(kāi)始,后面在設(shè)置頁(yè)表項(xiàng)屬性的時(shí)候會(huì)用到它.
>> pte = one_page_table_init(pmd);
根據(jù)pmd分配一個(gè)頁(yè)表, 代碼同樣在mm/init.c中:
static pte_t * __init one_page_table_init(pmd_t *pmd)
{
if (pmd_none(*pmd)) {
pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
if (page_table != pte_offset_kernel(pmd, 0))
BUG();
return page_table;
}
return pte_offset_kernel(pmd, 0);
}
pmd_none宏判斷pmd表是否為空, 如果為空則要利用alloc_bootmem_low_pages分配一個(gè)4k大小的物理頁(yè)面。 然后通過(guò)set_pmd(pmd, __pmd

(__pa(page_table) | _PAGE_TABLE));來(lái)設(shè)置pmd表項(xiàng)。page_table顯然屬于線性地址,先通過(guò)__pa宏轉(zhuǎn)化為物理地址,在與上_PAGE_TABLE宏,此時(shí)它們還是無(wú)符號(hào)整數(shù),在通過(guò)__pmd把無(wú)符號(hào)整數(shù)轉(zhuǎn)化為pmd類型,經(jīng)過(guò)這些轉(zhuǎn)換, 就得到了一個(gè)具有屬性的表項(xiàng), 然后通過(guò)set_pmd宏設(shè)置pmd表項(xiàng).

接著又是一個(gè)循環(huán),設(shè)置1024個(gè)頁(yè)表項(xiàng)。

is_kernel_text函數(shù)根據(jù)前面提到的address來(lái)判斷address線性地址是否屬于內(nèi)核代碼段,它同樣在mm/init.c中定義:

static inline int is_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)_stext && addr <= (unsigned long)__init_end)
return 1;
return 0;
}

_stext, __init_end是個(gè)內(nèi)核符號(hào), 在內(nèi)核鏈接的時(shí)候生成的, 分別表示內(nèi)核代碼段的開(kāi)始和終止地址.

如果address屬于內(nèi)核代碼段, 那么在設(shè)置頁(yè)表項(xiàng)的時(shí)候就要加個(gè)PAGE_KERNEL_EXEC屬性,如果不是,則加個(gè)PAGE_KERNEL屬性.

#define _PAGE_KERNEL_EXEC \
(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)

#define _PAGE_KERNEL \
(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)

最后通過(guò)set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));來(lái)設(shè)置頁(yè)表項(xiàng), 先通過(guò)pfn_pte宏根據(jù)頁(yè)框號(hào)和頁(yè)表項(xiàng)的屬性值合并成一個(gè)頁(yè)表項(xiàng)值,

然戶在用set_pte宏把頁(yè)表項(xiàng)值寫到頁(yè)表項(xiàng)里。
當(dāng)pagetable_init()函數(shù)返回后,內(nèi)核已經(jīng)設(shè)置好了內(nèi)核頁(yè)表,緊著調(diào)用load_cr3(swapper_pg_dir);
#define load_cr3(pgdir) \
asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir)))
將控制swapper_pg_dir送入控制寄存器cr3. 每當(dāng)重新設(shè)置cr3時(shí), CPU就會(huì)將頁(yè)面映射目錄所在的頁(yè)面裝入CPU內(nèi)部高速緩存中的TLB部分. 現(xiàn)在內(nèi)存中(實(shí)際上是高速緩存中)的映射目錄變了,就要再讓CPU裝入一次。由于頁(yè)面映射機(jī)制本來(lái)就是開(kāi)啟著的, 所以從這條指令以后就擴(kuò)大了系統(tǒng)空間中有映射區(qū)域的大小, 使整個(gè)映射覆蓋到整個(gè)物理內(nèi)存(高端內(nèi)存)除外. 實(shí)際上此時(shí)swapper_pg_dir中已經(jīng)改變的目錄項(xiàng)很可能還在高速緩存中, 所以還要通過(guò)__flush_tlb_all()將高速緩存中的內(nèi)容沖刷到內(nèi)存中,這樣才能保證內(nèi)存中映射目錄內(nèi)容的一致性。
3.4 對(duì)如何構(gòu)建頁(yè)表的總結(jié)
通過(guò)上述對(duì)pagetable_init()的剖析, 我們可以清晰的看到, 構(gòu)建內(nèi)核頁(yè)表, 無(wú)非就是向相應(yīng)的表項(xiàng)寫入下一級(jí)地址和屬性。 在內(nèi)核空間保留著一部分內(nèi)存專門用來(lái)存放內(nèi)核頁(yè)表.當(dāng)cpu要進(jìn)行尋址的時(shí)候,無(wú)論在內(nèi)核空間,還是在用戶空間, 都會(huì)通過(guò)這個(gè)頁(yè)表來(lái)進(jìn)行映射。對(duì)于這個(gè)函數(shù), 內(nèi)核把整個(gè)物理內(nèi)存空間都映射完了, 當(dāng)用戶空間的進(jìn)程要使用物理內(nèi)存時(shí), 豈不是不能做相應(yīng)的映射了? 其實(shí)不會(huì)的, 內(nèi)核只是做了映射, 映射不代表使用, 這樣做是內(nèi)核為了方便管理內(nèi)存而已。

四. 實(shí)例分析映射機(jī)制
4.1示例代碼
通過(guò)前面的理論分析,我們通過(guò)編寫一個(gè)簡(jiǎn)單的程序, 來(lái)分析內(nèi)核是如何把線性地址映射到物理地址的。
[root@localhost temp]# cat test.c
#include <stdio.h>
void test(void)
{
printf("hello, world.\n");
}
int main(void)
{
test();
}
這段代碼很簡(jiǎn)單, 我們故意要main調(diào)用test函數(shù), 就是想看下test函數(shù)的虛擬地址是如何映射成物理地址的。
4.2 段式映射分析
我們先編譯, 在反匯編下test文件
[root@localhost temp]# gcc -o test test.c
[root@localhost temp]# objdump -d test
08048368 <test>:
8048368: 55 push %ebp
8048369: 89 e5 mov %esp,%ebp
804836b: 83 ec 08 sub $0x8,%esp
804836e: 83 ec 0c sub $0xc,%esp
8048371: 68

億恩科技地址(ADD):鄭州市黃河路129號(hào)天一大廈608室 郵編(ZIP):450008 傳真(FAX):0371-60123888
   聯(lián)系:億恩小凡
   QQ:89317007
   電話:0371-63322206


本文出自:億恩科技【www.cmtents.com】

服務(wù)器租用/服務(wù)器托管中國(guó)五強(qiáng)!虛擬主機(jī)域名注冊(cè)頂級(jí)提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM]

  • 您可能在找
  • 億恩北京公司:
  • 經(jīng)營(yíng)性ICP/ISP證:京B2-20150015
  • 億恩鄭州公司:
  • 經(jīng)營(yíng)性ICP/ISP/IDC證:豫B1.B2-20060070
  • 億恩南昌公司:
  • 經(jīng)營(yíng)性ICP/ISP證:贛B2-20080012
  • 服務(wù)器/云主機(jī) 24小時(shí)售后服務(wù)電話:0371-60135900
  • 虛擬主機(jī)/智能建站 24小時(shí)售后服務(wù)電話:0371-60135900
  • 專注服務(wù)器托管17年
    掃掃關(guān)注-微信公眾號(hào)
    0371-60135900
    Copyright© 1999-2019 ENKJ All Rights Reserved 億恩科技 版權(quán)所有  地址:鄭州市高新區(qū)翠竹街1號(hào)總部企業(yè)基地億恩大廈  法律顧問(wèn):河南亞太人律師事務(wù)所郝建鋒、杜慧月律師   京公網(wǎng)安備41019702002023號(hào)
      0
     
     
     
     

    0371-60135900
    7*24小時(shí)客服服務(wù)熱線