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

【Linux进程七】程序地址空间

【Linux进程七】程序地址空间

  • 1.进程的地址空间分布
  • 2.类型的本质是偏移量
  • 3.什么是进程地址空间
  • 4.页表的映射和访问权限字段
  • 5.地址空间的作用

1.进程的地址空间分布

在这里插入图片描述
堆是向上扩展的,栈是向下扩展的
因为字符常量区和代码区相邻,受到同样的保护,字符常量区和代码区一样不允许修改
通过代码验证:
在这里插入图片描述
在这里插入图片描述

2.类型的本质是偏移量

栈整体向下扩展,局部向上读取
堆整体向上扩展,局部向下读取
用栈举例:
在这里插入图片描述

所以类型的本质是偏移量

3.什么是进程地址空间

我们用下面的代码可以查看到一个事实

#include <stdio.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include<stdlib.h>    

int main()    
{    
    int id = fork();    
    int tmp = 100;    
    if(id == 0)//子进程执行的代码    
    {    
        tmp = 200;    
        while(1)    
        {    
            printf("子进程tmp: %d,&tmp: %p\n",tmp,&tmp);    
            sleep(1);    
        }    
    }    
    if(id > 1)//父进程执行的代码    
    {    
        while(1)    
        {    
            printf("父进程tmp: %d,&tmp: %p\n",tmp,&tmp);    
            sleep(1);    
        }    
    }                                                                                                                                                                   
    return 0;    
}    

在这里插入图片描述

子进程和父进程的地址一样,但却有两个值

所以是事实:平时看见的地址并不是真实的地址而是虚拟地址,真实的地址空间被称为物理地址(物理内存)

在这里插入图片描述
每个进程都有自己的进程地址空间

操作系统想管理进程,就一定要先描述,再组织
所以进程地址空间是一个数据结构struct用于描述进程

在这里插入图片描述

程序地址空间有多个区域结合而成,而区域之间的划分就是区域开头begin和区域结尾end
说明进程地址空间就是一个线性区域
就像下面代码一样:

struct mm_struct
{
	int code_begin;//代码区起始
	int code_end;//代码区结束
	int init_begin;//初始化区起始
	int init_end;//初始化区结束
	int heap_begin;//堆区起始
	int heap_end;//堆区结束
	......
};

4.页表的映射和访问权限字段

OS为每一个进程配对一个虚拟地址空间和一张页表,要访问物理地址时,需要先在页表进行映射(若访问的是非法地址,则会在页表层阻止你的访问)

在这里插入图片描述
所以父进程和子进程之间的关系是这样的:
在这里插入图片描述

创建子进程,就要创建子进程的PCB,及地址空间和页表结构 子进程的相关内核数据结构的属性字段会继承父进程
正常来说,子进程要对tmp对修改,把tmp变成200,父进程通过映射关系找到tmp,读到200
但因为进程具有独立性,子进程对数据的修改,不影响父进程,所以当子进程要对tmp修改时,在内存中重新申请一块空间,拷贝tmp值给新空间,重新映射指向新开辟的空间,不影响父进程的tmp值,最终将新开辟的空间tmp值改成200
所以二者虚拟地址相同,但物理地址不同

更详细的页表:
在这里插入图片描述

常量字符串不能修改,正是因为映射时的访问权限字段里没有修改权限

5.地址空间的作用

  1. 让进程已统一的视角看待内存(物理地址):无序变有序
    任意一个进程都可以通过地址空间和页表将内存中乱序的内存数据变为有序
  2. 虚拟地址有效保护了物理地址
    操作系统通过虚拟地址的映射过程,用页表的权限访问字段阻止了非法访问
  3. 将进程管理和内存管理解耦
    因为有进程地址空间和页表的存在,物理内存的分配就可以和进程的管理互不打扰
  4. 保证进程的独立性
    操作系统通过虚拟地址的映射过程,用页表将进程映射到不同的物理内存,实现进程间的独立
    进程=内核数据结构+进程的代码和数据

相关文章:

  • UDP协议原理
  • CatchCat
  • 【电路笔记】-D型触发器
  • mapper.xml中 “http://mybatis.org/dtd/mybatis-3-mapper.dtd“> 报错的解决方法
  • 指令系统3(算数运算指令)
  • 算法题(102):八皇后
  • 剑指 Offer II 113. 课程顺序
  • 【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring MVC 的核心组件:DispatcherServlet 的工作原理
  • 投资日记_道氏理论技术分析
  • 互联网it常用抓包工具说明
  • 洛谷 P10108 [GESP202312 六级] 闯关游戏 题解
  • 【Linux】——环境变量与进程地址空间
  • ocp考试有判断题吗?多少分及格?
  • 【C++】理解 C++ 中的完美转发(Perfect Forwarding)
  • 人工智能开发中的常见问题与避坑指南
  • 列举常见算法的时间复杂度与空间复杂度
  • 【Java/数据结构】队列(Quque)
  • 【DeepSeek学C++】 effective modern C++第33条款
  • Xcode16.1使用MonkeyDev运行Tiktok报错分析
  • 分享一个精灵图生成和拆分的实现
  • 4天内,云南昆明又一县市区原主官被查
  • 上影节公布今年IMAX片单:暗涌、重生与感官的史诗
  • 美俄亥俄州北部发生火车撞人事故,致2人死亡、至少1人失踪
  • 一个留美学生的思想转向——裘毓麐的《游美闻见录》及其他
  • 七猫征文大赛颁出112万奖金,非遗题材作品斩获金奖
  • 高新波任西安电子科技大学校长