当前位置: 首页 > news >正文

Linux虚拟内存简介

Linux,像多数现代内核一样,采用了虚拟内存管理技术。该技术利用了大多数程序的一个典型特征,即访问局部性(locality of reference),以求高效使用CPU和RAM(物理内存)资源。大多数程序都展现了两种类型的局部性。

  • 空间局部性(Spatial locality):是指程序倾向于访问在最近访问过的内存地址附近的内存(由于指令是顺序执行的,且有时会按顺序处理数据结构)。
  • 时间局部性(Temporal locality):是指程序倾向于在不久的将来再次访问最近刚访问过的内存地址(由于循环)。

正是由于访问局部性特征,使得程序即便仅有部分地址空间存在于RAM中,依然可能得以执行。

虚拟内存的规划之一是将每个程序使用的内存切割成小型的、固定大小的“页”(page)单元。相应地,将RAM划分成一系列与虚存页尺寸相同的页帧。任一时刻,每个程序仅有部分页需要驻留在物理内存页帧中。这些页构成了所谓驻留集(resident set)。程序未使用的页拷贝保存在交换区(swap area)内—这是磁盘空间中的保留区域,作为计算机RAM的补充—仅在需要时才会载入物理内存。若进程欲访问的页面目前并未驻留在物理内存中,将会发生页面错误(page fault),内核即刻挂起进程的执行,同时从磁盘中将该页面载入内存。

为支持这一组织方式,内核需要为每个进程维护一张页表(page table)。该页表描述了每页在进程虚拟地址空间(virtual address space)中的位置(可为进程所用的所有虚拟内存页面的集合)。页表中的每个条目要么指出一个虚拟页面在RAM中的所在位置,要么表明其当前驻留在磁盘上。

在这里插入图片描述

​ 虚拟内存概览

在进程虚拟地址空间中,并非所有的地址范围都需要页表条目。通常情况下,由于可能存在大段的虚拟地址空间并未投入使用,故而也无必要为其维护相应的页表条目。若进程试图访问的地址并无页表条目与之对应,那么进程将收到一个SIGSEGV信号。

由于内核能够为进程分配和释放页(和页表条目),所以进程的有效虚拟地址范围在其生命周期中可以发生变化。这可能会发生于如下场景。

  • 由于栈向下增长超出之前曾达到的位置。
  • 当在堆中分配或释放内存时,通过调用brk()、sbrk()或malloc函数族来提升program break的位置。
  • 当调用shmat()连接System V共享内存区时,或者当调用shmdt()脱离共享内存区时。
  • 当调用mmap()创建内存映射时,或者当调用munmap()解除内存映射时。

虚拟内存的实现需要硬件中分页内存管理单元(PMMU)的支持。PMMU把要访问的每个虚拟内存地址转换成相应的物理内存地址,当特定虚拟内存地址所对应的页没有驻留于RAM中时,将以页面错误通知内核。

虚拟内存管理使进程的虚拟地址空间与RAM物理地址空间隔离开来,这带来许多优点。

  • 进程与进程、进程与内核相互隔离,所以一个进程不能读取或修改另一进程或内核的内存。这是因为每个进程的页表条目指向RAM(或交换区)中截然不同的物理页面集合。

  • 适当情况下,两个或者更多进程能够共享内存。这是由于内核可以使不同进程的页表条目指向相同的RAM页。内存共享常发生于如下两种场景。

    – 执行同一程序的多个进程,可共享一份(只读的)程序代码副本。当多个程序执行相同的程序文件(或加载相同的共享库)时,会隐式地实现这一类型的共享

    – 进程可以使用shmget()和mmap()系统调用显式地请求与其他进程共享内存区。这么做是出于进程间通信的目的。

  • 便于实现内存保护机制;也就是说,可以对页表条目进行标记,以表示相关页面内容是可读、可写、可执行亦或是这些保护措施的组合。多个进程共享RAM页面时,允许每个进程对内存采取不同的保护措施。例如,一个进程可能以只读方式访问某页面,而另一进程则以读写方式访问同一页面。

  • 程序员和编译器、链接器之类的工具无需关注程序在RAM中的物理布局。

  • 因为需要驻留在内存中的仅是程序的一部分,所以程序的加载和运行都很快。而且,一个进程所占用的内存(即虚拟内存大小)能够超出RAM容量。

和运行都很快。而且,一个进程所占用的内存(即虚拟内存大小)能够超出RAM容量。

虚拟内存管理的最后一个优点是:由于每个进程使用的RAM减少了,RAM中同时可以容纳的进程数量就增多了。这增大了如下事件的概率:在任一时刻,CPU都可执行至少一个进程,因而往往也会提高CPU的利用率。

相关文章:

  • Vitalik Buterin香港主旨演讲:协议过去10年迅速发展,但存在效率、安全两大问题
  • 科技云报道:从“奇点”到“大爆炸”,生成式AI开启“十年周期”
  • 【spring】@Scope注解学习
  • 神经网络解决回归问题(更新ing)
  • 属于我们Go语言的toString!
  • UVA230 Borrowers 图书管理系统 解题报告
  • 谈谈Python中的单元测试和集成测试
  • Docker内更新Jenkins详细讲解
  • 如何使用Arduino IDE对STM32F103C8T6进行编程
  • 比较好玩的车子 高尔夫6
  • TCP-IP详解卷一:协议——阅读总结
  • UML学习
  • ORAN C平面 Section Extension 22
  • Flutter之TabBar篇
  • hive管理之ctl方式
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • Java 内存分配及垃圾回收机制初探
  • Javascript基础之Array数组API
  • java中具有继承关系的类及其对象初始化顺序
  • Js基础——数据类型之Null和Undefined
  • Laravel Telescope:优雅的应用调试工具
  • Linux各目录及每个目录的详细介绍
  • python大佬养成计划----difflib模块
  • rabbitmq延迟消息示例
  • spring cloud gateway 源码解析(4)跨域问题处理
  • swift基础之_对象 实例方法 对象方法。
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 当SetTimeout遇到了字符串
  • - 概述 - 《设计模式(极简c++版)》
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 删除表内多余的重复数据
  • 思维导图—你不知道的JavaScript中卷
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #Linux(帮助手册)
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • $.each()与$(selector).each()
  • ( 10 )MySQL中的外键
  • (day6) 319. 灯泡开关
  • (TOJ2804)Even? Odd?
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (六)软件测试分工
  • (转)linux下的时间函数使用
  • ***利用Ms05002溢出找“肉鸡
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .net 使用ajax控件后如何调用前端脚本
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • [4.9福建四校联考]
  • [ActionScript][AS3]小小笔记
  • [C++] 统计程序耗时
  • [Foreman]解决Unable to find internal system admin account
  • [HackMyVM]靶场Boxing