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 虚拟空间、用户空间

  1. struct mm_struct {
  2. struct vm_area_struct * mmap;   /* list of VMAs */
  3. ...
  4. pgd_t * pgd;                //用于地址映射
  5. atomic_t mm_users;          /* How many users with user space? */
  6. atomic_t mm_count;          /* How many references to "struct mm_struct" (users count as 1) */
  7. int map_count;              /* number of VMAs */
  8. ...
  9. //描述用户空间的段分布:数据段,代码段,堆栈段
  10. unsigned long start_code, end_code, start_data, end_data;
  11. unsigned long start_brk, brk, start_stack;
  12. unsigned long arg_start, arg_end, env_start, env_end;
  13. unsigned long rss, total_vm, locked_vm;
  14. ...
  15. };

以上结构描述了进程的用户空间的结构,其中
pgd_t    是该进程用户空间地址映射到物理地址时使用
vm_area_struct 是进程用户空间已映射到物理空间的虚拟地址区间,mmap是该空间区块组成的链表。

虚拟空间的空洞:虚拟空间还未被映射的区块(即没有被使用),那么就没有vm_area_struct结构

2.2 内存区间

  1. /*
  2. * This struct defines a memory VMM memory area. There is one of these
  3. * per VM-area/task.  A VM area is any part of the process virtual memory
  4. * space that has a special rule for the page-fault handlers (ie a shared
  5. * library, the executable area etc).
  6. */
  7. struct vm_area_struct {
  8. struct mm_struct * vm_mm;   /* VM area parameters */
  9. unsigned long vm_start;     //虚拟空间起始地址
  10. unsigned long vm_end;       //终止地址
  11. /* linked list of VM areas per task, sorted by address */
  12. struct vm_area_struct *vm_next;
  13. //该区间的权限及标志
  14. pgprot_t vm_page_prot;
  15. unsigned long vm_flags;
  16. //一些vm_area 的链接
  17. ...
  18. struct vm_operations_struct * vm_ops;
  19. unsigned long vm_pgoff;     /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
  20. struct file * vm_file;      //用于将磁盘文件映射至用户空间
  21. ...
  22. };

虚拟空间区间的描述中:
vm_start/vm_end    为该区块的起始和结束地址
vm_file    是在文件映射中使用到,即常用的mmap(fd,...)函数,简单说即将虚拟空间映射至文件在内核的缓冲区,那么这时候访问该虚拟空间将有别于pgd的映射。
vm_operations_struct 为本虚拟区间的操作,其中的nopage函数指针是处理内存缺页而使用的。对于通用的内存映射,该缺页处理函数为do_no_page()将虚拟地址映射到物理地址(匿名映射):分配物理页& 设置pgd & pte。
而对于mmap操作相关的虚拟地址,其缺页处理函数将和文件系统的缺页函数相关,filemap_nopage(),通过文件系统的缺页从磁盘将相关文件块加载如内核缓冲区.

  1. struct vm_operations_struct {
  2. void (*open)(struct vm_area_struct * area);
  3. void (*close)(struct vm_area_struct * area);
  4. struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);     //缺页操作
  5. };

3.系统物理地址的组织

内核将物理地址按页来组织,struct page描述系统的物理页的信息,但是页的数据内容是不在该结构中的。系统有全局数据 struct page mem_map[],用于记录每个物理页。
页面大小为4kb,在源码中用体现为(PAGE_SHIFT = 12)

  1. /*
  2. * Try to keep the most commonly accessed fields in single cache lines
  3. * here (16 bytes or greater).  This ordering should be particularly
  4. * beneficial on 32-bit processors.
  5. *
  6. * The first line is data used in page cache lookup, the second line
  7. * is used for linear searches (eg. clock algorithm scans).
  8. */
  9. typedef struct page {
  10. struct list_head list;
  11. struct address_space *mapping;
  12. unsigned long index;
  13. struct page *next_hash;
  14. atomic_t count;
  15. unsigned long flags;    /* atomic flags, some possibly updated asynchronously */
  16. struct list_head lru;
  17. unsigned long age;
  18. wait_queue_head_t wait;
  19. struct page **pprev_hash;
  20. struct buffer_head * buffers;
  21. void *virtual; /* non-NULL if kmapped */
  22. struct zone_struct *zone;
  23. } 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中存放的即为对应物理页面的指针。

  1. typedef struct { unsigned long pte; } pte_t;
  2. typedef struct { unsigned long pmd; } pmd_t;
  3. typedef struct { unsigned long pgd; } pgd_t;
  4. 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开始的。
所以内核空间虚拟地址到物理地址的转换为:

  1. PAGE_OFFSET = 3GB
  2. vitr_to_phys(kadd)
  3. return vadd - PAGE_OFFSET
  4. 内核空间的虚拟地址vaddr是通过如下方式找到它对应物理地址的page结构:
  5. vitr_to_page(vadd)
  6. index = virt_to_phys(kadd) >> PAGE_SHIFT
  7. return mem_map[index]

