虚拟地址和物理地址

     虚拟地址和物理地址

第一层理解

1、每个进程都有自己独立的4g内存空间,每个进程的内存空间都具有类似的结构。

2、一个新进程建立的时候,将会建立自己的内存空间,此进程的数据,代码等数据从磁盘拷贝到自己的进程空间,哪些数据在哪里,都由进程控制表中的task_struck记录,task_struck中记录一条链表,记录内存空间的分配情况,哪些地址有数据,哪些地址没有数据,哪些可读,哪些可写,都可以通过这个链表进行记录。

3、每个进程已经分配的内存及空间,都与对应的磁盘空间映射。

 

 

问题:

计算机明明没有那么多内存(n个进程的话需要n*4g)内存

建立一个进程,就要把磁盘上的程序文件拷贝到进程对应的内存中,对于一个程序对应多个进程这种情况,浪费内存。

第二层理解

1、每个进程的4G内存空间只是虚拟内存空间,每次访问内存空间的某个地址,都需要把地址翻译成实际物理内存地址

2、所有进程共享同一物理内存,每个进程只需要把自己目前需要的虚拟内存映射并存储到物理内存上。

3、进程要知道哪些内存地址的数据在物理内存上,哪些不在,还有在物理内存上哪里,需要用页表记录

4、页表的每一项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)

5、当进程访问每个虚拟地址,去看页表,如果发现对应的数据不在物理内存中,则缺页异常。

6、缺页异常的处理过程,就是把进程需要的数据从磁盘上拷贝到物理内存中,如果内存已经满了,没有空地方了,那就找一个页覆盖(页面置换算法)

 

优点:

1、既然每个进程的内存空间都是一致并且固定,所以连接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际的内存地址,这是独立内存空间的好处。

2、当不同的进程使用同样的代码时,比如库文件的代码,物理内存中可以值存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存。

3、在程序员需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用内存碎片。

   另外,事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表中内存相关的链表,实际上并不立即把虚拟内存对应位置的程序数据和代码拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫存储器映射),等到运行到对应的程序,才会通过缺页异常吗,来拷贝数据。还有进程运行过程中,要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做对应设置,进程真正访问到此数据时,才引发缺页异常。

 

 

补充理解:

虚拟存储器设计三个概念:虚拟存储空间,磁盘空间,内存空间

     可以认为虚拟空间都被映射到了磁盘空间,(事实上也是按需映射到磁盘空间上,通过mmap),并且由页表记录位置,当访问某个地址的时候,通过页表中的有效位,可以得知此数据是否在内存中,如果不是,则通过缺页异常,将磁盘对应的数据拷贝到内存中,如果没有空闲的内存,则选择牺牲页面,替换其他页面。

 

物理内存:

       在内核态申请内存比在用户态申请内存更直接,它没有采取用户态的那种延迟分配内存技术。内核认为一旦有内核函数申请,那么就必须立刻满足该申请内存的请求,并且这个请求一定正确合理。相反,对于用户态申请内存的请求,内核总是尽量延后分配物理内存,用户进程总是先获得一个虚拟内存的使用权,最终通过缺页异常获得一块真正的物理内存。

1、物理内存的内核映射

    IA32架构中内核虚拟地址空间只有1G大小(从3G到4G),因此可以直接将1G大小的物理内存(即常规内存)映射到内核地址空间,但超出1G大小的物理内存(即高端内存)就不能映射到内核空间了。为此,内核采取了下面的方法使得内存可以使用所有的物理内存。

    1、高端内存不能全部映射到内核空间,也就是说这些物理内存没有对应的线性地址。不过,内核为每个物理页框都分配了对应的页框描述符,所有的页框描述符都保存在mem_map数组中,因此每个页框描述符的线性地址都是固定存在的。内核此时可以使用alloc_pages()和alloc_page()来分配内存,因为这些函数返回框描述符的线性地址。

    2、内核地址空间的后128MB专门用于映射高端内存,否则,没有线性地址的高端内存不能访问不能被内核所访问。这些高端内存的内核映射显然是暂时映射,否则也只能映射128MB的高端内存。当内核 需要访问高端内存时就临时在这个区域进行地址映射,使用完毕之后再用来进行其他高端内存的映射。

    由于要进行高端内存的内核映射,因此直接能够映射物理内存得到大小只有896MB,该值保存在high_memory中。

 

 

