上一节我们提到过父子进程的一个概念:父子进程代码共享,数据各自开辟空间。

因为子进程从父进程的PCB中拷贝了数据,所以它的代码、数据以及运行的位置,都与父进程一模一样。但是为什么这个代码是无法修改的?为什么又需要再各自开辟空间呢?Linux是如何实现权限控制以及空间映射的呢?

我们用这段代码进行试验

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>int val = 0;int main()
{pid_t id = fork();if(id == 0){val = 100;//子进程printf("子进程pid:[%d]  val:[%d] val地址:[%p]\n", getpid(), val, &val);}else if(id > 0){//父进程sleep(3);printf("父进程pid:[%d]  val:[%d] val地址:[%p]\n", getpid(), val, &val);}return 0;}

我们利用一个全局变量val,看看修改子进程中的变量val,父进程会不会发生变化,他们的地址又是否相同。

因为子进程运行的位置和父进程一样,所以先让父进程睡眠一会,让子进程先修改

奇怪的事情发生了,明明子进程已经修改了val,但是父进程的却没变,同时明明父子进程中全局变量val的大小都不一样,发生了变化,但是他们的地址确还是一样的,这就有些不符合逻辑了,因为一个地址中不可能有两个同名的变量。

这里就让我们确定了一件事情,我们在代码中所看到的地址,并不是真正的地址。

这就引入了程序地址空间的概念。


进程地址空间

程序是不占用内存的,它只是一个没有生命的实体, 只有运行起来的程序(进程)才会被加载到内存中,这才会占用内存。

地址:地址就是对内存单元的编号,通过这个编号来访问数据。

从上面的例子我们发现,代码中看到地址并不是真正的内存地址,而是虚拟内存地址

为什么要创建这样一个虚拟的内存地址呢?

操作系统为了不让进程直接访问物理内存,通过mm_struct结构体来为进程描述了一个虚拟的,连续的,完整的地址空间(只有编号,无法存储),也就是我们所说的虚拟地址空间

为什么不让进程直接访问物理内存呢?


假设我们内存中有6m的空间,其中已经存入了3m,这时我们想再存入一个3m,但是问题来了,因为物理空间还剩下的3m是不连续,所以这时会再找一个连续的空间来存储这个3m。这样就造成了内存的大量浪费

还有这样一种情况。
当几个进程同时访问物理内存时,各进程的操作可能会产生冲突,可能会产生无法预料的后果。缺乏访问控制的内存是非常不安全的。


页表

操作系统再引入虚拟地址空间的时候还引入了一种东西,叫做页表

通过页表来映射虚拟地址和物理地址的关系。

  • 通过在虚拟地址来使数据进行连续的存储,然后再通过页表映射到物理内存上,来实现离散式的存储,提高了内存的利用率。

  • 同时页表可以针对某个地址设置访问权限,让某个地址设置为只读,通过这种方法来实现内存的访问控制。

  • 为了能够使进程具有独立性,彼此之间不会相互干预,每一个进程都会有它自己的页表和虚拟地址空间。


回到最开始的问题。

为什么父子进程的代码相同,且无法修改?
:因为通过页表将代码段的权限设置为只读,所以无法修改。

为什么父子进程数据各自开辟空间?
:其实父子进程一开始物理地址和虚拟地址都是相同的,但是当任意一个进程中数据发生变化的时候,这个时候操作系统会找到另外一块物理空间,将数据全部拷贝过去给发生修改的进程使用,并且修改原来的物理空间的权限,使原来的物理空间给另一个进程使用。

Linux 进程(二) 进程地址空间相关推荐

  1. linux 进程(二) --- 进程的创建及相关api

    一.进程的创建fork()函数 由fork创建的新进程被称为子进程(child process).该函数被调用一次,但返回两次.两次返回的区别是子进程的返回值是0,而父进程的返回值则是 新子进程的进程 ...

  2. 【Linux 内核】进程管理 ( 进程与操作系统 | 进程与程序 | 进程与线程 | 虚拟地址空间 )

    文章目录 一.进程与操作系统 二.进程与程序 三.进程与线程 四.虚拟地址空间 一.进程与操作系统 操作系统与硬件的关系 : 操作系统 使用 硬件 提供的资源 , 如 CPU , 内存 , 磁盘 , ...

  3. Linux下的进程概论与编程二(进程控制)

    一.进程标识符 1.每个进程都有非负的整形表示唯一的进程ID. 几个典型进程的ID及其功能: 2.除了进程ID,每个进程还有一些其他的标识符. 下列函数返回这些标识符: #include <sy ...

  4. 【Linux】进程概念 —— 虚拟内存地址空间

    目录 一.进程地址空间 1.进程地址空间分布图 2.验证上述进程地址空间 3.Linux vs Windows 二.了解虚拟内存地址空间 0.通过代码引出虚拟内存地址空间概念 1.什么是虚拟内存地址空 ...

  5. 操作系统实验一 Linux基本操作|实验二 进程管理

    由于当时没存代码,只有实验文档代码截图,文末也可直接获取实验文档. 操作系统实验 目录 实验一 Linux基本操作 实验二进程管理 实验一 Linux基本操作 1实验目的 1.熟悉在Linux操作系统 ...

  6. Linux虚拟内存和进程虚拟地址空间简述

    后台开发经常会问此类问题,虽说难度不大,但是知道和不知道还是有区别的.以下的内容总结自<深入理解Linux内核>第一章,仅仅是简述,没有深入研究,毕竟内存管理这一块内容超级多,感兴趣的同学 ...

  7. linux exec 二程序,二十五、Linux 进程与信号---exec函数

    25.1 介绍 在用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序 当进程调用一种 exec 函数时,该进程完全由新程序代换,替换原有进程的正文,而新程序则从其 m ...

  8. linux 驱动线程与进程,Linux内核学习之二-进程与线程

    一.操作系统的功能 根据维基百科的解释,一个操作系统大概包括以下几个功能: 进程管理(Processing management) 安全机制(Security) 内存管理(Memory managem ...

  9. 【Linux从无到有】进程的地址空间

    地址空间想必大家听的耳朵都起茧子了,栈区.堆区.静态区--其实这还有很的秘密,或许他会颠覆你的认知,那么就一起来探索吧 文章目录 进程地址空间 什么是虚拟地址空间 ? 浅谈页表 以现在的视角在看程序 ...

最新文章

  1. html 怎么设置cooki,怎么设置浏览器接受cookie
  2. PCL综述—三维图像处理
  3. kafka分区停留在UnderReplicated状态
  4. yolov5-detect.py解析与重写
  5. Flume+Kafka+Spark Streaming+MySQL实时日志分析
  6. PHP系统学习3 正则
  7. 解压rootfs.img根文件系统
  8. 《专家系统破解篇 六、IL代码破解--配套乱说》之 FeatherskyExpertSystem
  9. 消费品企业,会员营销四大痛点
  10. 黑客攻击入侵服务器的6种常见方式
  11. 计算机点击管理无效,我的电脑有任务管理器但是点击却没反应是怎么回事
  12. 将Clound compare以及一些mathLab 等源码,集成到我们vs上来并编译
  13. VB MsgBox 函数 了解一下
  14. 瀑布流的3种实现方式
  15. 常见问题汇总:FLUENT面数据处理
  16. 热修复——Tinker的集成与使用
  17. AI+社区智能管理,赋能智慧城市人情共「智」(人工智能应用案例)
  18. UI设计必备工具有哪些?
  19. iPhone用android充电头,安卓充电器也可以给iPhone 12快充!
  20. 【聆思CSK6视觉AI开发套件试用】从部署工程师和测试工程师角度体验CSK6

热门文章

  1. SpringCloud 搭建项目环境、创建 Dept 微服务、客户端调用微服务
  2. ios键盘横屏_iOS横竖屏旋转及其基本适配方法 转
  3. matlab简单程序实例_【简单实例】如何使用C++加速python程序
  4. 在 Java OOP 编程中的注意事项
  5. 端口号被占用时,查找占用该端口号的进程并释放端口号
  6. 『原创』+『参考』使用C#在PPC的Today界面上的任务栏加入应用程序图标
  7. # JavaScript中的执行上下文和队列(栈)的关系?
  8. nginx+tomcat的keepalive验证、bio/nio连接比较
  9. koa-mysql(三)
  10. hdu 4291 矩阵幂 循环节