Linux内核地址空间的布局
更新时间:2024-06-01 12:16:01 阅读量: 综合文库 文档下载
Linux内核地址空间的布局
1) Linux将整个4G线性地址空间分为用户空间和内核空间两部分,
而内核地址空间又被划分为\物理内存区\虚拟内存分配区\高端页面映射区\
\专用页面映射区\系统保留映射区\几个区域.
2) 在标准配置下, 物理区最大长度为896M, 系统的物理内存被顺序映射在物理区中,
在支持扩展页长(PSE)和全局页面(PGE)的机器上, 物理区使用4M页面并作为全局页面来处理.
当系统物理内存大于896M时, 超过物理区的那部分内存称为高端内存, 低端内存和高端内存用highmem_start_page变量来定界, 内核在存取高端内存时必须将它们映射到\高端页面映射区\
3) Linux保留内核空间最顶部128K区域作为保留区, 紧接保留区以下的一段区域为专用页面映射区,
它的总尺寸和每一页的用途由fixed_address枚举结构在编绎时预定义, 用__fix_to_virt(index)可获取专用区内预定义页面的逻辑地址.
在专用页面区内为每个CPU预定义了一张高端内存映射页, 用于在中断处理中高端页面的映射操作.
4) 距离内核空间顶部32M, 长度为4M的一段区域为高端内存映射区,
它正好占用1个页帧表所表示的物理内存总量, 它可以缓冲1024个高端页面的映射.
在物理区和高端映射区之间为虚存内存分配区, 用于vmalloc()函数, 它的前部与物理区有8M隔离带, 后部与高端映射区有8K的隔离带.
5) 当系统物理内存超过4G时,
必须使用CPU的扩展分页(PAE)模式所提供的64位页目录项才能存取到4G以上的物理内存.
在PAE模式下, 线性地址到物理地址的转换使用3级页表, 第1级页目录由线性地址的最高2位索引,
每一目录项对应1G的寻址空间, 第2级页目录项以9位索引, 每一目录项对应2M的寻址空间,
第3级页目录项以9位索引, 每一目录项对应4K的页帧.
除了页目录项所描述的物理地址扩展为36位外, 64位和32位页目录项结构没有什么区别.
在PAE模式下, 包含PSE位的中级页目录项所对应的页面从4M减少为2M.
/* Just any arbitrary offset to the start of the vmalloc VM area: the * current 8MB value just means that there will be a 8MB \after the * physical memory until the kernel virtual memory starts. That means
that
* any out-of-bounds memory accesses will hopefully be caught.
* The vmalloc() routines leaves a hole of 4kB between each vmalloced * area for the same reason. ;) */
#define VMALLOC_OFFSET (8*1024*1024) 虚拟区与物理区的隔离宽度 #define VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \\ ~(VMALLOC_OFFSET-1)) 虚拟区的开始
#define VMALLOC_VMADDR(x) ((unsigned long)(x)) #if CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) #else
# define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) #endif
#define PKMAP_BASE (0xfe000000UL) 高端映射区的开始
#define FIXADDR_TOP (0xffffe000UL) 专用映射区的顶部
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) 专用映射区尺寸
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) 专用映射区开始
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) 取专用映射区页面 /*
* on UP currently we will have no trace of the fixmap mechanizm, * no page table allocations, etc. This might change in the * future, say framebuffers for the console driver(s) could be * fix-mapped? */
enum fixed_addresses { 专用区页面的功能定义 #ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ #endif
#ifdef CONFIG_X86_IO_APIC FIX_IO_APIC_BASE_0, FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1, #endif
#ifdef CONFIG_X86_VISWS_APIC FIX_CO_CPU, /* Cobalt timer */
FIX_CO_APIC, /* Cobalt APIC Redirection Table */ FIX_LI_PCIA, /* Lithium PCI Bridge A */ FIX_LI_PCIB, /* Lithium PCI Bridge B */ #endif
#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_fixed_addresses };
enum km_type { KM_BOUNCE_READ, KM_BOUNCE_WRITE, KM_TYPE_NR };
; arch/i386/mm/init.c:
static void __init pagetable_init (void) 建立内核空间的页表 { unsigned long vaddr, end; pgd_t *pgd, *pgd_base; int i, j, k; pmd_t *pmd; pte_t *pte, *pte_base; /* * This can be zero as well - no problem, in that case we exit * the loops anyway due to the PTRS_PER_* conditions. */ end = (unsigned long)__va(max_low_pfn*PAGE_SIZE); 取内核物理内存区域终止边界物理地址 pgd_base = swapper_pg_dir; 取内核基准页目录表地址
#if CONFIG_X86_PAE 在PAE模式下, 首级页表只包含4个64位目录项 for (i = 0; i < PTRS_PER_PGD; i++) { pgd = pgd_base + i; __pgd_clear(pgd); } #endif i = __pgd_offset(PAGE_OFFSET); 取内核空间起始边界在首级页表内的地址偏移 pgd = pgd_base + i;
for (; i < PTRS_PER_PGD; pgd++, i++) { 扫描内核空间的页目录项 vaddr = i*PGDIR_SIZE; 取该目录项所对应物理区域的起始地址 if (end && (vaddr >= end)) 如果该映射区域起始边界大于或等于内核物理内存的终止边界 break; 退出扫描 #if CONFIG_X86_PAE pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); 分配中级页表 set_pgd(pgd, __pgd(__pa(pmd) + 0x1)); 将中级页表登记到首级页表 #else pmd = (pmd_t *)pgd; #endif if (pmd != pmd_offset(pgd, 0)) BUG(); for (j = 0; j < PTRS_PER_PMD; pmd++, j++) { 扫描中级页目录项,对于二级页表来说,循环一次 vaddr = i*PGDIR_SIZE + j*PMD_SIZE; 取该目录项映射区域的起始地址 if (end && (vaddr >= end)) break; if (cpu_has_pse) { 如果CPU具有扩展页长功能 unsigned long __pe; set_in_cr4(X86_CR4_PSE); boot_cpu_data.wp_works_ok = 1; __pe = _KERNPG_TABLE + _PAGE_PSE + _PAGE_USER + __pa(vaddr); 使用扩展页长目录项 /* Make it \ if (cpu_has_pge) { set_in_cr4(X86_CR4_PGE); __pe += _PAGE_GLOBAL; 设置全局页目录项标志 } set_pmd(pmd, __pmd(__pe)); 设置中级页表 continue; 继续下一中级页目录项 } ; 不使用扩展页长 pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); 分配页帧表 for (k = 0; k < PTRS_PER_PTE; pte++, k++) { 扫
描页帧目录项 vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE; 取页帧目录项所映射页面的起始地址 if (end && (vaddr >= end)) break; *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL); 设置页帧表 } set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base))); 设置中级页表 if (pte_base != pte_offset(pmd, 0)) BUG(); } } /* * Fixed mappings, only the page table structure has to be * created - mappings will be set by set_fixmap(): */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; 取专用区起始地址所在的中级页目录边界地址 fixrange_init(vaddr, 0, pgd_base); 建立专用区页表
#if CONFIG_HIGHMEM /* * Permanent kmaps: */ vaddr = PKMAP_BASE; fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); 建立高端映射区页表 pgd = swapper_pg_dir + __pgd_offset(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset(pmd, vaddr); pkmap_page_table = pte; 设置高端映射区所在的页帧目录 #endif
#if CONFIG_X86_PAE /* * Add low memory identity-mappings - SMP needs it when * starting up on an AP from real-mode. In the non-PAE * case we already have these mappings through head.S. * All user-space mappings are explicitly cleared after
* SMP startup. */ pgd_base[0] = pgd_base[USER_PTRS_PER_PGD]; #endif }
static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t
*pgd_base) { pgd_t *pgd; pmd_t *pmd; pte_t *pte; int i, j; unsigned long vaddr; vaddr = start; i = __pgd_offset(vaddr); j = __pmd_offset(vaddr); pgd = pgd_base + i; for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { #if CONFIG_X86_PAE if (pgd_none(*pgd)) { pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pgd(pgd, __pgd(__pa(pmd) + 0x1)); if (pmd != pmd_offset(pgd, 0)) printk(\ } pmd = pmd_offset(pgd, vaddr); #else pmd = (pmd_t *)pgd; #endif for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte))); if (pte != pte_offset(pmd, 0)) BUG(); } vaddr += PMD_SIZE;
}
}
}
j = 0;
正在阅读:
Linux内核地址空间的布局06-01
3对3 辩论赛--当今社会女人更累04-08
锻造生产安全与环保通则04-11
鸿业日照分析软件常见问题与解答201601-01
特别的演出作文450字06-30
武汉理工微机原理数字累加求和课设报告06-20
告诉你我很愉快作文600字06-29
自己做的ARM的UDP通信实验 - 图文04-20
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 内核
- 布局
- 地址
- Linux
- 空间
- 最新公共关系学试题及答案
- 淄博市2015年初中历史学业考试说明
- 湖北省2018-2019学年九年级下期中化学试卷(解析版)
- 关于车尔尼钢琴练习曲作品740的技术类型划分及其训练
- 浅析庄子的无为而治论
- 如何分析调节的各因素与近视眼的关系
- 第四节 - - 难溶电解质的溶解平衡
- 高教版中职数学(基础模块)下册8.3《两条直线的位置关系》word教
- 皮带输送机司机考试试题(标准题答案)
- 长沙房地产市场周报(2.11-2.17)
- 陕北唢呐与陕北丧事
- 货币金融学第的二章信用与信用工具
- 我的母校 杨岑
- 乡镇上半年宣传思想工作总结及下半年工作思路(多篇范文)
- 太阳能电池板发电原理
- 做最好的自己--杨澜在太平人寿第七届业务精英高峰论坛的演讲
- 中学健康教育工作实施方案
- 江苏省淮安市洪泽县2017届九年级英语下学期第一次模拟试题
- 2017年春仁爱版初中英语八年级英语下册全套全册精品教案
- 入职三个月工作总结