Linux|进程地址空间

Linux|内存地址空间

  • 现象
  • 基本概念
  • 理解
    • 如何理解地址空间
      • 什么是划分区域?
      • 地址空间的理解
      • 为什么要有地址空间?
      • 如何进一步理解页表和写时拷贝
      • 如何理解虚拟地址
    • Linux真正的进程调度方案

现象

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
int g_val = 100;


int main()
{
    printf("father is running, pid: %d, ppid: %d\n", getpid(), getppid());


    pid_t id = fork();
    if(id == 0)
    {
        //child
        int cnt = 0;
        while(1)
        {
            printf("I am child process, pid: %d, ppid: %d. g_val: %d, &g_val: %p\n", getpid(), getppid(), g_val, &g_val);
            sleep(1);
            cnt++;
            if(cnt == 5)
            {
                g_val = 300;
                printf("I am child process, change %d -> %d\n", 100, 300);
            }
        }
    }
    else
    {
        //father
        while(1)
        {
            printf("I am father process, pid: %d, ppid: %d. g_val: %d, &g_val: %p\n", getpid(), getppid(), g_val, &g_val);
            sleep(1);
        }
    }
}

在这里插入图片描述
同一个地址但是值却不一样!这是为什么呢?我们可以得出一个最基本的结论:就是我们看到的地址不是真实的物理地址

基本概念

操作系统为我们划分了4G的虚拟进程地址空间(针对32位的机器)
在这里插入图片描述

  • 虚拟进程空间和真实的进程空间通过页表的映射联系起来
    在这里插入图片描述

  • 每一个进程都有自己的一份虚拟进程空间,子进程会基础父进程的内核数据结构
    在这里插入图片描述

  • 内存空间是用来描述代码和数据的,本质是操作内核中的一个数据结构

  • 因为操作系统设计进程的时候要保证独立性,子进程的数据是独立的,子进程修改val的值的时候会发生写时拷贝
    在这里插入图片描述
    这也解释了为什么我们看到的地址一样值却不一样,因为发生了写时拷贝,虽然虚拟地址是一样的但是物理地址则不一样。
    写实拷贝本质是一种按需申请,如果把父进程内存空间的数据全部拷贝一份,会浪费很多。比如命令行参数和环境变量几乎是不修改的。

理解

如何理解地址空间

什么是划分区域?

上小学的的时候,我们都会遇到这种情况,就是和同桌划分三八线,本来各占桌子的百分之五十,但是一天你突发奇想想要把区域划分大一点。这怎么用计算机描述呢?
在这里插入图片描述
我们可以定义一个区域的结构体来描述自己的区域大小。
另外一个结构体用来描述来个区域的信息。

struct area
{
	int start;
	int end;
}typedef area

struct desk
{
 	area left;
 	area right;
}typedef desk

desk.left.end += 20;
desk.right.start -= 20;

进程地址空间本质上也是一个结构体,很多属性表示end 和start的范围

地址空间的理解

操作系统给进程画的大饼
操作系统告诉每个进程你们可以使用整个的内存哦!

为什么要有地址空间?

  • 实际中的物理内存中,代码区,数据区,堆区,栈区,共享区,命令行参数,环境变量是杂乱存放的。页表和进程地址空间可以将无序变为有序。
  • 对进程管理模块和内存管理模块进行解耦。我们申请开辟空间只是在进程地址空间中调end的大小,当使用时才真正的在内存中分配。这样做能提高内存的利用率
  • 拦截非法请求当我们访问内存时,操作系统和硬件会在页表中寻找物理内存的位置,但是当我们越界访问时,就在页表中找不到对应的物理内存的位置,操作系统就把这次访问内存的请求拦截了下来,避免往内存中写入废旧的数据,从而影响其他内存。

如何进一步理解页表和写时拷贝

页表里面有很多标记位,比如能否读写的标记位,是否在物理内存中的标记位

  • 理解进程挂起,就是把进程是否在物理内存中置为false了
    在这里插入图片描述

  • 解释 char *str =“hello word”; *str =‘H’ 在字符常量区为什么不能被修改呢? 因为页表在映射时有权限管理

OS通过识别到错误(比如父子进程对全局变量的权限都是r和w 父进程一旦创建了子进程,对全局变量的权限都变为w 此时修改就会判断为错误)来引发写时拷贝:

  • 先判断数据是不是在物理内存中(看标记为是否ture)如果不在发生缺页中断,在内存中分配一个空间。这属于正常情况
  • 是不是需要写实拷贝,怎么判断是否需要写实拷贝呢?通过引用计数的方式
  • 如果都不是才进行异常处理,比如我们越界了,地址就不页表的虚拟地址中

