linux进程(进程地址空间)

目录

前言:

正文:

1.验证地址空间 

2.地址空间是指物理空间吗

3.linux内核的地址空间

4进程访问地址

4.1早期程序寻址 

4.2进程地址空间到物理内存的映射

4.3解释同一变量产生不同值

5虚拟地址空间的意义 

5.1保护物理内存 

5.2进程管理和内存管理的解耦

5.3方便管理 

6总结 


前言:

对于 C/C++ 来说,程序中的内存包括这几部分:栈区堆区静态区 等,其中各个部分功能都不相同,比如函数的栈帧位于 栈区,动态申请的空间位于 堆区,全局变量和常量位于 静态区 ,区域划分的意义是为了更好的使用和管理空间,那么 真实物理空间 也是如此划分吗?多进程运行 时,又是如何区分空间的呢?写时拷贝 机制原理是什么?本文将对这些问题进行解答

 

正文:

1.验证地址空间 

 我们通过代码验证一下,各部分数据处于的位置

  

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    int g_unval;    
int g_val = 100;    int main(int argc, char *argv[], char *env[])    
{    // int a = 10;    //字面常量    const char *str = "helloworld";    // 10;    // 'a';    printf("code addr: %p\n", main);    printf("init global addr: %p\n", &g_val);    printf("uninit global addr: %p\n", &g_unval);    char *heap_mem = (char*)malloc(10);    char *heap_mem1 = (char*)malloc(10);    printf("heap addr: %p\n", heap_mem); //heap_mem(0), &heap_mem(1)    printf("heap addr: %p\n", heap_mem1); //heap_mem(0), &heap_mem(1)    printf("stack addr: %p\n", &heap_mem); //heap_mem(0), &heap_mem(1)    printf("stack addr: %p\n", &heap_mem1); //heap_mem(0), &heap_mem(1)    printf("read only string addr: %p\n", str);    int i;    for(i = 0 ;i < argc; i++){printf("argv[%d]: %p\n", i, argv[i]);}for(i = 0; env[i]; i++){printf("env[%d]: %p\n", i, env[i]);}return 0;
}

2.地址空间是指物理空间吗