内核采用了三种机制将高端内存映射到内核空间:永久内核映射,固定映射和vmlloc机制。

物理内存机制

      基于物理内存在内核空间中的映射原理,物理内存的管理方式也是有所不同。内核中物理内存的管理机制主要有伙伴算法,slab高速缓存和vmalloc机制。其中伙伴算法和slab高速缓存都是在物理内存映射分配物理内存,而vmalloc机制则在高端内存映射区分配物理内存。

伙伴算法

    伙伴算法负责大连续物理内存的分配和释放,以页框为基本单位。该机制可以避免外部的碎片。

per-CPU页框告诉缓存

内核经常请求和释放单个页框,该缓存包含预先分配的页框,用户满足本地cpu发出的单一页框请求。

slab缓存

     slab缓存负责小块内存的分配,并且它可以作为告诉的缓存,主要针对内核中经常分配并释放的对象。

vmalloc机制

   vmalloc机制使得内核通过连续的线性地址来访问非连续的物理页框,这样可以最大限度的使用高端物理内存。

物理内存的分配

  内核发出内存申请的请求,根据内核函数调用接口将启用不同的内存分配器。

分区页框分配器

     分区页框分配器 (zoned page frame allocator),处理对连续页框的内存分配请求。分区页框管理器分为两大部分:前端的管理区分配器和伙伴系统,如下图

    

 

 

管理区分配器负责搜索一个能满足请求页框块大小的管理区。在每个管理区中,具体的页框分配工作由伙伴系统负责。为了达到更好的系统性能,单个页框的申请工作直接通过per-CPU页框高速缓存完成。

该分配器通过几个函数和宏来请求页框,它们之间的封装关系如下图所示。

 

 

  这些函数和宏将核心的分配函数__alloc_pages_nodemask()封装,形成满足不同分配需求的分配函数。其中,alloc_pages()系列函数返回物理内存首页框描述符,__get_free_pages()系列函数返回内存的线性地址。

slab分配器

    slab 分配器最初是为了解决物理内存的内部碎片而提出的,它将内核中常用的数据结构看做对象。slab分配器为每一种对象建立高速缓存。内核对该对象的分配和释放均是在这块高速缓存中操作。一种对象的slab分配器结构图如下:

 

 

   可以看到每种对象的高速缓存是由若干个slab组成,每个slab是由若干个页框组成的。虽然slab分配器可以分配比单个页框更小的内存块,但它所需的所有内存都是通过伙伴算法分配的。

   slab高速缓存分专用缓存和通用缓存。专用缓存是对特定的对象,比如为内存描述符创建高速缓存。通用缓存则是针对一般情况,适合分配任意大小的物理内存,其接口即为kmalloc()。

非连续内存区内存的分配

        内核通过vmalloc()来申请非连续的物理内存,若申请成功,该函数返回连续内存区的起始地址,否则,返回NULL。vmalloc()和kmalloc()申请的内存有所不同,kmalloc()所申请内存的线性地址与物理地址都是连续的,而vmalloc()所申请的内存线性地址连续而物理地址则是离散的,两个地址之间通过内核页表进行映射。

vmalloc()的工作方式理解起来很简单:

 1、寻找一个新的连续线性地址空间;

 2、依次分配一组非连续的页框;

 3、为线性地址空间和非连续页框建立映射关系,即修改内核页表;

   vmalloc()的内存分配原理与用户态的内存分配相似,都是通过连续的虚拟内存来访问离散的物理内存,并且虚拟地址和物理地址之间是通过页表进行连接的,通过这种方式可以有效的使用物理内存。但是应该注意的是,vmalloc()申请物理内存时是立即分配的,因为内核认为这种内存分配请求是正当而且紧急的;相反,用户态有内存请求时,内核总是尽可能的延后,毕竟用户态跟内核态不在一个特权级。

 

参考:https://www.cnblogs.com/dyllove98/archive/2013/06/12/3132940.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