如何理解虚拟地址

最开始的时候页表里的数据从那里来的?
我们知道程序里面本身就有地址
这个地址就是逻辑地址(虚拟地址)
当程序加载到物理内存的时候,就得到物理地址
根据这个虚拟到物理建立映射关系

int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        // child
        while(1)
        {
            printf("I am child, %d, %p\n", id, &id);
            sleep(1);
        }
    }
    else if(id > 0)
    {
        while(1)
        {
            printf("I am father, %d, %p\n", id, &id);
            sleep(1);
        }
    }
    return 0;
}

解释这个id怎么能同时==0又!=0呢?return 的本质就是对ID进行写时拷贝

Linux真正的进程调度方案

在这里插入图片描述

  • runqueue里的queue虽然有140个空间 但是前100个空间不用。
    和我们nice -20到19 对应优先级 60~99
    在这里插入图片描述
  • queue里面的每一个元素又是一个队列,把task_struct 按优先级放入对应下标的队列中
  • 因为前面有很多空间没用,我们又使用了大小为5个长整型的位图 32位 32位的查找 使用的下标。
  • 实际当中有两个这样的结构 通过一个active指针和expired指针指向,active指向的队列 只出不进,expired指向的队列只进不出。
  • active指向的队列为空时交换两个指针。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

兔子繁衍问题<C语言>

问题&#xff1a;一对兔子&#xff0c;从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。假如兔子都不死&#xff0c;请问第1个月出生的一对兔子&#xff0c;至少需要繁衍到第几个月时兔子总数才可以达到N对&#xff1f; 分析&#xff1a; 可以观…

HTML5 Canvas发光Loading动画源码

源码介绍 之前我们分享过很多基于CSS3的Loading动画效果&#xff0c;相信大家都很喜欢。今天我们要来分享一款基于HTML5 Canvas的发光Loading加载动画特效。Loading旋转图标是在canvas画布上绘制的&#xff0c;整个loading动画是发光3D的视觉效果&#xff0c;HTML5非常强大。 …

Docker入门指南:Docker镜像的使用(二)

&#x1f340; 前言 博客地址&#xff1a; CSDN&#xff1a;https://blog.csdn.net/powerbiubiu &#x1f44b; 简介 在本章节中&#xff0c;将深入探讨 Docker 镜像的概念&#xff0c;以及如何使用镜像的一系列操作。 &#x1f4d6; 正文 1 什么是镜像 1.1 Docker镜像的简…

C++对象引用作为函数参数

使用对象引用作为函数参数最常见&#xff0c;它不但有指针作为参数的优点&#xff0c;而且比指针作为参数更简单、更方便。 引用方式进行参数传递&#xff0c;形参对象就是实参对象的“别名”&#xff0c;对形参的操作其实就是对实参的操作。 例如:用对象引用进行参数传…

每日Attention学习4——Spatial Attention Module

模块出处 [link] [code] [MM 21] Complementary Trilateral Decoder for Fast and Accurate Salient Object Detection 模块名称 Spatial Attention Module (SAM) 模块作用 空间注意力 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional a…

新能源汽车动力电池热管理方案直冷方案原理简介

前言 随着新能源汽车的快速发展&#xff0c;动力电池作为其核心部件之一&#xff0c;对于其性能和寿命具有重要影响。动力电池在工作过程中会产生大量的热量&#xff0c;如果不能有效地进行热管理&#xff0c;将会导致电池温度升高、性能下降甚至损坏。因此&#xff0c;热管理…

论文阅读:Real-Time 3D Model Acquisition

前言&#xff1a; 本文为记录自己在NeRF学习道路的一些笔记&#xff0c;包括对论文以及其代码的思考内容。 小编目前在探索3DAIGC和3D打印交叉研究&#xff0c;在这方面有想法、经验的朋友都可以在b站留言交流下&#xff01;欢迎&#xff01; 公众号&#xff1a; AI知识物语…

QT--4

QT 使用定时器完成闹钟 #include "widget.h" #include "ui_widget.h"void Widget::timestart() {timer.start(1000); }void Widget::timeend() {timer.stop(); }Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(t…

OSPF NSSA区域

原理概述 OSPF 协议定义了 Stub 区域和 Totally Stub 区域这两种特殊的非骨干区域&#xff0c;为的是精简 LSDB 中 LSA 的数量&#xff0c;同时也精简路由表中的路由条目数量&#xff0c;实现优化设备和网络性能的目的。根据定义&#xff0c; Stub 区域或 Totally Stub 区域中是…