我们利用fork()系统调用函数创建子进程,让父子进程共同使用同一个变量

 

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>int main()
{int val = 10;pid_t id = fork();if(id == 0){val *= 2;	//刻意改变共享值printf("我是子进程,pid:%d ppid:%d 共享值:%d 共享值地址:%p\n", getpid(), getppid(), val, &val);exit(0);}waitpid(id, 0, 0);printf("我是父进程,pid:%d ppid:%d 共享值:%d 共享值地址:%p\n", getpid(), getppid(), val, &val);return 0;
}

 

怎么同一个变量,同一个地址,同时读取读到了不同内容呢!!如果地址空间是实实在在的物理地址,同一地址是不可嗯呢读取到两个值,所以结论就是地址空间是虚拟地址也叫线性地址,语言层面包括c/c++都是虚拟地址,用户无法看到真实地址,由操作系统统一管理。

3.linux内核的地址空间

地址空间本质就是一种内核数据结构,在Linux当中,叫做struct mm_struct(linux内核当中的地址空间结构体)包含了一些区域信息(先描述),能够实现区域划分(本质就是在一定的范围内定义start和end)。 

struct mm_struct
{unsigned long code_start;unsigned long code_end;unsigned long init_start;unsigned long init_end;unsigned long uninit_start;unsigned long uninit_end;unsigned long heap_start;unsigned long heap_end;unsigned long stack_start;unsigned long stack_end;//...等不同的区域划分
}

 每个进程都会有自己的地址空间,同时进程控制块(PCB)中也包含了 *mm_struct 指针,可使我们直接找到自己所对应的进程地址空间(后组织)。

  上述讲述的这么多,我们可以理解为进程地址空间就是操作系统给进程花了一个大饼。

  这个大饼就是指的每个进程都会有4GB的连续的空间(0x00000000~0xFFFFFFFF)。实际上呢,这4GB的的空间是虚拟内存,虚拟内存对应的实际物理内存,可能只对应的分配了一点点的物理内存,实际使用了多少内存,就会对应多少物理内存。

  这4G虚拟内存是一个连续的地址空间(这也只是进程认为),而实际上,它的数据是存储在多个物理内存碎片的,还有一部分存储在外部磁盘存储器上,在需要时将数据交换进物理内存。

4进程访问地址

4.1早期程序寻址 

在虚拟地址出现之前,程序的寻址都是直接寻找的物理地址。但是这样会有很多的不足:

直接访问物理内存不安全。例如我们假如使用了野指针,对内存中的数据进行了修改,那么这个时就会影响到其他的进程;
因为物理内存是有限的,当有多个进程要执行的时候,对每个进程都要分配4G内存,很显然你内存若小一点,这很快就分配完了,于是没有得到分配资源的进程就只能等待。当一个进程执行完后,再将等待的进程装入内存。这种频繁的装入内存的操作是很没效率的。
因为内存是随机分配的,所以程序运行的地址也是不正确的。例如下面的代码就会出现野指针的问题

4.2进程地址空间到物理内存的映射

为了解决各种问题,大佬们提出了 虚拟地址空间 这个概念,有了 虚拟空间 后,当进程创建时,系统会为其分配属于自己的 虚拟空间需要使用内存时,通过 寻址 的方式,使用物理地址上的空间即可。如下图所示:

 当有多个进程,具体情况就如下图所示:

        地址空间和页表是每个进程都独有的一份,只要保证每一个进程的页表,能够映射到不同区域的物理内存,就能够做到进程之间互不干扰。这就是我们所说的进程所具有独立性。

          映射是由谁来完成的呢?答案是操作系统!操作系统通过地址转换机制将虚拟地址映射到物理地址,以实现对内存的访问。这种映射通常在页表或段表等数据结构上实现,其中存储了虚拟地址与物理地址之间的映射关系。 

4.3解释同一变量产生不同值

 相同的地址打印出不同的数据。注意,我们所访问到的地址都是虚拟地址。并不是物理地址。我们创建了一个子进程,子进程本身是继承了父进程的数据和代码。在没有对数据进行修改之前,子进程和父进程共享了一份数据。一但对子进程或者父进程的数据进行修改,就会发生写时拷贝。对修改的数据进行深拷贝,从而达到对彼此不产生干扰,实现进程独立性。

  那就对相同地址打印出不同数据的现象不难理解了。当我们对父进程的数据进行修改时,父进程发生了写时拷贝,在内存中开辟了空间。但他们都有自己的地址空间(虚拟地址),所以地址相同也是正常现象(子进程继承父进程的代码和数据)。即使虚拟地址一样,但是可通过页表映射到不同的物理内存中。具体如下图:

5虚拟地址空间的意义 

5.1保护物理内存 

 

可能还有一些疑惑:即使有了虚拟地址,那我要是对野指针进行了访问修改,页表对野指针映射后,还不是对物理内存进行了非法的访问修改吗?地址空间的设置不就多此一举了吗?

  事实并非上述一样。凡是非法的访问或者映射,操作系统都会识别到的。一但你进行了非法的访问或者映射,操作系统就会终止掉你的程序。举个例子,当我们对野指针进行访问修改时,你的程序就会崩溃,这不就是程序终止退出吗!!!

  地址空间有效的保护了物理内存。因为地址空间和页表是操作系统创建并且维护的。这也就意味着地址空间和页表进行映射时需要操作系统进行监管!

5.2进程管理和内存管理的解耦

 

因为有了地址空间和页表,所以我们的数据可以在物理内存中的任何合法位置加载。因为他们之间有映射。物理内存的分配和进程的管理可以做到没有关系!

  所以进程模块和内存模块只需要各自完成各自的事情,最后通过页表的映射将他们连接起来,产生关系。降低了他们之间互相的影响度。

5.3方便管理 

都可以从ox0000开始,同喜视角看待内存结构,让无序的物理地址有序化方便管理。

6总结 

 

我们平常所访问到的地址均为虚拟地址。地址空间并不是物理地址,而是虚拟地址。通过页表映射访问物理地址。 每个进程都有自己的地址空间和页表。

  页表是一种数据结构,它存储了虚拟地址与物理地址之间的映射关系。在进行地址转换时,操作系统根据进程的页表查找对应的物理地址,然后将虚拟地址转换为物理地址,以便进行实际的内存访问。

  通过使用虚拟地址,操作系统可以为每个进程提供独立的地址空间,使得多个进程可以并发运行,彼此之间相互隔离,互不干扰。虚拟地址还提供了更高的灵活性和保护性,使得操作系统可以有效地管理和分配内存资源,提高系统的性能和安全性。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

[论文总结] 深度学习在农业领域应用论文笔记12

文章目录 1. 3D-ZeF: A 3D Zebrafish Tracking Benchmark Dataset (CVPR, 2020)摘要背景相关研究所提出的数据集方法和结果个人总结 2. Automated flower classification over a large number of classes (Computer Vision, Graphics & Image Processing, 2008)摘要背景分割…

前端JavaScript篇之对象创建的方式有哪些?

目录 对象创建的方式有哪些&#xff1f;1. 工厂模式&#xff1a;2. 构造函数模式&#xff1a;3. 原型模式&#xff1a;4. 混合模式&#xff1a;5. 动态原型模式&#xff1a;6. 寄生构造函数模式&#xff1a;7. 字面量方式&#xff1a; 对象创建的方式有哪些&#xff1f; JavaS…

春晚魔术和约瑟夫问题

春晚的魔术实际上是一个约瑟夫问题&#xff0c;最终的结果是魔术开始时确定的几个变量确定好的&#xff0c;扑克牌只是道具和障眼法。网上一查这个问题发现颇有历史渊源&#xff0c;17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事&#xff1a;15个教徒和15 个…

房屋租赁系统的Java实战开发之旅

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

WebSocket 通信流程,注解和Spring实现WebSocket ,实战多人聊天室系统

一、前言 实现即时通信常见的有四种方式-分别是&#xff1a;轮询、长轮询(comet)、长连接(SSE)、WebSocket。 ①短轮询 很多网站为了实现推送技术&#xff0c;所用的技术都是轮询。轮询是在特定的的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由客户端浏览器对服务…

机器学习2--逻辑回归(案列)

糖尿病数据线性回归预测 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_diabetes diabetesload_diabetes() datadiabetes[data] targetdiabetes[target] feature_namesdiabetes[feature_names] data.shape df …

2024刘谦春晚第二个扑克牌魔术

前言 就是刚才看春晚感觉这个很神奇&#xff0c;虽然第一个咱模仿不过来&#xff0c;第二个全国人民这么多人&#xff0c;包括全场观众都有成功&#xff0c;这肯定是不需要什么技术&#xff0c;那我觉得这个肯定就是数学了&#xff0c;于是我就胡乱分析一通。 正文 首先准备…

Mysql Day04

mysql体系结构 连接层服务层引擎层&#xff08;索引&#xff09;存储层 存储引擎 存储引擎是基于表建立的&#xff0c;默认是innoDB show create table tb; 查看当前数据库支持的存储引擎 show engines; InnoDB 特点 DML&#xff08;数据增删改&#xff09;遵循ACID模…

MongoDB的分片集群(二) :mongodb4.x分片集群离线搭建开启安全认证

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 相关文章&#xff1a; MongoDB的分片集群(一) : 基础知识 在《MongoDB的分片集群(一) : 基础知识》中梳理了分片集群的基础知识…

opencv计算机视觉

树莓派主机的无键盘解决 进入控制面板&#xff0c;更改适配器设置&#xff0c;WIFI属性&#xff0c;勾选 1.将网线两头分别接入树莓派和笔记本的网线接口 2.在无线连接属性那里勾选允许其他用户连接 3.运行cmd使用arp -a查看树莓派ip地址&#xff0c;或者使用ipscanner查看 cmd…

JavaIO读取C101.txt文件

一、split分割带空格的字符串&#xff08;四种方法及其区别&#xff09; 参考&#xff1a;https://blog.csdn.net/yezonghui/article/details/106455940 String str "a b c d";String[] arr1 str.split(" "); //仅分割一个空格 String[] arr2 str…

c++之说_11|自定义类型 enum(枚举)与enumclass (c11新枚举)

至于枚举 会用就行 至少目前我感觉没什么太多问题 enum 被称为无作用域枚举 &#xff0c; enumclass / enumstruct 被称为有作用域枚举 看到了吧 语法规则 和 struct 差不多 只不过枚举成员 只是一个标志 它本质是数值 从上到下 下面的数根据上面的数 加 1 也可以直接…

前端JavaScript篇之对闭包的理解

目录 对闭包的理解用途循环中使用闭包解决 var 定义函数的问题 对闭包的理解 闭包是指一个函数能够访问并操作其词法作用域&#xff08;定义时所在的作用域&#xff09;之外的变量的能力。它可以通过在一个函数内部创建另一个函数来实现。内部函数可以访问外部函数的局部变量、…

【维生素C语言】附录:strlen 函数详解

写在前面&#xff1a;本篇将专门为 strlen 函数进行讲解&#xff0c;总结了模拟实现 strlen 函数的三种方法&#xff0c;并对其进行详细的解析。手写库函数是较为常见的面试题&#xff0c;希望通过本篇博客能够加深大家对 strlen 的理解。 0x00 strlen函数介绍 【百度百科】str…

Cobalt Strike 的使用及拓展

Cobalt Strike是一款以Metasploit为基础的GUI框架式渗透测试工具&#xff0c;集成了端 口转发、服务扫描、 自动化溢出、多模式端口监听、exe 、PowerShell木马生成 等&#xff0c;主要用于团队作战&#xff0c;能让多个渗透者同时连接到团体服务器上&#xff0c;共享渗透资 源…

Leetcode2560. 打家劫舍 IV

Every day a Leetcode 题目来源&#xff1a;2560. 打家劫舍 IV 解法1&#xff1a;二分答案 动态规划 给定数组 nums&#xff0c;从中选择一个长度至少为 k 的子序列 A&#xff0c;要求 A 中没有任何元素在 nums 中是相邻的。 最小化 max⁡(A)。 看到「最大化最小值」或者…

基于vue+node.js的校园跳蚤市场系统多商家

校园跳蚤市场系统可以在短时间内完成大量的数据处理、帮助用户快速的查找校园跳蚤市场相关信息&#xff0c;实现的效益更加直观。校园跳蚤市场系统中采用nodejs技术和mysql数据库。主要包括管理员、发布者和用户三大部分&#xff0c;主要功能是实现对个人中心、用户管理、发布者…

数据分析基础之《pandas(7)—高级处理2》

四、合并 如果数据由多张表组成&#xff0c;那么有时候需要将不同的内容合并在一起分析 1、先回忆下numpy中如何合并 水平拼接 np.hstack() 竖直拼接 np.vstack() 两个都能实现 np.concatenate((a, b), axis) 2、pd.concat([data1, data2], axis1) 按照行或者列…

【Opencv学习】04-图像加法

文章目录 前言一、图像加法混合1.1 代码1.2 运行结果 二、图像的按位运算-组合相加2.1 代码2.2 运行结果示例&#xff1a;PPT平滑切换运行结果 总结 前言 简单说就是介绍了两张图如何组合在一起。 1、混合&#xff0c;透明度和颜色会发生改变 2、组合&#xff0c;叠加起来。可…

大厂的供应链域数据中台设计

关注我&#xff0c;紧跟本系列专栏文章&#xff0c;咱们下篇再续&#xff01; 作者简介&#xff1a;魔都技术专家兼架构&#xff0c;多家大厂后端一线研发经验&#xff0c;各大技术社区头部专家博主&#xff0c;编程严选网创始人。具有丰富的引领团队经验&#xff0c;深厚业务架…