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

简介虚拟地址空间:保障进程间独立性的机制

我们知道,进程之间是相互独立的,在操作系统级别中,一个进程所执行的程序无法直接访问另一个进程所执行的内存区域(即实现进程间通信比较困难);一个进程运行的失败也不会影响其它进程的运行。这使我们的操作系统功能更加稳定。

如何保障进程之间这样的独立性?操作系统采用了“虚拟地址空间”的方式。


一、每个进程都直接访问物理内存的地址会怎样?

物理内存是一块内存条:

内存条上有许多内存颗粒(黑色块状的东西就是内存颗粒),它是内存条最核心的部件,是内存的储存介质。里面有许多的存储单元,类似于“小房间”。每个“小房间”都有编号,即“内存地址”。这时我们假设现在有两个进程,它们分别使用一定的内存资源:

此时,就出现了一个严重的问题:由于进程1和进程2使用的是同一块物理内存,且彼此之间没有约束,那么当进程1代码出现bug(如数组下标越界、野指针等问题时),就可能把进程2内存里的内容也搞坏了。进程1的bug,就很有可能引起进程2也bug。试想你浏览器用着用着,QQ崩了;QQ用着用着,桌面崩了……两个进程之间能直接相互影响,这极大地影响了操作系统整体的稳定性。

因而,虚拟地址空间就是来解决这个麻烦问题的。


二、“虚拟内存空间”是如何解决上述问题的?

现在有进程1和进程2,我们给两个进程分别分配一块虚拟的内存空间。然后,操作系统中提供了一个专门的数据结构:页表,通过页表,实现虚拟地址与实际的物理地址之间的映射。如进程1的虚拟地址空间是 0x00 - 0xff,页表就会将这段虚拟地址空间映射到物理内存上的真实地址 0xaa00 - 0xaaff 。同样的,进程2被分配的虚拟地址也会在页表的映射下对应到真实的物理内存上。

此时,站在这两个进程的角度看,它们的代码中操作的内存地址就是 0x00 - 0xff 这一段。这里访问的内存虽然会被操作系统自动映射到真实的物理内存上,但是进程自身是感知不到实际的物理地址是啥的。如果这时,进程1代码bug (比如数组下标越界,野指针等),就没事了。

因为任何一个内存操作都需要通过页表来“翻译”一下地址。如果出现野指针0x2ff,拿着这个地址去页表上找,发现页表上就没有这个地址!那页表便无法翻译,同时也就无法真正修改物理内存。这样一来,也就不会对别的进程的内存数据造成干扰了。

页表最大的作用就是校验,方便知道当前的虚拟地址是否有效。这样,一个进程崩了,不会对别的进程产生影响;进程之间无法直接干预,操作系统的稳定性也就上来了。


三、简述进程间通信的实现

有的情况下,我们需要进程之间能进行交互,相互配合。

但正如上面提到的,如果每个进程可以直接访问物理内存也即进程间没有隔离性,也就不需要进程间通信。进程1直接把算好的结果写到进程2的内存里就行。

但进程之间是有隔离性的。所谓进程间通信,就是在进程间隔离性的前提下,找一个公共的区域,让两个进程借助这个区域来完成数据交换。

这就好像疫情期间封小区,外面的人进不来,小区里的人也出不去(隔离性)。这时,如果小区里的人要买菜,就让小区外头送菜的人把菜放在保安亭,然后自己也去保安亭拿菜。那此时,这个保安亭就是公共空间,它帮助我们小区里被隔离的人和小区外的人实现了“通信”。

这可以理解为,所谓“公共空间”,就是在进程隔离性的情况下,作出了一些小小的妥协。

操作系统提供的实现进程间通信的方式有很多种,如管道、消息队列、共享内存、信号等等。由于编程语言的特点,C++对这部分的研究会比Java更加细致。因为在Java圈子中,并不是很鼓励多进程编程。Java更多地使用文件和socket这两种方式来完成进程间的通信。

在多线程与多进程编程都能满足并发编程的需求的前提下,Java也更鼓励多线程编程。

相关文章:

  • 【剑指offer】旋转数组的最小数字
  • 手写一个简单的RPC框架
  • 如何创建和编写项目管理计划?
  • 算法设计与分析 实验五 贪心算法
  • 正式环境关闭swagger
  • 动态内存的开辟
  • 【分布式版本控制系统Git】| IDEA 集成 Git 、IDEA 集成 GitHub
  • C语言指针链表
  • 全网最完整,接口测试总结彻底打通接口自动化大门,看这篇就够了......
  • 【JVM虚拟机面试宝典】JVM的内存结构是怎么样的?在JVM中会发生内存溢出的区域有那些?— day06
  • C++ string类
  • 细数那些惊艳一时的 CSS 属性
  • 【C语言】你真的了解结构体吗
  • 可做题2(矩阵快速幂,乘法逆元,exgcd)
  • Mysql用户权限分配详解
  • #Java异常处理
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 10个最佳ES6特性 ES7与ES8的特性
  • AngularJS指令开发(1)——参数详解
  • const let
  • css选择器
  • Docker下部署自己的LNMP工作环境
  • JavaScript的使用你知道几种?(上)
  • JSDuck 与 AngularJS 融合技巧
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • maven工程打包jar以及java jar命令的classpath使用
  • 从零开始学习部署
  • 聊聊sentinel的DegradeSlot
  • 前端性能优化--懒加载和预加载
  • 协程
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 移动端唤起键盘时取消position:fixed定位
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • $forceUpdate()函数
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (超详细)语音信号处理之特征提取
  • (转)memcache、redis缓存
  • (转)shell调试方法
  • .libPaths()设置包加载目录
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .net 提取注释生成API文档 帮助文档
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • @GetMapping和@RequestMapping的区别
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • []sim300 GPRS数据收发程序
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [Android] Implementation vs API dependency
  • [Android] Android ActivityManager