C++进阶:map与set简单自实现

目录 1. map与set封装红黑树的方式1.1 大概实现思路1.2 红黑树模板抽象1.3 红黑树的迭代器 2. 红黑树模板的实现2.1 结点结构的定义2.2 红黑树迭代器的实现2.2.1 迭代器的结构2.2.2 迭代器的方法实现 2.3 树结构的定义2.4 红黑树接口实现2.4.1 插入2.4.2 查找2.4.3 迭代器相关 …

HTML4(二)

文章目录 1 开发者文档2 基本标签2.1 排版标签2.2 语义化标签2.3 行内元素与块级元素2.4 文本标签2.5 常用标签补充 3 图片标签4 超链接标签4.1 跳转页面4.2 跳转文件4.3 跳转锚点4.4 唤起指定应用 5 列表5.1 有序列表5.2 无序列表5.3 自定义列表 6 表格6.1 基本结构6.2 表格标…

企业计算机服务器中了rmallox勒索病毒怎么破解,rmallox勒索病毒解密工具步骤

科技技术的发展&#xff0c;为企业的生产运营注入了新的活力&#xff0c;越来越多的企业利用网络走向了数字化办公模式&#xff0c;网络也极大地方便了企业的生产运营&#xff0c;大大提高了企业的生产效率&#xff0c;加快了企业发展的步伐。但是网络数据安全问题一直是企业关…

基于大语言模型的Agent的探索与实践

AI代理是人工智能领域的核心概念之一&#xff0c;它指的是能够在环境中感知、做出决策并采取行动的计算实体。代理可以是简单的&#xff0c;如自动化的网页爬虫&#xff0c;也可以是复杂的&#xff0c;如能够进行战略规划和学习的自主机器人。 AI代理的概念最早源于哲学探讨&am…

ssrf漏洞学习——基础知识

一、SSRF是什么&#xff1f; SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。 一般情况下&#xff0c;SSRF攻击的目标是从外网无法访问的内部系统。&#xff08;正是因为它是由服务端发起的&#xff0c;所以它能…

大数据手册(Spark)--Spark 简介

Spark 简介 Apache Spark 是一种用于大数据工作负载的分布式开源处理系统。它使用内存中缓存和优化的查询执行方式&#xff0c;可针对任何规模的数据进行快速分析查询。Apache Spark 提供了简明、一致的 Java、Scala、Python 和 R 应用程序编程接口 (API)。 Apache Spark 是专…

Rust Postgres实例

Rust Postgres介绍 Rust Postgres是一个纯Rust实现的PostgreSQL客户端库&#xff0c;无需依赖任何外部二进制文件2。这意味着它可以轻松集成到你的Rust项目中&#xff0c;提供对PostgreSQL的支持。 特点 高性能&#xff1a;Rust Postgres提供了高性能的数据库交互功能&#…

DI-engine强化学习入门(九)环境包裹器(Env Wrapper)

在强化学习中&#xff0c;环境&#xff08;Environment&#xff09;是智能体&#xff08;Agent&#xff09;进行学习和互动的场所&#xff0c;它定义了状态空间、动作空间以及奖励机制。Env Wrapper&#xff08;环境包装器&#xff09;提供了一种方便的机制来增强或修改原始环境…

揭秘新时代的内容创作:一键生成的AI黑科技

在数字媒体的浪潮下&#xff0c;内容创作已成为连接人与信息的重要桥梁。然而&#xff0c;头条、公众号等平台上的爆文创作&#xff0c;对很多内容创作者来说却是一项挑战。“从选题到找素材&#xff0c;再到成文&#xff0c;”这个过程不仅耗时至少1到2个小时&#xff0c;而且…

【go项目01_学习记录08】

学习记录 1 模板文件1.1 articlesStoreHandler() 使用模板文件1.2 统一模板 1 模板文件 重构 articlesCreateHandler() 和 articlesStoreHandler() 函数&#xff0c;将 HTML 抽离并放置于独立的模板文件中。 1.1 articlesStoreHandler() 使用模板文件 . . . func articlesSt…

产品评测:SmartX 与 Nutanix 超融合在数据库场景下的性能表现

重点内容 SmartX 与 Nutanix 超融合分布式存储设计差异如何影响数据库性能表现。重点测试结论&#xff1a;数据库场景下&#xff0c;SmartX 超融合基于单卷部署的性能&#xff0c;依旧优于 Nutanix 超融合基于多卷部署最佳配置的性能。更多 SmartX、VMware、Nutanix 超融合技术…
最新文章