2020-12-31

博客园Logo
首页
新闻
博问
专区
闪存
班级

代码改变世界
搜索
注册
登录
返回主页 机器感知 邮箱:jiauzhang@163.com • GitHub:https://github.com/jiauzhang
博客园
首页
新随笔
联系
订阅
管理
Linux内核源码分析之setup_arch (三)

  1. 前言

在 Linux内核源码分析之setup_arch (二) 中介绍了当前启动阶段的内存分配函数memblock_alloc,该内存分配函数在本篇将要介绍paging_init中用于页表和内存的分配,paging_init函数大致流程如下图所示。

  1. paging_init

2.1 build_mem_type_table

该函数根据具体的CPU架构对静态定义的mem_types数组中定义的属性进行调整。

2.2 prepare_page_table

该函数的作用是把页目录项清零,源码大致如下。首先是把虚拟地址范围[0, MODULES_VADDR]的页目录项清零,如果内核是模块区域以XIP方式运行的,则跳过内核部分的页目录,然后继续对区域[addr,PAGE_OFFSET]的页目录项清零,此时用户空间的页目录项已经全部清零;最后,把除了第一块内存条之外的内核空间[__phys_to_virt(end), VMALLOC_START]对应的页目录项清零。

/* arch/arm/mm/mmu.c /
static inline void prepare_page_table(void)
{
unsigned long addr;
phys_addr_t end;
/
<–(1)–> */
for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));

#ifdef CONFIG_XIP_KERNEL
addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK;
#endif
/* <–(2)–> */
for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));

end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
if (end >= lowmem_limit)
end = lowmem_limit;
/* <–(3)–> */
for (addr = __phys_to_virt(end);
addr < VMALLOC_START; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
}
2.3 map_lowmem

该函数将物理内存地址小于lowmem_limit的内存映射到内核空间,实际的内存映射工作在create_mapping中完成。

/* arch/arm/mm/mmu.c */
static void __init map_lowmem(void)
{

for_each_memblock(memory, reg) {
start = reg->base;
end = start + reg->size;

if (end > lowmem_limit)
end = lowmem_limit;
if (start >= end)
break;

map.pfn = __phys_to_pfn(start);
map.virtual = __phys_to_virt(start);
map.length = end - start;
map.type = MT_MEMORY;

create_mapping(&map, false);
}
}
create_mapping函数的大致流程如下图所示,这里需要提一下,linux内核使用的是四级页表,即PGD、PUD、PMD、PTE;而ARM32使用的是二级页表,即PMD、PTE。同时由于内存管理是以页为单位进行的,如果按照ARM硬件MMU的分页机制,一个PMD对应的PTE并不能完全占用完整个页,为了避免内存浪费,会在软件层面上将两个PMD对应的PTE放在一个页内,具体细节可以参考文件arch/arm/include/asm/pgtable-2level.h中的注释部分。最终会调用alloc_init_pte函数对指定范围的内存区域进行映射,其中的early_pte_alloc函数最终也会去调用 Linux内核源码分析之setup_arch (二) 中介绍的memblock_alloc函数来分配内存,最后将PTE所在页写入到PMD中即可完成映射。

/* arch/arm/mm/mmu.c */
static void __init alloc_init_pte(…)
{
pte_t *start_pte = early_pte_alloc(pmd);
pte_t *pte = start_pte + pte_index(addr);

do {
set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
pfn++;
} while (pte++, addr += PAGE_SIZE, addr != end);
early_pte_install(pmd, start_pte, type->prot_l1);
}
2.4 devicemaps_init

该函数大致流程如下图所示,首先调用early_alloc分配一个页,然后调用early_trap_init将向量表复制到新的页内,最后调用create_mapping将这个页映射到0xffff0000处,如果mdesc->map_io存在,还会对设备相关的IO进行映射。

2.5 kmap_init

这个函数非常简单,把大小为2MB的区间[PKMAP_BASE,PAGE_OFFSET]映射到内核空间。

/* arch/arm/mm/mmu.c */
static void __init kmap_init(void)
{
#ifdef CONFIG_HIGHMEM
pkmap_page_table = early_pte_alloc_and_install(pmd_off_k(PKMAP_BASE),
PKMAP_BASE, _PAGE_KERNEL_TABLE);
#endif
}
3. 总结

本文主要介绍了内核启动阶段页表初始化部分的内容,其中,build_mem_type_table负责根据不同CPU架构对mem_types进行调整,prepare_page_table负责将待初始化区域的页目录项清零,然后通过map_lowmem建立低端内存区域的页表映射,最后调用devicemaps_init建立对向量表和设备IO的映射。至此,除了bootmem_init函数没有分析之外,paging_init基本算是分析完了,bootmem_init的分析将在下一篇中给出。

分类: Linux
标签: 嵌入式, linxu
好文要顶 关注我 收藏该文
机器感知
关注 - 2
粉丝 - 3
+加关注
0 0
« 上一篇: Linux内核源码分析之setup_arch (二)
posted @ 2020-12-31 10:33 机器感知 阅读(48) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· InstallArch
· arch安装tim
· arch安装mariadb
· InnoSetupConpiler使用方法
· CentOS7安装setup工具
» 更多推荐…

最新 IT 新闻:
· 加速的B站,滞后的社区治理
· 天猫回应被市场监管总局处罚:全面整改所涉问题
· 携程CEO孙洁发表跨年署名文章:2020年每一位旅业人都是英雄
· MIT研发出可通过光让药物直接作用于靶子区域的方法:且无副作用
· 蛋壳公寓App下架全部房源 行业人士:腾讯或成为接盘方
» 更多新闻…
公告

机器感知
一个专注于SLAM、Linux、算法等相关技术文章分享的公众号
公众号:机器感知
昵称: 机器感知
园龄: 1年2个月
粉丝: 3
关注: 2
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索

找找看
常用链接

我的随笔
我的评论
我的参与
最新评论
我的标签
随笔分类

LeetCode(11)
Linux(13)
SLAM(1)
随笔档案

2020年12月(2)
2020年11月(2)
2020年6月(2)
2020年5月(3)
2020年4月(1)
2019年12月(3)
2019年11月(3)
2019年10月(9)
最新评论

  1. Re:LeetCode 题解汇总
    @ 代码改变世界-谢谢…
    –机器感知

  2. Re:LeetCode 题解汇总
    不错
    –代码改变世界-
    阅读排行榜

  3. 主流视觉SLAM、激光SLAM总结(2296)

  4. LeetCode 题解汇总(742)

  5. Linux内核配置过程(473)

  6. Linux内核构建过程(465)

  7. Linux内核最顶层文档(241)
    评论排行榜

  8. LeetCode 题解汇总(2)
    推荐排行榜

  9. Linux内核构建过程(1)

  10. Linux内核配置过程(1)

  11. LeetCode 题解汇总(1)
    Copyright © 2020 机器感知
    Powered by .NET 5.0 on Kubernetes

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值