分享好友 最新动态首页 最新动态分类 切换频道
page_to_pfn 、virt_to_page、 virt_to_phys、page、页帧pfn、内核虚拟地址、物理内存地址linux内核源码详解
2024-12-26 08:26

首先说说内核态虚拟地址和物理内存地址转换关系

page_to_pfn 、virt_to_page、 virt_to_phys、page、页帧pfn、内核虚拟地址、物理内存地址linux内核源码详解

  1. #define PAGE_OFFSET     UL(0xffffffc000000000)
  2. #define PHYS_OFFSET     ({ memstart_addr; })
  3. //把内核态虚拟地址转成物理地址
  4. #define __virt_to_phys(x)   (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
  5. //把物理内存地址转成内核态虚拟地址
  6. #define __phys_to_virt(x)   ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))

phys:物理内存地址

virt:内核态虚拟地址

virt内核态虚拟地址与phys物理内存地址是一个线性偏移关系,二者计算公式是 virt=phys-PHYS_OFFSET + PAGE_OFFSET。二者的转换关系可直接调用 __virt_to_phys __phys_to_virt 两个内核宏。PHYS_OFFSET 代表物理内存首地址PAGE_OFFSET是基于体系架构的偏移值,不同的架构不一样

我们在内核里调用kmalloc 返回的就是内核态虚拟地址。内核态虚拟地址属于什么?我们知道,系统空间分配用户空间和内核空间,比如有些32系统0~3G 属于用户空间3G~4G 属于内核空间。内核空间又由直接映射区、高端映射区(包含vmaloc区、动态映射区、固定映射区)组成,我们kmalloc分配内存就是从normal 直接映射区的分配一片内核空间,这片空间的内存地址便是内核态虚拟地址,与物理内存构成线性偏移关系。表面是从直接映射区内核空间分配走一片内核虚拟空间,实际在读写这片内存时,读写对应的是构成映射关系的物理内存。

接下来说说页帧pfn、物理内存的page指针的关系

  1. #define ARCH_PFN_OFFSET     (PAGE_OFFSET >> PAGE_SHIFT)
  2. //内存单元page指针数组mem_map+0代表第1个内存单元pagemem_map+1代表第2个内存单元page...
  3. struct page *mem_map;
  4. //把页帧转成内存单元对应的page
  5. #define __pfn_to_page(pfn)  (mem_map + ((pfn) - ARCH_PFN_OFFSET))
  6. //把内存单元对应的page转成页帧
  7. #define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + ARCH_PFN_OFFSET)
  8. //把内存单元对应page转成页帧
  9. #define page_to_pfn __page_to_pfn
  10. //把页帧转成其内存单元对应page
  11. #define pfn_to_page __pfn_to_page

内核把物理内存以4K大小分成一个个内存单元,每一个内存单元都用struct page结构管理。 mem_map 原型是struct page *mem_map,管理系统的物理内存。可以理解成它是一个指针数组,成员是每个内存单元的struct page指针,比如struct page *mem_map={page0,page1,page2,page3...}mem_map指向第一个内存的page指针。pfn叫做页帧,代表一个内存单元的物理起始地址,实际计算方法是pfn=phys/4K ,即物理内存地址除以4K就是页帧。

pfnpage的转换关系是。page=mem_map + (pfn - ARCH_PFN_OFFSET)ARCH_PFN_OFFSET 应该是第一个物理内存单元的页帧。第1个内存单元page=mem_map+( ARCH_PFN_OFFSET - ARCH_PFN_OFFSET)= mem_map+0,第2个内存单元page=mem_map+(ARCH_PFN_OFFSET+1 - ARCH_PFN_OFFSET) = mem_map+1

还有其他快捷的转换

  1. //把内核虚拟地址转成页帧
  2. #define virt_to_pfn(kaddr)  (__pa(kaddr) >> PAGE_SHIFT)
  3. //把页帧转成内核虚拟地址
  4. #define pfn_to_virt(pfn)    __va((pfn) << PAGE_SHIFT)
  5. //把内核虚拟地址转成其内存单元对应page
  6. #define virt_to_page(addr)  pfn_to_page(virt_to_pfn(addr))
  7. //把内存单元对应page转成内核虚拟地址
  8. #define page_to_virt(page)  pfn_to_virt(page_to_pfn(page))
  9. //把内核态虚拟地址转成物理地址
  10. #define __pa(x)         __virt_to_phys((unsigned long)(x))
  11. //把物理地址转成内核态虚拟地址
  12. #define __va(x)         ((void *)__phys_to_virt((phys_addr_t)(x)))

