【Linux课程学习】: 进程地址空间,小故事理解虚拟地址,野指针

🎁个人主页:我们的五年

🔍系列专栏:Linux课程学习 

🌷追光的人,终会万丈光芒

🎉欢迎大家点赞👍评论📝收藏⭐文章

Linux学习笔记:
 https://blog.csdn.net/djdjiejsn/category_12669243.html

前言:

之前听过一遍课,但是如今还对它很模糊,不知道它到底是如何进行的。所以今天重新听课,重新学习。进程地址空间话题很大,这次也只能讲很少一部分,能对进程地址空间的宏观了解就OK。

目录

一.小实验(不是物理地址,而是虚拟地址/线性地址)

1.1实现目的和预想:

1.2修改gval的值继续进行实验:

 二.虚拟地址是什么?

2.1小故事(画饼):

2.2理解虚拟地址空间:

2.3mm_struct结构体

2.4内存编址

 三.页表

3.1代码共享:

3.2页表和物理地址的映射

3.3页表中的标志位

3.3.1rwx权限:

3.3.2isexit标记位:

四.为什么要有虚拟地址+页表

4.1安全和隐私保护:

4.2进程管理和文件管理解耦合:

4.3有效利用内存资源:

4.4让进程以统一的视角看待物理内存:


一.小实验(不是物理地址,而是虚拟地址/线性地址)

Linux大哥,你别骗我,我之前一直给我的时物理地址,没想到你给我一个虚拟的地址,我真的看透你了。线性

路上的一个下BUG

刚刚在进行运行代码的时候,运行结果没有输出,一直卡在那,我以为是出现什么错误了。结果是我没有换行,因为我创建了子进程,这时候的显示器文件缓冲区采取的刷新模式可能是满刷新,当缓冲区满的时候,才会进行刷新。所以一开始在显示器上没有看见东西。后面啪的一下出现很多内容。大概就是这个原因。啊哈哈哈哈哈。下面我又无知了,请原谅我。

1.1实现目的和预想:

因为之前不是说父进程和子进程的代码共享,数据会独立一份吗?现在我们创建一个子进程,打印同一个值的地址是不是一样的,按理来说,他们地址是不一样的,因为数据相互独立。但是真实的结果是如何呢?

看上面的图,我们居然发现他们的地址是一样,啊?这好像不对啊,但好像又可以理解。我们之前学C++的时候,比如字符串string的拷贝的时候,不会立马进行拷贝,不会立即复制字符串的内容,而是增加一个引用计数。这里好像也可以这样理解,如果你不对数据进行修改,那么我还是用原来的呗,你要修改的时候,我再给你申请空间,进行赋值,再让你修改呗!那么我们下面就把gval的值修改一下,看是不是地址会不一样。

好像结果不是这样的,不是要写时拷贝,是因为(Linux大哥)C语言给了我们一个虚拟的地址。

1.2修改gval的值继续进行实验:

我们每次循环让子进程的gval发生变化,他们的地址还是一样的。为什么会这样啊,这就真的不能理解的啊?上面我还能去想想可能是写时拷贝的原因,在这里写时拷贝也关不上啊!

#include<stdio.h>    
#include<sys/types.h>    
#include<unistd.h>    int gval=100;    int main()    
{    printf("我是一个进程,pid:%d , ppid:%d\n",getpid(),getppid());    pid_t id=fork();    if(id==0)    {    while(1)    {    printf("子进程,pid:%d,ppid:%d,gval:%d,&gval:%p\n",getpid(),getppid(),gval,&gval);    sleep(1);    }    }    else    {    while(1)    {    printf("父进程,pid:%d,ppid:%d,gval:%d,&gval:%p\n",getpid(),getppid(),gval,&gval);sleep(1);                                                                                                                                                                                              }    }return 0;    } 

 二.虚拟地址是什么?

这不是程序地址空间哈,这是进程地址空间。为了引入虚拟地址空间,必须把老师说的小故事在这里重复一遍。

2.1小故事(画饼):

在美国有一个大富翁,他很有钱,手上有10亿美金,并且他有很多孩子。有一天他的孩子A跑过来对他说:我想要100美元。大富翁听到以后,觉得没啥,我都有10亿美金了,这100美元能算啥,就把这100美元给了A孩子。但是还没道A孩子的手上,B孩子就冲过来把大富翁手上的100美元给抢走了,B孩子说这100美元是我先看到的,应该是我的。B孩子还没说完,C孩子就抢着说:B孩子都拿了100美元,那我要200美元。A孩子听到以后觉得很不公平,为什么最开始是我先找父亲要的钱,你们反倒比我要的多,为此A孩子说,那我最起码也要200美元。大富翁听到以后,非常头疼,不知道该怎么办?