每个HTTP请求和响应都会带有相应的头部信息。默认情况下,在发送XHR请求的同时,还会发送下列头部信息: Accept:浏览器能够处理的内容类型 Accept-Charset:浏览器能够显示的字符集
"Markdown自动生成目录" "使用npm语法生成" "1、安装npm" "2、安装doctoc插件" "
当我们从客户端向服务器发送请求时 服务器向我们返回状态码 状态码就是告诉我们服务器响应的状态 通过它,我们就可以知道当前请求是成功了还是出现了什么问题 状态码是
原理 介绍 哈希表(Hash table,也叫散列表), 是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映
一 共享秘钥 1.1 概念 共享秘钥和我们生活中同一把锁的钥匙概念类似,对同一把锁来说,加锁时使用什么钥匙,解锁也必须使用同样的钥匙。 1.2 共享秘钥在HTTP传输中的缺点 以共享密钥方式加密时必须
正向代理的概念 正向代理,也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器这个代理服务器呢,他能访问那个我不能访问的网站于是我先连上代
如果你是网站的开发者或维护者,就不得不重视盗链的问题了。如果你刚刚开发完一个没有防盗链的带有文件下载功能的网站,挂上internet,然后上传几个时下非常热门的软件或电影并在网站内公布下载地址,让MS
select,poll,epoll区别总结 select,poll,epoll都是I/O多路复用。I/O多路复用就是通过一种机制,可以监测多个描述符,一旦某个描述就绪(一般是读或者写),能够通知程序进
PS: https就是http和TCP之间有一层SSL层,这一层的实际作用是防止钓鱼和加密。防止钓鱼通过网站的证书,网站必须有CA证书,证书类似于一个解密的签名。另外是加密,加密需要一个密钥交换算法,
一、什么是http协议 HTTP是一个应用层协议,无状态的,端口号为80。主要的版本有1.0/1.1/2.0. HTTP/1.* 一次请求-响应,建立一个连接,用完关闭; HTTP/1.1 串行化单线
host文件的工作原理及应用 Hosts文件是一个用于存储计算机网络中节点信息的文件,它可以将主机名映射到相应的IP地址,实现DNS的功能,它可以由计算机的用户进行控制。 一、Hosts文件基本介绍
HTTP 2.0是在SPDY(An experimental protocol for a faster web, The Chromium Projects)基础上形成的下一代互联网通信协议。HTT
虚拟地址和物理地址 第一层理解 1、每个进程都有自己独立的4g内存空间,每个进程的内存空间都具有类似的结构。 2、一个新进程建立的时候,将会建立自己的内存空间,此进程的数据,代码等数据从磁盘拷贝到自己
0x00 前言 发现自己学习python已经有半个月了,也开发了自己的一些渗透的小脚本,但觉得还是不够,我个人觉得工具和脚本还有框架是个本质上的区别。脚本的话,不会考虑到其他的一些因素,例如报错和交互
0x00 前言 由于昨天520,今天又是521,我被朋友圈和qq空间给刷屏了,都在秀对象。一气之下决定把我上次写的nc拿出来使用类进行重构,多实例化几个对象,这下子我也有对象了。 0x01 一些小插曲
upload labs通关 0x00 前言 这段时间一直在忙,没时间来更新文章,这里就写篇upload labs的通关手册吧,现在包括网上也有很多upload通关手册,但是在这里还是想自己去写一篇,来
0x00 前言 介于这段时间比较忙,所以博客的更新也比较慢。本来想前几天就发这个mssql数据库的,但是因为mssql的结构比较复杂,利用方式也比较多,所以又去深入研究了一下mssql的数据库结构和各
0x00 了解数据库 数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。 数据库是以一定方式储存在一起、能与多个用户共享、
0x00 前言 现在access的站,比较少,有的话也是小型网站在用,因为access的性能比较差,多人访问都能卡死,所以很多网站都很少会采用access的数据库搭建。但是该学的我们还是得学。 0x0
记一次某企业实战 0x00 前言 近段时间来也没怎么更新过博客,在这里就来水篇文章吧。 前段时间一直在做项目,也来分享并且记录一下自己的一些成果,和一些小思路。 0x01 信息收集 渗透的第一步肯定是