Linux-程序地址空间

news2024/10/9 2:28:56

目录

 1. 程序地址空间分布

2. 两个问题

3. 虚拟地址和物理地址

4. 页表

5. 解决问题

6. 为什么要有地址空间


 1. 程序地址空间分布

测试一下: 

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

int gal_init = 1;
int gal_uninit;


int main(int argc, char* argv[], char* env[])
{
    printf("code add:%p\n",main);
    const char* str = "hello";
    
    printf("str add:%p\n",str);
    printf("init global add:%p\n",&gal_init);
    printf("uninit global add:%p\n",&gal_uninit);
    char* heap1 = (char*)malloc(10);
    char* heap2 = (char*)malloc(10);
    char* heap3 = (char*)malloc(10);
    char* heap4 = (char*)malloc(10);
    
    printf("heap1 add:%p\n",heap1);
    printf("heap2 add:%p\n",heap2);
    printf("heap3 add:%p\n",heap3);
    printf("heap4 add:%p\n",heap4);

    printf("stack1 add:%p\n",&heap1);
    printf("stack2 add:%p\n",&heap2);
    printf("stack3 add:%p\n",&heap3);
    printf("stack4 add:%p\n",&heap4);


    int i = 0;
    for(;i < argc; ++i)
    {
        printf("%s:%p\n",argv[i],&argv[i]);
    }
    printf("env add:%p\n",env);
    return 0;
}

运行结果:

code add0x40057d
int a add0x7ffc2b16df7c
static int b add0x601044
str add0x40081d
init global add0x60103c
uninit global add0x601048
heap1 add0x2301010
heap2 add0x2301030
heap3 add0x2301050
heap4 add0x2301070
stack1 add0x7ffc2b16df70
stack2 add0x7ffc2b16df68
stack3 add0x7ffc2b16df60
stack4 add0x7ffc2b16df58
./myproc0x7ffc2b16e078
env add0x7ffc2b16e088

这些都是之前就了解过的内容,今天详细聊聊地址空间

2. 两个问题

1. 安全问题:

这些程序都在同一个地址空间中,如果发生了越界访问,野指针问题,这些问题该怎么办?

2. 一个特殊现象问题:

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

int main()
{
    int num = 0;
    int ret = fork();
    if(ret == 0)
    {
        int i = 3;
        while(i--)
        {
            printf("I am child,num = %d,&num = %p\n",num,&num);
            sleep(1);                
        }
        num = 1;
        while(1)
        {
            printf("I am child,num = %d,&num = %p\n",num,&num);
            sleep(1);
        }
    }
    else
    {
        while(1)
        {
            printf("I am father,num = %d,&num = %p\n",num,&num);
            sleep(1);
        }
    }
    return 0;
}

为什么父进程和子进程中的num同一个地址,但是却有两个值?

3. 虚拟地址和物理地址

在Linux地址下,这种地址叫做 虚拟地址

我们在用C/C++语言所看到的地址,全部都是虚拟地址!

物理地址,用户一概看不到,由OS统一管理

由OS负责将 虚拟地址 转化成 物理地址 

上面的地址空间分布就是虚拟地址,每个进程被创建,就会有对应的虚拟地址表

虚拟地址表在linux下就是由mm_struct结构体来描述的

Linux下的进程管理PCB:task_struct就有一个指针指向mm_struct,程序和虚拟地址空间联系起来了

4. 页表

OS是如何把虚拟地址转换成物理地址的呢?

页表

页表是一种key-value的数据结构,记录虚拟地址和物理地址一一映射关系

task_struck有一个指针指向页表

页表里的值(虚拟地址,物理地址)是哪里来的呢?

代码在被编译器编译后的每一条语句每一个函数都会有对应的地址,这个地址是逻辑地址,和虚拟地址一样,作为页表的虚拟地址。当程序被加载到物理内存中时,就会有对应的物理地址,然后在对应到页表里面。

程序被执行时,使用的地址是虚拟地址,需要用页表映射到物理地址 

5. 解决问题

到这里,我们就可以解决第一个问题,每个进程都有一个虚拟地址和页表,这些都由OS来维护,在页表对应的每一个物理地址后面,都有一个像文件访问权限一样的标志,如果这个物理地址没有访问权限,就会直接报错终止。有效的保护了物理内存。