在美国的另一边,也有一个大富翁,他很有钱,也有10亿美元,也有很多的孩子,但是这些孩子都是他的私生子,他们不知道彼此的存在,都以为大富翁只有我这一个孩子。有一天,大富翁跑到私生子A住的地方去看望A孩子,然后发现A孩子在一家上市公司上班,每天工作非常辛苦。大富翁对孩子A说,好样的!好好干,以后我10亿美金全是你的,孩子A听到以后,非常的开心,认为只要好好干,以后父亲的10亿美金全是我的。

后面大富翁又跑到B私生子那里,B孩子还在读大学,他是他们学习篮球队的主力 ,为了以后能打进NBA,每天训练也是非常的辛苦。大富翁看到以后,对B孩子说:好好打球,只要你好好打球,以后我的10亿美金也是你的。孩子B听到以后,也是非常的开心,觉得马上就能继承父亲的10亿美金了。

大富翁看望完B孩子以后,就去看望私生子C了,C孩子是女儿,现在在读高中,但是跳舞很厉害,她的梦想是去当模特。大富翁看到C孩子以后,也对C孩子说,只要你好好跳,以后我的10亿美金全部都是你的,此时C孩子很开心……当然,大富翁还有其他很多的私生子。

大富翁对每个私生子都是这么说的,每个私生子都以为自己可以拿到父亲的10亿美金,却不知道他们根本拿不到,只能拿到一部分。

以后每个孩子在找父亲要钱的时候,都会有一个潜台词,就是父亲有10亿,而且以后都是我的。

饼画多了,也需要管理。先描述,再组织。这个大富翁就是操作系统!这里的大饼就是程序地址空间!

2.2理解虚拟地址空间:

假如内存大小是4GB,一个进程过来申请了500MB,此时这个进程认为还有3.5GB可以用。但是另外一个进程也申请了500MB,这个进程也觉得它还有3.5GB可以申请,其实此时内存的真实大小只有3GB了。

2.3mm_struct结构体

理解区域划分的本质:

交代区域的开始和结束,就能进行区域划分。

mm_struct中就有每个地址区域的地址空间。有起始位置和结束位置。

PCB中,有一个mm_struct结果体指针,指向一个mm_struct结构体。

mm_struct是由谁来初始化的?信息来源是可执行程序,因为可执行程序被编译好,就有需要多大的空间等信息。可以不加载可执行程序的内容,但是这些信息必须被加载,这些属于PCB的范畴。

栈区是运行的时候,操作系统自己创建的,由操作系统决定。

物理内存延迟开辟,需要的时候,先给你虚拟地址,没有对应的物理地址,只有当真正使用的时候,才会填入物理地址形成映射。

2.4内存编址

最小内存寻址是计算机能访问的最小内存单元。内存是按字节来划分的,32位系统中地址总线通常是32了,能最大表示的地址范围是2的32次方的存储单位,2的10次方是1024,2的32次方就表示4GB大小。

用unsigned long就能表示地址的所以范围,这就是内存编码。


 三.页表

3.1代码共享:

当父进程创建子进程的时候,子进程会拿父进程的PCB进行初始化,mm_struct也相同,页表也相同。页表中的代码区指向同样的物理地址,所以形成了代码共享。父子映射道同样的内存代码区域。所以子进程也是看到fork以上的代码的,只是不会执行它。

3.2页表和物理地址的映射

页表也被子进程继承,所以最开始的虚拟地址和物理地址都是和父进程一样的,用的还是父进程的代码和数据。当时当子进程的数据修改的时候,在此之前,操作系统OS会先申请空间给子进程用,然后修改子进程中的页表物理地址,虚拟地址不变。所以父子进程的有不同的页表,向上返回的虚拟地址是一样的,但是通过不同的页表能映射到不同的物理空间上去。所以就能解释上面小实验了。

在C语言中,变量名就相当于地址。

3.3页表中的标志位

页表中会有很多的标记位,下面就来谈谈rwx标记位和isexit标记位。

3.3.1rwx权限:

rwx标记位可以设置权限,比如代码区,只能是只读的,当如果要写,页表不让你从虚拟地址映射到真实的物理地址了。还有可能直接杀死进程。在代码层面,如果去修改一个只读区,编译器是识别不出来的,这是在运行时,才会去发生映射,才会报错。所以为了让编译器能检查,就引入了const。

3.3.2isexit标记位:

1.分批加载。2.挂起等操作。

