【内存】高端内存映射

来源:互联网 发布:vb中名称和caption 编辑:程序博客网 时间:2024/04/30 16:35
    高端内存含义为:线性地址空间 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

原创粉丝点击