[置顶] Linux 虚拟地址与物理地址的映射关系分析【转】
转自:http://blog.csdn.net/ordeder/article/details/41630945
版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文章,未经博主允许不得转载。
Ordeder原创文章,原文链接: http://blog.csdn.net/ordeder/article/details/41630945
源码版本 2.4.0
1. 虚拟空间
0-3G 用户空间 0x00000000 ~ 0xbfffffff
3-4G 内核空间 0xc0000000 ~ 0xffffffff
每个用户进程都有独立的用户空间(虚拟地址0-3),而内核空间是唯一的(相当于共享)
每个进程的用户空间用mm_struct描述,即task_struct.mm。
2.进程虚拟地址的组织
2.1 虚拟空间、用户空间
- struct mm_struct {
- struct vm_area_struct * mmap; /* list of VMAs */
- ...
- pgd_t * pgd; //用于地址映射
- atomic_t mm_users; /* How many users with user space? */
- atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
- int map_count; /* number of VMAs */
- ...
- //描述用户空间的段分布:数据段,代码段,堆栈段
- unsigned long start_code, end_code, start_data, end_data;
- unsigned long start_brk, brk, start_stack;
- unsigned long arg_start, arg_end, env_start, env_end;
- unsigned long rss, total_vm, locked_vm;
- ...
- };
以上结构描述了进程的用户空间的结构,其中
pgd_t 是该进程用户空间地址映射到物理地址时使用
vm_area_struct 是进程用户空间已映射到物理空间的虚拟地址区间,mmap是该空间区块组成的链表。
虚拟空间的空洞:虚拟空间还未被映射的区块(即没有被使用),那么就没有vm_area_struct结构
2.2 内存区间
- /*
- * This struct defines a memory VMM memory area. There is one of these
- * per VM-area/task. A VM area is any part of the process virtual memory
- * space that has a special rule for the page-fault handlers (ie a shared
- * library, the executable area etc).
- */
- struct vm_area_struct {
- struct mm_struct * vm_mm; /* VM area parameters */
- unsigned long vm_start; //虚拟空间起始地址
- unsigned long vm_end; //终止地址
- /* linked list of VM areas per task, sorted by address */
- struct vm_area_struct *vm_next;
- //该区间的权限及标志
- pgprot_t vm_page_prot;
- unsigned long vm_flags;
- //一些vm_area 的链接
- ...
- struct vm_operations_struct * vm_ops;
- unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
- struct file * vm_file; //用于将磁盘文件映射至用户空间
- ...
- };
虚拟空间区间的描述中:
vm_start/vm_end 为该区块的起始和结束地址
vm_file 是在文件映射中使用到,即常用的mmap(fd,...)函数,简单说即将虚拟空间映射至文件在内核的缓冲区,那么这时候访问该虚拟空间将有别于pgd的映射。
vm_operations_struct 为本虚拟区间的操作,其中的nopage函数指针是处理内存缺页而使用的。对于通用的内存映射,该缺页处理函数为do_no_page()将虚拟地址映射到物理地址(匿名映射):分配物理页& 设置pgd & pte。
而对于mmap操作相关的虚拟地址,其缺页处理函数将和文件系统的缺页函数相关,filemap_nopage(),通过文件系统的缺页从磁盘将相关文件块加载如内核缓冲区.
- struct vm_operations_struct {
- void (*open)(struct vm_area_struct * area);
- void (*close)(struct vm_area_struct * area);
- struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access); //缺页操作
- };
3.系统物理地址的组织
内核将物理地址按页来组织,struct page描述系统的物理页的信息,但是页的数据内容是不在该结构中的。系统有全局数据 struct page mem_map[],用于记录每个物理页。
页面大小为4kb,在源码中用体现为(PAGE_SHIFT = 12)
- /*
- * Try to keep the most commonly accessed fields in single cache lines
- * here (16 bytes or greater). This ordering should be particularly
- * beneficial on 32-bit processors.
- *
- * The first line is data used in page cache lookup, the second line
- * is used for linear searches (eg. clock algorithm scans).
- */
- typedef struct page {
- struct list_head list;
- struct address_space *mapping;
- unsigned long index;
- struct page *next_hash;
- atomic_t count;
- unsigned long flags; /* atomic flags, some possibly updated asynchronously */
- struct list_head lru;
- unsigned long age;
- wait_queue_head_t wait;
- struct page **pprev_hash;
- struct buffer_head * buffers;
- void *virtual; /* non-NULL if kmapped */
- struct zone_struct *zone;
- } mem_map_t;
struct page是用于描述一个物理页面,该结构仅仅是作为描述,也就是说该页面的4kb数据时存储于某个连续的4kb的物理空间(由MMU决定,具体见下文)。其中:
lru 页面缓冲的调度策略(最少使用优先)
题外话:
page也可以用于文件缓冲,相关参数及作用:
buffer_head 是和设备文件相关的操作,例如在文件系统中,file的一个page有4个块,这些块就存储于buffer_head链表指定的内存中。
index 在文件系统中是用于file缓冲的页号。
3.1 用户空间页面目录(映射关系)
进程的虚拟空间描述中,pgd是用于页式存储的映射使用。当内核发生进程切换时,将新进程的pgd载入CR3寄存器,CPU中的MMU单元依据CR3寄存器进行页面映射。
pgd,pmd和pte可以看做是数组,为进程的地址空间到物理空间实现映射。其中虚拟地址的高位地址决定pgd,中间段地址决定pmd,而低位地址决定pte,pte是“page table entry”。
最终定位的pte中存放的即为对应物理页面的指针。
- typedef struct { unsigned long pte; } pte_t;
- typedef struct { unsigned long pmd; } pmd_t;
- typedef struct { unsigned long pgd; } pgd_t;
- typedef struct { unsigned long pgprot; } pgprot_t; //操作标志
3.2用户空间的映射:
1. 用户空间的虚拟地址vaddr通过MMU(pgd,pmd,pte)找到对应的页表项x(即为物理地址)
2. 页表项x的高20位是物理也好,物理页号index = x >> PAGE_SHIFT, 同理,index后面补上12个0就是物理页表的首地址。
3. 通过物理页号,我们可以再内核中找到该物理页的描述的指针mem_map[index],当然这个指针是虚拟地址,page结构见上文。
3.3内核空间虚拟地址的映射:
内核空间与物理地址之间有直接的映射关系,而不需要向用户空间那样通过mmu(pgd)。系统空间映射(3G开始)到物理空间0G起始:
例如:
系统内核映像载入的虚拟地址为3G+1M的起始地址,那么对应的物理地址为1M。
紧接着分配在3G+2M开始分配了8M的虚拟地址(物理地址为2-9M)用于PDG
之后预留了16M空间用DMA于存储。
而全局的page结构的mem_page[]数组是在0xc1000000开始的。
所以内核空间虚拟地址到物理地址的转换为:
- PAGE_OFFSET = 3GB
- vitr_to_phys(kadd)
- return vadd - PAGE_OFFSET
- 内核空间的虚拟地址vaddr是通过如下方式找到它对应物理地址的page结构:
- vitr_to_page(vadd)
- index = virt_to_phys(kadd) >> PAGE_SHIFT
- return mem_map[index]
4. 相关数据结构关系图
说明:
1. 黑色+红色 箭头展示了虚拟地址空间到物理空间的映射关系
2. 蓝色箭头涉涉及到文件的映射操作mmap(),相比匿名映射,文件映射多了文件层的磁盘IO。
[置顶] Linux 虚拟地址与物理地址的映射关系分析【转】的更多相关文章
- Linux 虚拟地址与物理地址的映射关系分析【转】
转自:http://blog.csdn.net/ordeder/article/details/41630945 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...
- Linux虚拟地址和物理地址的映射
➤背景 一般情况下,Linux系统中,进程的4GB内存空间被划分成为两个部分------用户空间和内核空间,大小分别为0~3G,3~4G.用户进程通常情况下,只能访问用户空间的虚拟地址,不能访问到内核 ...
- 浅析Linux 64位系统虚拟地址和物理地址的映射及验证方法
虚拟内存 先简单介绍一下操作系统中为什么会有虚拟地址和物理地址的区别.因为Linux中有进程的概念,那么每个进程都有自己的独立的地址空间. 现在的操作系统都是64bit的,也就是说如果在用户态的进程中 ...
- [置顶] Linux Malloc分析-从用户空间到内核空间【转】
转自:http://blog.csdn.net/ordeder/article/details/41654509 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...
- Linux驱动虚拟地址和物理地址的映射
一般情况下,Linux系统中,进程的4GB内存空间被划分成为两个部分------用户空间和内核空间,大小分别为0~3G,3~4G. 用户进程通常情况下,只能访问用户空间的虚拟地址,不能访问到内核空间. ...
- [置顶] linux内核启动2-setup_arch中的内存初始化(目前分析高端内存)
上一篇微博留下了这几个函数,现在我们来分析它们 sanity_check_meminfo(); arm_memblock_init(&meminfo, mdes ...
- x86虚拟地址到物理地址的映射学习
这里只谈分页管理的机制,也是目前最重要的内存管理机制. 最初的设计想法: 结构图如下: 页的尺寸是4KB,虚拟地址的前20位用于指定一个物理页,后12位用于访问页内偏移. 页表项的结构: 各个位的含义 ...
- [置顶] linux内核启动1-启动参数(启动参数的获取和处理,分析setup_arch)
最近公司要求调试一个内核,启动时有问题,所以就花了一点时间看看内核启动. 看的过程中总结了一点东西,希望可以帮助大家调试内核. 当我开始看的时候,第一件事是从网上搜集资料,不看不知道,一看吓一跳!牛人 ...
- [置顶] linux常用命令大全
SSH 密令控制台 user/pwd 一:停止tomcat 1,cd .. 进入根目录 2,cd home/ 3,ll 4,cd bin/ 进入tomcat bin目录 5,ll 6,ps -ef | ...
随机推荐
- ELK之Elasticsearch
安装并运行Elasetisearch cd elasticsearch-<version> ./bin/elasticsearch 如果你想把 Elasticsearch 作为一个守护进程 ...
- 2018Ec-Final比赛总结
一场匆忙的旅程. NCC_9754_ Victory的最后一场比赛终究没能victory. 去的时候晕车到吐了两次,到宾馆吃完饭直接睡了,但还是两天都昏昏沉沉的头疼的厉害,第二天直接步行去了西工大体育 ...
- 購買管理(MM)
■購買管理■ [購買伝票]EKKO: ヘッダ EKPO: 明細 EKET: 納入日程行 EKPA: 取引先機能 EKKN: 勘定設定 EKBE: 後続伝票 EKBEH: 削除済み後続伝票履歴 [請求書 ...
- vue 组件轮播联动
组件轮播联动我使用的是 el-carousel 组件,具体代码如下: <el-carousel trigger="click" :interval="3000&qu ...
- 流量操控之SSH隧道与端口转发
目 录 第1章 概述... 3 1.1. 实现命令... 3 1.2. SSH隧道类型... 3 第2章 SSH隧道... ...
- 嵌入式(Embedded System)笔记 —— Cortex-M3 Introduction and Basics(上)
随着课内的学习,我想把每节课所学记录下来,以作查阅.以饲读者.由于我所上的是英文班课程,因此我将把关键术语的英文给出,甚至有些内容直接使用英文. 本次所介绍内容是关于Cortex-M3的基础内容. - ...
- JavaScript显示当前时间的操作
JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标 ...
- HTML5新增属性学习笔记
1.form属性 表单内的从属元素,可以写在表单外部.可以通过指定元素的form属性来声明元素所属表单.form的属性值为表单的id. <form id="testForm" ...
- day06_04 购物车讲解02
1.0 补充知识 a,b = [2,3] print(a) print(b) #>>>2 #>>>3 a,b = (2,3) print(a) print(b) # ...
- IntelliJ IDEA 注释模版 输入/**后 不显示配置好的模板
简单一句话就是 当你在live templetes里配置好以后,记住abbreviation:输入框里的字母 比如我的是cc ,我要想写注释怎么办? 在方法上输入 /*cc 然后按tab键就出来了