表示在页表中这个映射关系是否存在,是都能在内存中找到。因为有种种原因,数据不会一直占着内存,会被放回到磁盘中,内存的大小是有限的。所以这个标记就是说是否在内存中存在。当不存在的时候,如果要进行操作,就会重新加载。所以才能跑大型程序。


四.为什么要有虚拟地址+页表

野指针就是有一个虚拟地址,在进行映射的时候,发现找不到真实的物理地址,或者权限不对,就会发生错误。操作系统就可以控制该进程终止。

可执行程序的代码和数据可以加载到物理内存的任何地址处。有页表进行映射。

4.1安全和隐私保护:

虚拟地址的设定,可以避免程序直接访问物理内存。必须通过页表的映射才能知道物理内存。页表是操作系统来管理的。防止错误程序和恶意软件篡改内存数据,增加系统的稳定性。

4.2进程管理和文件管理解耦合:

进程在进行管理的时候,操作的是虚拟地址,不要去物理地址。这样就大大降低了程序开发的复杂度。

4.3有效利用内存资源:

让进程都以为独占内存空间,但是操作系统可以进行自由切换,没用的时候,就能从内存中放到磁盘中。

4.4让进程以统一的视角看待物理内存:

代码和数据可以加载到物理内存的任意位置,但是对于mm_struct一样还是相同的数据放在一起。

无序变有序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/485651.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

位运算符I^~

&运算&#xff1a;上下相等才是1&#xff0c;有一个不同就是0 |运算&#xff1a;只要有1返回的就是1 ^(亦或)运算&#xff1a;上下不同是1&#xff0c;相同是0 ~运算&#xff1a;非运算&#xff0c;与数据全相反 cpu核心运算原理&#xff0c;四种cpu底层小电路 例&#xf…

16-01、JVM系列之:内存与垃圾回收篇(一)

JVM系列之&#xff1a;内存与垃圾回收篇&#xff08;一&#xff09; ##本篇内容概述&#xff1a; 1、JVM结构 2、类加载子系统 3、运行时数据区之&#xff1a;PC寄存器、Java栈、本地方法栈一、JVM与JAVA体系结构 JAVA虚拟机与JAVA语言并没有必然的联系&#xff0c;它只是与特…

美团一面,有点难度

前几天分享过一篇训练营的朋友在阿里的一面面经&#xff0c;挺简单的她也是很轻松的过了&#xff0c;感兴趣的可以看一下我之前发的文章。 今天要分享的还是她的面经&#xff0c;美团的一面&#xff0c;感觉比阿里的难一些&#xff0c;各位观众老爷你怎么看&#xff1f; 自我介…

spring6:2入门

spring6&#xff1a;2入门 目录 spring6&#xff1a;2入门2.1、环境要求2.2、构建模块2.3、程序开发2.3.1、引入依赖2.3.2、创建java类2.3.3、创建配置文件2.3.4、创建测试类测试2.3.5、运行测试程序 2.4、程序分析2.5、启用Log4j2日志框架2.5.1、Log4j2日志概述2.5.2、引入Log…

03、Node.js安装及环境配置

1.下载node.js 下载地址&#xff1a;Node.js 2.安装 2.1 自定义安装路径&#xff08;可以选择默认&#xff09; 下图根据本身的需要进行&#xff0c;我选择了默认Node.js runtime&#xff0c;然后Next&#xff1a; Node.js runtime &#xff1a;表示运行环境 npm package mana…

容器镜像仓库

文章目录 1、docker hub1_注册2_登录3_创建容器镜像仓库4_在本地登录Docker Hub5_上传容器镜像6_下载容器镜像 2、harbor1_获取 docker compose二进制文件2_获取harbor安装文件3_获取TLS文件4_修改配置文件5_执行预备脚本6_执行安装脚本7_验证运行情况8_访问harborUI界面9_harb…

在paddle中安装python-bidi出错

翻看网上解决方式&#xff0c;是由于系统中缺少 Rust 及其包管理器 Cargo。python-bidi 依赖 Rust 来编译其扩展&#xff0c;如果没有安装 Rust 和 Cargo&#xff0c;安装过程将无法继续。 解决方式 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh但是我的终端…

buuctf:被嗅探的流量

解压后用wireshark查看 flag{da73d88936010da1eeeb36e945ec4b97}

Windows 11 文件管理器隐藏主文件夹、图库和OneDrive

Windows 11 文件管理器隐藏主文件夹、图库和OneDrive 注册表编辑器⌈ 主文件夹 ⌋⌈ 图库 ⌋⌈ OneDrive ⌋ 注册表编辑器 使用 Windows R 快捷键打开「运行」对话框&#xff0c;执行 regedit 打开注册表编辑器。 ⌈ 主文件夹 ⌋ 注册表路径 &#xff1a; 计算机\HKEY_LOCA…