4. 相关数据结构关系图

说明:

1. 黑色+红色 箭头展示了虚拟地址空间到物理空间的映射关系

2. 蓝色箭头涉涉及到文件的映射操作mmap(),相比匿名映射,文件映射多了文件层的磁盘IO。

Linux 虚拟地址与物理地址的映射关系分析【转】的更多相关文章

  1. [置顶] Linux 虚拟地址与物理地址的映射关系分析【转】

    转自:http://blog.csdn.net/ordeder/article/details/41630945 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...

  2. Linux虚拟地址和物理地址的映射

    ➤背景 一般情况下,Linux系统中,进程的4GB内存空间被划分成为两个部分------用户空间和内核空间,大小分别为0~3G,3~4G.用户进程通常情况下,只能访问用户空间的虚拟地址,不能访问到内核 ...

  3. 浅析Linux 64位系统虚拟地址和物理地址的映射及验证方法

    虚拟内存 先简单介绍一下操作系统中为什么会有虚拟地址和物理地址的区别.因为Linux中有进程的概念,那么每个进程都有自己的独立的地址空间. 现在的操作系统都是64bit的,也就是说如果在用户态的进程中 ...

  4. Linux驱动虚拟地址和物理地址的映射

    一般情况下,Linux系统中,进程的4GB内存空间被划分成为两个部分------用户空间和内核空间,大小分别为0~3G,3~4G. 用户进程通常情况下,只能访问用户空间的虚拟地址,不能访问到内核空间. ...

  5. x86虚拟地址到物理地址的映射学习

    这里只谈分页管理的机制,也是目前最重要的内存管理机制. 最初的设计想法: 结构图如下: 页的尺寸是4KB,虚拟地址的前20位用于指定一个物理页,后12位用于访问页内偏移. 页表项的结构: 各个位的含义 ...

  6. linux kernel内存映射实例分析

    作者:JHJ(jianghuijun211@gmail.com)日期:2012/08/24 欢迎转载,请注明出处 引子 现在android智能手机市场异常火热,硬件升级非常迅猛,arm cortex ...

  7. Linux内存管理 (12)反向映射RMAP

    专题:Linux内存管理专题 关键词:RMAP.VMA.AV.AVC. 所谓反向映射是相对于从虚拟地址到物理地址的映射,反向映射是从物理页面到虚拟地址空间VMA的反向映射. RMAP能否实现的基础是通 ...

  8. Page (computer memory) Memory segmentation Page table 虚拟地址到物理地址的转换

    A page, memory page, or virtual page is a fixed-length contiguous block of virtual memory, described ...

  9. 转: 关于Linux与JVM的内存关系分析

    转自: http://tech.meituan.com/linux-jvm-memory.html Linux与JVM的内存关系分析 葛吒2014-08-29 10:00 引言 在一些物理内存为8g的 ...

随机推荐

  1. 35. Search Insert Position@python

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  2. 【点分治】luoguP2664 树上游戏

    应该是一道中等难度的点分?麻烦在一些细节. 题目描述 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 现在他想让你求出所有的sum[i] ...

  3. centos6启动故障排除

    centos6中boot文件被全部删除的故障排除 /boot文件里关于启动的核心文件有三个,/vmlinuz-2.6.32-696.e16.x86_64,initramfs-2.6.32-696.el ...

  4. 【mysql】The server quit without updating PID file

      groupadd mysql useradd -r -g mysql mysql cd /usr/local/mysql chown -R mysql:mysql . scripts/mysql_ ...

  5. Anaconda安装和环境的搭建

    Anaconda安装 在官网上下载最新的Anaconda https://www.anaconda.com/distribution/ 我使用的是2018.12,Python 3.7这个版本的. 安装 ...

  6. Flask初学者:Jinja2模板

    Python的Jinja2模板,其实就是在HTML文档中使用控制语句和表达语句替换HTML文档中的变量来控制HTML的显示格式,Python的Jinja2模板可以更加灵活和方便的控制HTML的显示,而 ...

  7. LightOj:1422-Halloween Costumes

    传送门:http://www.lightoj.com/volume_showproblem.php?problem=1422 Halloween Costumes problem descriptio ...

  8. Linux学习-Tarball 的管理与建议

    使用原始码管理软件所需要的基础软件 从原始码的说明我们晓得要制作一个 binary program 需要很多咚咚的呢!这包括底下这些基础的软件: gcc 或 cc 等 C 语言编译程序 (compil ...

  9. LAMP动态网站安装脚本

    #!/bin/bash #auto make install LAMP #by authors zhangjianghua #httpd define path variable H_FILES=ht ...

  10. Python虚拟机之异常控制流(四)

    Python虚拟机中的异常控制流 先前,我们分别介绍了Python虚拟机之if控制流(一).Python虚拟机之for循环控制流(二)和Python虚拟机之while循环控制结构(三).这一章,我们来 ...