【Linux】深挖进程地址空间

这篇具有很好参考价值的文章主要介绍了【Linux】深挖进程地址空间。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:熟悉【Linux】进程地址空间

> 毒鸡汤:也许有一天,你发觉日子特别的艰难,那可能是这次的收获特别的巨大。

> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

【Linux】深挖进程地址空间,linux

🌟前言

        学习每一个语言都跟地址扯不开关系,这也是学习每一种语言的必修课,学习好地址空间对语言的掌握熟练度就是质的飞越,我们学习代码知识只是语言的表面,像地址空间就比较深层,有点抽象,不好理解,基于这种情况博主给大家带来【Linux】深挖进程地址空间。

【Linux】深挖进程地址空间,linux

⭐主体

我们从以下学习【Linux】深挖进程地址空间😋😋。

【Linux】深挖进程地址空间,linux

简单来讲就是是什么,为什么,怎么做😜😜。

🌙什么是进程地址空间

再次回顾 C/C++ 学习地址空间时候:

【Linux】深挖进程地址空间,linux

地址空间是什么?是内存么?我们举个栗子:

代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

int g_val = 100;
int main()
{
	pid_t id = fork();
	assert(id >= 0);
	if (id == 0) 
	{
		while (1)
		{
			printf("我是子进程,我的id是:%d,我的父进程是:%d,g_val:%d,&g_val:%p\n", getpid(), getppid(), g_val, &g_val);
			sleep(1);
			g_val = 200;
		}
	}
	else
	{
		while (1)
		{
			printf("我是父进程,我的id是:%d,我的父进程是:%d, g_val: %d, &g_val: %p\n", getpid(), getppid(), g_val, &g_val);
			sleep(1);
		}
	}

	return 0;
}

运行结果:

【Linux】深挖进程地址空间,linux

通过上图可以发现子进程的g_val修改成了200,但是父进程的g_val始终未改变的。

  • 我们的fork调用之后创建了一个子进程,父子进程的代码和数据共享,而进程是具有独立性的
  • 所以改变子进程的g_val的值并不会影响父进程的g_val,这是得益于fork函数采用了写实拷贝的方法实现的

最大的问题是父子进程的地址相同,对应的g_val值竟然不一样?同一块空间有两个不同的值??

  • 这块空间绝不是物理地址(内存),因为物理地址(内存)对应的内容肯定是唯一的!!
  • 不可能会出现同一个变量的地址读取出两个不同的值。

这里的地址实际上是虚拟地址(线性地址),Linux也有可能叫做逻辑地址。

虚拟空间:所以对于我们而言,直接使用虚拟地址,操作系统再从虚拟地址到页表加载到内存,在通过页表映射,找到对应的物理内存。也就是说,操作系统自动完成。

采用图解的方式:

【Linux】深挖进程地址空间,linux

  • 父进程和子进程都有自己的独立的进程地址空间,且都有自己的页表结构。
  • 子进程由父进程创建,所以子进程的地址空间是从父进程拷贝而来,刚开始的g_val经过映射指向同一个物理内存,所以刚开始看到的都是100。

        后来子进程修改了自己地址空间的g_val的值,当操作系统通过页表映射发现g_val的值是共享的,但是我们知道进程具有独立性,所以操作系统为了保证进程的独立性,当子进程或者父进程任何一方尝试对共享数据进行写入,那么操作系统会在物理内存上重新开辟一块新的内存空间,拷贝数据,然后在修改映射关系,不再指向老的变量,在整个修改的过程中,和父子进程的虚拟地址没有任何关系,只是底层经过页表映射到不同的区域,所以我们看到了地址是一样的,但是内容却是不一样的,这就是现象的由来!

如何理解线性地址?

        以32位计算机为例,我们有32根地址线,每根地址线对应的数据只有0 1信号,那么32根地址线就有2^32中排列组合,就有2^32个地址,我们的CPU在运算完某些数据之后,会进行寻址找到一段地址空间将其存放在内存中,内存地址中最小的单位为字节,那么2^32个地址占据2^32个字节空间,换算出来总的地址空间大小就是4GB!!因为我们的地址是按照字节号大小依次递增的,所以我们就认为地址空间是一个线性结构。

🌙为什么要虚拟地址空间

  • 进程地址空间保证了数据的安全性。

        每个进程都有进程地址空间,所有的进程都要通过页表映射到物理内存,如果进程直接访问物理内存,万一进程越界非法访问、非法读写时,页表就可以进行拦截,而且直接访问物理内存对于账号信息是非常不安全的,所以保证了内存数据的安全性。

  • 地址空间的存在,可以更方便的进行进程和进程的数据代码的解耦,保证了进程独立性的特征

        对于进程而言,都有独立的地址空间及页表,通过页表映射到不同的物理内存上,所以一个进程数据的改变不会影响到另一个进程,保证了进程的独立性,而对于上面我们所说的父进程和子进程而言,子进程的地址空间从父进程拷贝,页表都指向同一块物理内存,但是即使此时的数据是共享的,在修改数据的时候也会发生我们所说的写时拷贝,保证了进程的独立性

  • 让进程以统一的视角,看待进程对应的代码和数据各个区域,方便编译器也以统一的视角来进行编译代码。

        可执行程序被编译器编译的时候每个代码和数据在内存中已经有虚拟地址了(在磁盘上称为逻辑地址),也就是说,地址空间对于操作系统和编译器都是遵守的。所以当程序被加载到内存成为进程后,每个变量/函数都具备了物理地址。