第二问题的答案就在图中,fork函数创建子进程时,其实就是拷贝了大部分对应的task_struct,mm_struct和页表,因为父子进程之间大部分属性都一样,但当需要改变num的值时,子进程就在物理空间上重新开了一块空间,拷贝父进程,OS也会更新对应的页表映射关系。这个叫做写时拷贝。但是虚拟地址还是一样的,只是映射关系发生了变化。所以num相同的虚拟地址,不同的值。

6. 为什么要有地址空间

安全性,有效的保护了物理内存

因为地址空间和页表是OS创建并维护的,凡是想用地址空间和页表进行映射,都需要在OS的监管下来进行访问。

内存管理模块和进程管理模块完成了解耦

提高内存的利用率

用户申请的物理空间,malloc和new其实是在虚拟地址上申请的,OS通过延迟分配,提高物理内存的利用率

地址空间和页表的存在可以将内存分布有序化(按照地址空间分布)和进程的独立性(不同的进程映射到不同的物理空间)每一个进程不知道其他进程的存在

对于程序的分批加载,当程序刚刚新建的状态下,进程就只创建内核结构,程序和数据还没有加载到内存中。

程序的分批换出,当进程短时间内不会再被执行了,比如阻塞了,进程的数据和代码被换出到磁盘中的swap区,页表的映射关系也改为磁盘地址。这个过程就叫挂起。

完,写的不好的地方多有体谅,还在学

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

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

相关文章

java中Date类,SimpleDateFormat类和Calendar类

Date类 public Date() 创建一个Date对象&#xff0c;代表的是系统当前此刻的日期时间 public Date(long date) Constructs a Date object using the given milliseconds time value. 把时间毫秒值转变成Date日期对象 public void setTime(long date) Sets an existing Date ob…

【Linux学习】Linux 的虚拟化和容器化技术

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

进阶线段树之乘法线段树

1.乘法线段树 顾名思义&#xff0c;就是其中的区间修改为乘法&#xff0c;但是呢&#xff0c;如果只是一个乘法&#xff0c;把之前的加号变成*号&#xff0c;然后开long long即可&#xff08;因为乘法的数据超大&#xff0c;如果不在中间mod点儿东西还能直接超出64位&#xff…

【Java EE】Maven jar 包下载失败问题的解决方法

文章目录 1. 配置好国内的Maven源1.1配置当前项⽬setting1.2设置新项⽬的setting 2.重新下载jar包3.其他问题⭕总结 1. 配置好国内的Maven源 因为中央仓库在国外, 所以下载起来会⽐较慢, 所以咱们选择借助国内⼀些公开的远程仓库来下载资源 接下来介绍, 如何设置国内源 1.1配…

Java集合(个人整理笔记)

目录 1. 常见的集合有哪些&#xff1f; 2. 线程安全的集合有哪些&#xff1f;线程不安全的呢&#xff1f; 3. Arraylist与 LinkedList 异同点&#xff1f; 4. ArrayList 与 Vector 区别&#xff1f; 5. Array 和 ArrayList 有什么区别&#xff1f;什么时候该应 Array而不是…

Spring Boot Mockito (二)

Spring Boot Mockito (二) 基于第一篇Spring Boot Mockito (一) 这篇文章主要是讲解Spring boot 与 Mockito 集成持久层接口层单元测试。 1. 引入数据库 h2及其依赖包 <dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId…

C语言----数据在内存中的存储

文章目录 前言1.整数在内存中的存储2.大小端字节序和字节序判断2.1 什么是大小端&#xff1f;2.2 练习 3.浮点数在内存中的存储3.1.引子3.2.浮点数的存储3.2.2 浮点数取的过程 前言 下面给大家介绍一下数据在内存中的存储&#xff0c;这个是一个了解c语言内部的知识点&#xf…

动规训练3

一、按摩师 1、题目解析 简而言之就是&#xff0c;找到一个按摩师的预约总是长的最长方案&#xff0c;还有一个限制条件&#xff0c;选取的预约两两不相邻。 2、算法原理 a状态表示方程 小技巧&#xff1a;经验题目要求 dp[i]表示以这个节点为结尾&#xff0c;最长的预约时…

【C语言】翻译环境与运行环境