数据结构与算法-03链表-04

链表与递归 在链表操作中移除、反转经常会用到递归实现。通过力扣案例理解链表常规操作中的递归实现。 移除数据 删除链表的节点 问题 LCR 136. 删除链表的节点 - 力扣&#xff08;LeetCode&#xff09; 问题描述 给定单向链表的头指针和一个要删除的节点的值&#xff0c;定…

什么是敏捷(Agile)开发?Scrum和Kanban有什么关系?

最近面试过程中被问到和敏捷开发相关的内容&#xff0c;在产品实际工作中经常会涉及到敏捷开发&#xff0c;但其实我自己没有系列了解过敏捷开发&#xff0c;除了考PMP的时候接触了下&#xff0c;大多数都是在工作中实践积累的&#xff0c;太接地气&#xff0c;为了稍显理论知识…

OpenCV-平滑图像

二维卷积(图像滤波) 与一维信号一样&#xff0c;图像也可以通过各种低通滤波器&#xff08;LPF&#xff09;、高通滤波器&#xff08;HPF&#xff09;等进行过滤。LPF 有助于消除噪音、模糊图像等。HPF 滤波器有助于在图像中找到边缘。 opencv 提供了函数 **cv.filter2D()**&…

容积卡尔曼滤波(CKF)仿真抛物线运动

容积卡尔曼滤波&#xff08;CKF&#xff09;仿真抛物线运动 容积卡尔曼滤波&#xff08;Cubature Kalman Filter, CKF&#xff09;的MATLAB实现。CKF是一种用于非线性系统状态估计的算法&#xff0c;它通过在状态空间中采样点&#xff08;容积点&#xff09;来近似非线性函数的…

leetcode:1995. 统计特殊四元组(python3解法)

难度&#xff1a;简单 给你一个 下标从 0 开始 的整数数组 nums &#xff0c;返回满足下述条件的 不同 四元组 (a, b, c, d) 的 数目 &#xff1a; nums[a] nums[b] nums[c] nums[d] &#xff0c;且a < b < c < d 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3…

几个Linux系统安装体验: 开源欧拉系统

本文介绍开源欧拉系统&#xff08;openEuler&#xff09;的安装。 下载 下载地址&#xff1a; https://www.openeuler.org/zh/download/archive/detail/?versionopenEuler%2022.03%20LTS 本文下载的文件名称为openEuler-22.03-LTS-x86_64-dvd.iso。 帮助文档地址如下&…

Data Uncertainty Learning in Face Recognition 论文阅读

Data Uncertainty Learning in Face Recognition 论文阅读 Abstract1. Introduction2. Related Work3. Methodology3.1. Preliminaries3.2. Classification-based DUL for FR3.3. Regression-based DUL for FR3.4. Discussion of Related Works 4. Experiments4.1. Datasets an…

用友BIP与旺店通数据集成方案解析

用友BIP与旺店通企业奇门的供应商集成同步方案 在现代企业的数据管理中&#xff0c;跨平台的数据集成是实现高效业务运作的关键环节。本文将分享一个实际案例&#xff1a;如何通过轻易云数据集成平台&#xff0c;将用友BIP系统中的供应商数据无缝对接到旺店通企业奇门&#xf…

代码随想录Day34 本周小结动态规划,62.不同路径,63. 不同路径 II,343. 整数拆分,96.不同的二叉搜索树。

1.本周小结动态规划 周一 在关于动态规划&#xff0c;你该了解这些&#xff01; (opens new window)中我们讲解了动态规划的基础知识。 首先讲一下动规和贪心的区别&#xff0c;其实大家不用太强调理论上的区别&#xff0c;做做题&#xff0c;就感受出来了。 然后我们讲了动…

vue中使用socket.io统计在线用户

目录 一、引入相关模块 二、store/modules 中封装socketio 三、后端代码(nodejs) 一、引入相关模块 main.js 中参考以下代码 ,另外socketio的使用在查阅其它相关文章时有出入,还是尽量以官方文档为准 import VueSocketIO from vue-socket.io import SocketIO from socket.io-…

Agent Network Protocol技术白皮书:一个对标Anthropic MCP的协议

Agent Network Protocol技术白皮书&#xff1a;一个对标Anthropic MCP的协议 Anthropic MCP让人们看到智能体通过API或协议与外部数据对接的巨大潜力。我们在几个月之前就发布了Agent Network Protocol技术白皮书&#xff0c;一个和MCP类似的协议&#xff0c;致力于解决智能体…