1. 程式人生 > >【記憶體】高階記憶體對映

【記憶體】高階記憶體對映

    高階記憶體含義為:線性地址空間 PAGE_OFFSET + 896M至4G的最後128M線性地址  <==對映==> 896M以上的物理頁框,非直接對映。有3種方法:非連續記憶體區對映,永久核心對映,臨時核心對映(固定對映)
   從 PAGE_OFFSET開始的線性地址區域為:
   PAGE_OFFSET(3G)|實體記憶體對映 --8M-- vmallot區 --4K-- vmallot區 --8K-- 永久核心對映--臨時核心對映(固定對映)|4G

1. 非連續區對映

1.1 每個非連續記憶體區都對應一個型別為 vm_struct的描述符,通過next欄位,這些描述符被插入到一個vmlist連結串列中。

1.2 三種非連續區的型別:
   VM_ALLOC   -- 實體記憶體(呼叫alloc_page)和線性地址同時申請,實體記憶體是 __GFP_HIGHMEM型別(分配順序是HIGH, NORMAL, DMA )
   VM_MAP     -- 僅申請線性區,實體記憶體另外申請,是VM_ALLOC的簡化版
   VM_IOREMAP -- 僅申請線性區,實體記憶體另外申請(這裡的實體記憶體一般都是高階記憶體,大於896M的記憶體)

2. 永久核心對映

2.1 永久記憶體對映允許建立長期對映。使用主核心頁表中swapper_pg_dir的一個專門頁表。
    pkmap_page_table: 專門的頁表。頁表表項數由LAST_PKMAP(512或1024)產生。
    page_address_htable: 存放地址的
    pkmap_count: 包含LAST_PKMAP個計數器的陣列。
    PKMAP_BASE: 頁表線性地址從PKMAP_BASE開始。

2.2 如果LAST_PKMAP個項都用完,則把當前程序置為 TASK_UNINTERRUPTIBLE,並呼叫schedule()

3. 臨時記憶體對映

3.1 可以用在中斷處理函式和可延遲函式的內部,從不阻塞。因為臨時記憶體對映是固定記憶體對映的一部分,一個地址固定給一個核心成分使用。

3.2 每個CPU都有自己的一個13個視窗(一個線性地址及頁表項)的集合。
enum km_type {
    KM_BOUNCE_READ,
    KM_SKB_SUNRPC_DATA,
    KM_SKB_DATA_SOFTIRQ,
    KM_USER0,
    KM_USER1,
    KM_BIO_SRC_IRQ,
    KM_BIO_DST_IRQ,
    KM_PTE0,
    KM_PTE1,
    KM_IRQ0,
    KM_IRQ1,
    KM_SOFTIRQ0,
    KM_SOFTIRQ1,
    KM_TYPE_NR
};

所有固定對映的固定線性地址
enum fixed_addresses {
    FIX_HOLE,
    FIX_VSYSCALL,
        ....
#ifdef CONFIG_HIGHMEM
    FIX_KMAP_BEGIN,    /* reserved pte's for temporary kernel mappings */
    FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#endif
        .......
    __end_of_permanent_fixed_addresses,
    /* temporary boot-time mappings, used before ioremap() is functional */
#define NR_FIX_BTMAPS    16
    FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
    FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
    FIX_WP_TEST,
    __end_of_fixed_addresses
};

3.3 注意 fixed_addresses 的地址從上至下是倒著的,FIX_HOLE的地址等於 0xfffff000,是一個洞
#define __fix_to_virt(x)    (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __FIXADDR_TOP    0xfffff000