再总结一下物理内存page、页帧pfn、内核虚拟地址virt、物理内存地址phys的转换关系

virt=phys-PHYS_OFFSET + PAGE_OFFSET

pfn=phys/4K

page=mem_map + (pfn - ARCH_PFN_OFFSET)

内核里做一个实验,分配连续的物理内存,16K大小,然后以4K为单位打印每个内存单元对应的内核虚拟地址virt、物理地址physpage指针、页帧pfn

 

内核打印

 

可以发现连续两个内存单元,内核虚拟地址virt0x1000,即4Kphys物理地址相差0x1000page指针相差0x40struct page 大小sizeof(struct page)正是0x40;页帧pfn相差1。下边用示意图让我们有个更清晰的认识

最新文章
BIM和AI技术的协同应用优化方案
本文将讨论建筑信息模型(BIM)和人工智能(AI)技术的协同应用优化方案。随着科技的不断发展,BIM和AI技术在建筑行业的应用越来越广泛,通过它们的结合可以实现更高效的设计、施工和运营管理。BIM技术是一种基于三维模型的数字化建模工具
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
HTA(HTML Application)文件是一种可以在 Windows 上执行的 HTML 应用程序。由于其特性,攻击者可以利用 HTA 文件来执行恶意代码。本指南将结合 Metasploit 框架,展示如何利用 HTA 文件进行渗透测试。Kali LinuxMetasploit Framework 已
Google推广为什么分SEO、SEM,有什么区别
SEO是Search Engine Optimization的简称,也就是搜索引擎优化。指的是利用搜索引擎的规则,通过对网站进行内外部的调整和优化,从而提升网站的自然排名,主要是通过技术手段来获取搜索流量。SEM是Search Engine Marketing的简称,也就是搜
10种引流方法让你快速加满10000好友
现在是互联网的时代,不管是做什么行业的,最不可缺少的就是“流量” ,现在这个社会“流量”就等于“客源”,古圣给大家分享10种轻松加人的引流方法。1、主动去找用户去百度上找做保险的人、卖房子的人或者租房子的用户,一天怎么也能
Java毕业设计计算机毕设项目源码之基于Uniapp+ssm基于微信小程序的宠物寄养平台的设计与实现
《[含文档+PPT+源码等]精品微信小程序基于Uniapp+ssm基于微信小程序的宠物寄养平台的设计与实现》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功以及课程答疑与微信售后交流群、送查重系统
AI脚本关键词搜索优化:全面覆相关问题解决方案与技巧指南
在当今信息化时代脚本关键词搜索优化成为了升级搜索效率、提升使用者体验的关键手。本文将全面解析脚本关键词搜索优化的疑问解决方案与技巧帮助您更好地理解和应用关键词搜索技术。关键词搜索优化可以帮助脚本快速定位目标信息增强搜索效率
Gemini 2.0:谷歌推出的原生多模态输入输出 + Agent 为核心的 AI 模型
❤️ 如果你也关注 AI 的发展现状,且对 AI 应用开发非常感兴趣,我会每日跟你分享最新的 AI 资讯和开源应用,也会不定期分享自己的想法和开源实例,欢迎关注我哦!
2023全球最流行的6个AI logo生成器测评
Logo是一个品牌的身份象征,它可以帮助人们记住你的品牌并与之结合。所以,设计一个好看的logo重要性不需要过多强调,虽然我们可以去选择那些专业的设计师来帮我们量身定制,但往往创业初期囊中羞涩,使用在线 AI logo生成器是更加简单性价
100个python代码大全
1、for循环中的else条件 这是一个for-else方法,循环遍历列表时使用else语句。 下面举个例子,比如我们想检查一个列表中是否包含奇数。 那么可以通过for循环,遍历查找。2、数字求和执行以上代码输出结果为:3、随
相关文章
推荐文章
发表评论
0评