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

Linux-地址空间

目录

1.介绍

2.理解

3.Linux早期的内核调度队列


1.介绍

这是32位的程序空间地址图:

为了更好地理解这段图,我们来写一段代码编译运行:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int g_val=100;int main()
{pid_t id = fork();int cnt=3;if(id == 0){while(1){printf("I am child, pid=%d, ppid=%d,g_val=%d &g_val=%p\n", getpid(), getppid(),g_val,&g_val);sleep(2);cnt--;if(cnt==0){g_val=500;printf("I am child,change pid=%d->%d\n", 100,500);}}}else {while(1){printf("I am father, pid=%d, ppid=%d,g_val=%d &g_val=%p\n", getpid(), getppid(),g_val,&g_val);sleep(2);}}return 0;
}

我们可以看见子进程修改 g_val 的地址后,父进程的地址和子进程的地址是一模一样的,一个地址为什么会有两个不同的值?

答案是这是个虚拟地址,不是物理内存地址,我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理,下面我们从操作系统来理解地址空间

地址空间的本质是内核中的结构体对象。

未写时拷贝(初始共享)

父进程 fork 创建子进程,虚拟地址空间、页表 “逻辑复制” :父子进程虚拟地址(如 g_val 地址 0x56ab5ceac010 )一致,页表均映射到物理内存同一块数据页(g_val = 100 )。此时代码、数据物理页共享,不实际拷贝内存,快速创建进程,节省空间。

写时拷贝(触发拷贝)

当子 / 父进程尝试修改共享数据(如子进程改 g_val值 ),操作系统检测到写操作:
为写操作进程(如子进程)新分配物理页;
把原共享物理页数据(100 )拷贝到新页;
更新写操作进程页表,使其指向新物理页(此时子进程 g_val 500 )。父进程页表不变,仍访问原物理页(g_val 保持 100 ),实现 “写时才真正拷贝内存”,避免冗余开销
核心逻辑:读共享,写拷贝,平衡进程创建效率与数据独立性 。

2.理解

1.地址空间的本质是 struct 里面的一个结构体,内部很多属性都是表示 start end 的范围。 

2.虚拟地址无序变为有序,让进程从统一的角度看待物理内存以及自己运行的各个区域。

3.进程管理模块内存管理模块相互解耦。

在计算机系统(尤其是操作系统、分布式框架)中,进程管理模块(负责进程的生命周期管理、调度、状态维护、权限控制等)与内存管理模块(负责内存分配、回收、地址映射、虚拟内存管理等)是核心功能模块。

二者的 “相互解耦” 是指通过设计隔离模块间的直接依赖,使它们能独立完成各自功能,仅通过标准化接口协作,从而提升系统的可维护性、扩展性和容错性。

虚拟地址页表是实现两者解耦的核心机制之一

4.拦截非法请求

虚拟地址页表通过地址合法性验证权限检查进程地址空间隔离,构建了一层硬件级别的保护机制。它能有效拦截非法的内存访问请求(如越界、权限违规、访问未分配内存等),防止物理内存被错误或恶意操作破坏,是操作系统保障内存安全的核心手段之一。

之前我们介绍 Linux 进程的时候讲过一段代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");return 1;} else if (pid == 0) {while(1){printf("Child process: ID=%d PID = %d, PPID = %d\n", pid , getpid(), getppid());sleep(2);}} else {while(1){printf("Parent process: ID=%d PID = %d, Child PID = %d\n",pid , getpid(), pid);sleep(2);}}return 0;
}

fork() 对子进程进行了写时拷贝,所以才返回了两个不同的值。

3.Linux早期的内核调度队列

一个 CPU 拥有一个 runqueue

  • 如果有多个 CPU 就要考虑进程个数的负载均衡问题

运行队列优先级

queue[140]

之前我们介绍进程优先级的时候,我们介绍过进程默认优先级是 80,nice的范围为 [20,-19]。

进程队列的优先级为:

  • 普通优先级:100~139
  • 实时优先级:0~99

我们的进程值+40就能建立和进程队列的映射

位图:

long bitmap[ 5 ]

我们的队列优先级有140个,要是一个个逐一检测,会增加时间。

bitmap就是为了节约时间的 long bitmap[5] 有 32*5=160 足够包含这么多的优先级,我们只要看位图的数字就能找到哪个优先级还存在进程。