所以我们现在有两套地址:

  1. 标识物理内存中代码和数据的地址
  2. 在程序内部互相跳转的时候的虚拟地址

        加载完成之后,代码的各个区域的地址已经知道。进程被调度时,CPU拿到虚拟地址,经过地址空间查页表通过映射,进行访问查到物理地址往后执行。也就是CPU通过了虚拟地址——页表映射——物理地址执行。也就是在整个CPU运行过程中,CPU并没有见到物理地址,用的都是虚拟地址。

        另外,对于磁盘内可执行程序编译好,这个可执行程序的地址不叫虚拟地址,是逻辑地址。但是对于Linux而言,虚拟地址、线性地址、逻辑地址都是一样的。
【Linux】深挖进程地址空间,linux

🌙虚拟地址与物理地址如何联系

【Linux】深挖进程地址空间,linux

        fork在返回时,父子进程都已经创建好了,这两个进程是独立的,是不是就会return两次?返回的本质是不是写入?谁先return谁就先进行写实拷贝,同一块地址是子进程继承父进程的虚拟地址,return返回写入后,它们就映射到不同的物理空间上了。

   🌟结束语

       今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

【Linux】深挖进程地址空间,linux文章来源地址https://www.toymoban.com/news/detail-770071.html

到了这里,关于【Linux】深挖进程地址空间的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】进程>环境变量&&地址空间&&进程调度

    主页: 醋溜马桶圈-CSDN博客 专栏: Linux_醋溜马桶圈的博客-CSDN博客 gitee :mnxcc (mnxcc) - Gitee.com 目录 1.环境变量 1.1 基本概念 1.2 常见环境变量  1.3 查看环境变量方法  1.4 和环境变量相关的命令 1.5 环境变量的组织方式 1.6 通过代码如何获取环境变量 1.6.1 命令行第三个参数 1

    2024年04月15日
    浏览(54)
  • Linux:进程地址空间

    目录 1.程序地址空间  2.进程地址空间 我们在讲C/C++语言的时候,32位平台下,我们见过这样的空间布局图 我们来验证一下这张图的正确性: 运行结果: 通过观察静态变量的位置,可以认为静态变量就是全局变量,只是静态变量只初始化一次,有作用域的限制。 这里栈区还

    2024年02月04日
    浏览(41)
  • 【Linux】—— 进程地址空间

    序言: 在上篇中,我们讲解了关于进程优先级的概念。本期,我将给大家介绍的是关于进程地址空间的话题。 目录 (一)程序地址空间回顾 (二)代码演示 (三)进程地址空间的引入 总结 我们在学习C/C++语言的时候,大家可能都见过这样的空间布局图: 一个程序有哪些

    2024年02月15日
    浏览(42)
  • 浅析Linux进程地址空间

    现代处理器基本都支持虚拟内存管理,在开启虚存管理时,程序只能访问到虚拟地址,处理器的内存管理单元(MMU)会自动完成虚拟地址到物理地址的转换。基于虚拟内存机制,操作系统可以为每个运行中的进程创建独享的虚拟地址空间,在这个空间中执行的程序,无法感知

    2024年01月20日
    浏览(39)
  • Linux--进程地址空间

    1.线程地址空间 所谓进程地址空间(process address space),就是从进程的视角看到的地址空间,是进程运行时所用到的虚拟地址的集合。 简单地说,进程就是内核数据结构和代码和本身的代码和数据,进程本身不能访问物理地址,之时候就需要有一个中间媒介,就是地址空间,

    2024年02月11日
    浏览(44)
  • 【Linux】理解进程地址空间

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 ​我们在学习C语言的时候,都学过内存区域的划分如栈、堆、代码区、数据区这些。但我们其实并不真正理解内存 — 我们之前一直说的内存是物理上的内存吗? 我们先看一段测试代码: 运行结果: 我们可以注意到子进程的变量

    2024年02月02日
    浏览(53)
  • 『 Linux 』进程地址空间概念

    在c/C++中存在一种 内存 的概念; 一般来说一个内存的空间分布包括 栈区 , 堆区 , 代码段 等等; 且内存是 自底向上 (由 0x00000000 至 0xFFFFFFFF ); 以该图为例: 该图即为常见的内存分布图; 正文代码段 正文代码段所存放的数据 一般为函数体的二进制代码 ; 已初始化数据区 已初始化

    2024年02月03日
    浏览(45)
  • 【Linux】进程理解与学习Ⅳ-进程地址空间

    环境:centos7.6,腾讯云服务器 Linux文章都放在了专栏:【 Linux 】欢迎支持订阅 🌹 相关文章推荐: 【Linux】冯.诺依曼体系结构与操作系统 【Linux】进程理解与学习Ⅰ-进程概念 浅谈Linux下的shell--BASH 【Linux】进程理解与学习Ⅱ-进程状态 【Linux】进程理解与学习Ⅲ-环境变量 在

    2023年04月14日
    浏览(81)
  • 【Linux进行时】进程地址空间

    我们在讲C语言的时候,老师给大家画过这样的空间布局图,但是我们对它不了解 我们写一个代码来验证Linux进程地址空间 这里没什么问题,就是他们的g_valule 和其地址都是一样的, 我们将代码调整一下,让子进程的g_value++ 我们可以发现子进程的g_value变了,但是父进程没有

    2024年02月08日
    浏览(41)
  • 【Linux取经路】初探进程地址空间

    之前在介绍 fork 函数的时候说过该函数返回了两次,至于为什么会返回两次,以及 fork 函数是如何做到返回两次的,在【Linux取经路】揭秘进程的父与子一文中已经做了详细的解释,忘了小伙伴可以点回去看看。在解释一个变量怎么会有两个不同值的时候,当时的说法是由于

    2024年01月21日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包