一、前言 在我们学习C语言的时候&#xff0c;第一个接触的程序就是&#xff1a;在屏幕上打印” hello word! “&#xff0c;可当时的我们却未去深入的理解与感悟&#xff0c;一个程序代码是如何运行的&#xff1b;而这一期的博客&#xff0c;则是带着我们&#xff0c;通过C代码…

Python | SLP | EOF | 去除季节趋势

EOF & PC 前言 在计算EOF&#xff08;经验正交函数&#xff09;之前去除季节循环是为了消除数据中的季节变化的影响&#xff0c;使得EOF能够更好地捕捉数据中的空间变化模式。如果不去除季节循环&#xff0c;季节性信号可能会在EOF中占据较大的比例&#xff0c;从而影响对其…

材料物理 笔记-4

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; 离…

浙大恩特客户资源管理系统 RegulatePriceAction SQL注入漏洞复现

0x01 产品简介 浙大恩特客户资源管理系统是一款针对企业客户资源管理的软件产品。该系统旨在帮助企业高效地管理和利用客户资源,提升销售和市场营销的效果。 0x02 漏洞概述 浙大恩特客户资源管理系统 RegulatePriceAction接口存在 SQL 注入漏洞,攻击者可通过输入恶意 SQL …

信息传播的AI时代:机器学习赋能新闻出版业的数字化之旅

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

layui框架实战案例(26):layui-carousel轮播组件添加多个Echarts图标的效果

在Layui中&#xff0c;使用layui-carousel轮播组件嵌套Echarts图表来实现多个图表的展示。 css层叠样式表 调整轮播图背景色为白色&#xff1b;调整当个Echarts图表显示loading…状态&#xff1b;同一个DIV轮播项目添加多个Echarts的 .layui-carousel {background-color: #f…

黄锈水过滤器 卫生热水工业循环水色度水处理器厂家工作原理动画

​ 1&#xff1a;黄锈水处理器介绍 黄锈水处理器是一种专门用于处理“黄锈水”的设备&#xff0c;它采用机电一体化设计&#xff0c;安装方便&#xff0c;操作简单&#xff0c;且运行费用极低。这种处理器主要由数码射频发生器、射频换能器、活性过滤体三部分组成&#xff0c;…

GPT-3.5开放免费使用,这次OpenAI做到了真的open

本周一&#xff0c;OpenAI宣布&#xff0c;部分地区的ChatGPT网站访问者现在无需登录即可使用人工智能助手。 此前&#xff0c;该公司要求用户创建账户才能使用&#xff0c;即使是目前由GPT-3.5AI语言模型支持的免费版ChatGPT也是如此。 01.GPT-3.5开放免登录使用 众所周知&…

mysql+keepalive+lvs搭建的数据库集群实验

前提条件&#xff1a;准备5台计算机&#xff0c;且网络互通 1、客户端 yum groups -y install mariadb-client ip 192.168.0.5 2、lvs1 yum-y install ipvsadm keepalived ip 192.168.0.1 keepalivedvip 192.168.0.215 /etc/hosts 解析192.168.0.1 主机名 3、lvs2 yum-y i…

生成式人工智能与 LangChain(预览)(下)

原文&#xff1a;Generative AI with LangChain 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 六、开发软件 虽然这本书是关于将生成式人工智能&#xff0c;特别是大型语言模型&#xff08;LLMs&#xff09;集成到软件应用程序中&#xff0c;但在本章中&#xff0c;…

C++模板基础1——定义函数模板

函数模板定义格式 模板函数定义格式如下&#xff1a; template <typename T> 返回类型 函数名(参数列表) {// 函数体 }其中&#xff0c;template<typename T>是模板声明&#xff0c;用于定义模板参数 T。可以使用不同的关键字代替 typename&#xff0c;例如 clas…

4大企业实例解析:为何MongoDB Atlas成为AI服务构建的首选

随着人工智能和生成式AI技术的迅猛发展&#xff0c;众多企业和机构正积极利用自然语言处理&#xff08;NLP&#xff09;、大型语言模型&#xff08;LLM&#xff09;等前沿技术&#xff0c;打造出一系列AI驱动的产品、服务和应用程序。 本文将展示四家已在AI创新领域取得显著成…