IT学习站-137zw.com

作者: 却写杂布计
查看: 110|回复: 0

more +资源更新Forums

more +随机图赏Gallery

价值368元 从Docker到K8S实战视频教程 五年工程师主讲 百度云价值368元 从Docker到K8S实战视频教程 五年工程师主讲 百度云
价值299 opencv+tensorflow入门人工智能图像处理 百度云 网盘 下载价值299 opencv+tensorflow入门人工智能图像处理 百度云 网盘 下载
价值199元 Nginx中间件搭建负载均衡安全防护动静分离视频 ...价值199元 Nginx中间件搭建负载均衡安全防护动静分离视频 ...
价值348元 RabbitMQ消息中间件技术精讲2018视频教程 百度云价值348元 RabbitMQ消息中间件技术精讲2018视频教程 百度云
云豹直播平台全套源码无限制完美运营版(安卓+IOS)源码云豹直播平台全套源码无限制完美运营版(安卓+IOS)源码
Spring Security4企业权限管理视频,完整版课程下载Spring Security4企业权限管理视频,完整版课程下载

【原创】(三)Linux paging_init解析

【原创】(三)Linux paging_init解析

[复制链接]
却写杂布计 | 显示全部楼层 发表于: 2019-11-14 09:30:03
却写杂布计 发表于: 2019-11-14 09:30:03 | 显示全部楼层 |阅读模式
查看: 110|回复: 0
背景


  • Read the fucking source code! --By 鲁迅
  • A picture is worth a thousand words. --By 高尔基
说明:

  • Kernel版本:4.14
  • ARM64处理器,Contex-A53,双核
  • 使用工具:Source Insight 3.5, Visio
1. 介绍

从(二)Linux物理内存初始化中,可知在paging_init调用之前,存放Kernel Image和DTB的两段物理内存区域可以访问了(相应的页表已经建立好)。尽管物理内存已经通过memblock_add添加进系统,但是这部分的物理内存到虚拟内存的映射还没有建立,可以通过memblock_alloc分配一段物理内存,但是还不能访问,一切还需要等待paging_init的执行。最终页表建立好后,可以通过虚拟地址去访问最终的物理地址了。
按照惯例,先上图,来一张ARM64内核的内存布局图片吧,最终的布局如下所示:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907233854385-1365207283

开启探索之旅吧!
2. paging_init

paging_init源代码短小精悍,直接贴上来,分模块来介绍吧。

  • mark 1:分配一页大小的物理内存存放pgd;
  • mark 2:将内核的各个段进行映射;
  • mark 3:将memblock子系统添加的物理内存进行映射;
  • mark 4:切换页表,并将新建立的页表内容替换swappper_pg_dir页表内容;
代码看起来费劲?图来了:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907233919382-85485881

下边将对各个子模块进一步的分析。
3. early_pgtable_alloc

这个模块与FIX MAP映射区域相关,建议先阅读前文(二)Linux物理内存初始化
先上图:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907233938369-447541387

FIX MAP的区域划分从图中可以看出来
本函数会先分配物理内存,然后借用之前的全局页表bm_pte,建立物理地址到虚拟地址的映射,这次映射的作用是为了去访问物理内存,把内存清零,所以它只是一个临时操作,操作完毕后,会调用pte_clear_fixmap()来清除映射。
early_pgtable_alloc之后,我们看到paging_init调用了pgd_set_fixmap函数,这个函数调用完后,通过memblock_alloc分配的物理内存,最终就会用来存放pgd table了,这片区域的内容最后也会拷贝到swapper_pg_dir中去。
4. map_kernel

map_kernel的主要工作是完成内核中各个段的映射,此外还包括了FIXADDR_START虚拟地址的映射,如下图:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907233959419-1599284142

映射完成之后,可以看一下具体各个段的区域,以我自己使用的平台为例:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907234010351-796860477

这些地址信息也能从System.map文件中找到。
aarch64-linux-gnu-objdump -x vmlinux能查看更详细的地址信息。
5. map_mem

从函数名字中可以看出,map_mem主要完成的是物理内存的映射,这部分的物理内存是通过memblock_add添加到系统中的,当对应的memblock设置了MEMBLOCK_NOMAP的标志时,则不对其进行地址映射。
map_mem函数中,会遍历memblock中的各个块,然后调用__map_memblock来完成实际的映射操作。先来一张效果图:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907234053558-1917912244

map_mem都是将物理地址映射到线性区域中,我们也发现了Kernel Image中的text, rodata段映射了两次,原因是其他的子系统,比如hibernate,会映射到线性区域中,可能需要线性区域的地址来引用内核的text, rodata,映射的时候也会限制成了只读/不可执行,防止意外修改或执行。
map_kernel和map_mem函数中的页表映射,最终都是调用__create_pgd_mapping函数实现的:
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907234105579-1641393232

总体来说,就是逐级页表建立映射关系,同时中间会进行权限的控制等。
细节不再赘述,代码结合图片阅读,效果会更佳噢。
6. 页表替换及内存释放

这部分代码不多,不上图了,看代码吧:简单来说,将新建立好的pgd页表内容,拷贝到swapper_pg_dir中,也就是覆盖掉之前的临时页表了。当拷贝完成后,显而易见的是,我们可以把paging_init一开始分配的物理内存给释放掉。
此外,在之前的文章也分析过swapper_pg_dir页表存放的时候,是连续存放的pgd, pud, pmd等,现在只需要复用swapper_pg_dir,其余的当然也是可以释放的了。
好了,点到为止,前路漫漫,离Buddy System,Slab,Malloc以及各种内存的骚操作好像还有很远的样子,待续吧。
【原创】(三)Linux paging_init解析  技术博客 1771657-20190907234128359-1375441302


来源:http://www.137zw.com
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
137zw.com IT学习站致力于免费提供精品的java技术教程和python技术教程,CCNA书籍/资料/CCNP书籍/资料教程/CCIE书籍/资料/H3C学习/认证/一级建造师考试/微软学习/认证/包括基础教程和高级实战教程,同时也提供分享网站源码下载和互联网相关一系列的技术教程,我们想做的就是让知识分享更有价值!(IT学习站官方唯一域名地址:www.137zw.com 请谨防假冒网站!)本站所有资源全部收集于互联网或网友自行分享,分享目的仅供大家学习与参考,如无意中侵犯您的合法权益,请联系本站管理员进行删除处理!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

浙ICP备19022368号-1|Archiver|手机版|IT学习站-137zw.com

GMT+8, 2020-7-6 01:24 , Processed in 0.182949 second(s), 33 queries .

快速回复 返回顶部 返回列表