这就是大 O (1) 调度算法大 O (1) 调度算法指的是无论输入规模(比如进程数量、任务数量等)如何变化,算法执行所需的时间保持恒定,不随输入规模的增大而增加。

活动队列(Active Queue)(只出不进)

  • 作用:用于存放时间片尚未耗尽的进程,这些进程会依据优先级进行组织,系统优先调度优先级高的进程,以此保障系统能够高效响应任务需求。
  • 调度逻辑:利用 bitmap 快速查找出优先级最高的非空队列,然后选取该队列的队首进程执行。不管系统中进程的总数是多少,查找和调度进程所花费的时间始终固定,其时间复杂度为 O(1) ,确保了调度过程高效、稳定。

过期队列(Expired Queue)(只进不出)

  • 作用:用来存放时间片已经耗尽的进程,它的结构和活动队列完全一样,可看作是进程时间片管理的 “过渡区域”。
  • 特点:当活动队列中的进程把自身时间片用完后,就会被转移到过期队列中。而当活动队列为空(意味着所有进程的时间片都已耗尽 )时,系统会交换 active 和  expired 指针,此时过期队列就转变为新的活动队列,同时重新计算该队列中进程的时间片,让这些进程能够再次参与到系统调度中,以此实现 “批次轮换” 的调度机制,保障进程获取调度的公平性。

active 指针和 expired 指针

  • active 指针:始终指向当前可供调度使用的 活动队列,系统会从该队列里选取进程来执行任务。
  • expired 指针:始终指向 过期队列,用于暂时存放那些时间片已经耗尽的进程。
  • 核心机制:在系统运行过程中,活动队列里的进程会因为时间片不断消耗而逐渐减少,与之相对,过期队列里的进程数量会相应增多。当活动队列为空时,交换这两个指针,过期队列就 “变身” 为新的活动队列,原本过期队列中的进程会重新获得时间片,继续参与系统调度。这种方式无需实际去搬运进程,就能瞬间重置调度资源池,保障调度持续高效地进行。

http://www.xdnf.cn/news/1300951.html

相关文章:

  • 开发避坑指南(27):Vue3中高效安全修改列表元素属性的方法
  • 【学习笔记】NTP服务客户端配置
  • Go语言中安全停止Goroutine的三种方法及设计哲学
  • 前瞻性技术驱动,枫清科技助力制造企业借助大模型完成生产力转化
  • zabbix部署问题后常见问题
  • 新手入门Makefile:FPGA项目实战教程(二)
  • 【CV 目标检测】②R-CNN模型
  • 【Redis】分布式系统的演化过程
  • MyBatis的基本用法和配置方式
  • Highcharts Dashboards | 打造企业级数据仪表板:从图表到数据驾驶舱
  • 全球电商业财一体化:让出海品牌实现“看得见的增长“
  • demo 通讯录 + 城市选择器 (字母索引左右联动 ListItemGroup+AlphabetIndexer)笔记
  • Nginx反向代理与缓存实现
  • 人工智能与社会治理:从工具到生态的范式重构
  • Kafka生产者——提高生产者吞吐量
  • 切换VSCODE 中的默认 shell
  • GitHub 上 Star 数量前 18 的开源 AI Agent 项目
  • 制造装配、仓储搬运、快递装卸皆适配!MinkTec 弯曲形变传感器助力,让人体工学改变劳动生活
  • Vue3从入门到精通: 4.5 数据持久化与同步策略深度解析
  • Elasticsearch 深分页问题
  • 计算图的力量:从 PyTorch 动态图到 TensorFlow 静态图的全景与实战
  • Nginx蜘蛛请求智能分流:精准识别爬虫并转发SEO渲染服务
  • 【Java EE进阶 --- SpringBoot】初识Spring(创建SpringBoot项目)
  • iceberg 底层存储HDFS与juiceFS的区别
  • nflsoi 8.14 题解
  • 集成电路学习:什么是Video Processing视频处理
  • 《量子雷达》第4章 量子雷达的检测与估计 预习2025.8.14
  • ATAM:基于场景的软件架构权衡分析法
  • 解剖HashMap的put <三> JDK1.8
  • Linux入门指南:基础开发工具---yum/apt