[Linux]进程地址空间

一、虚拟地址

之前提到过父子进程的数据是各自私有一份的,所以子进程中数据的变化不会影响到父进程。我们理所当然的会认为俩进程的数据该保存在不同的地方才对,可是我们却发现他们的地址竟然是相同的,这该怎么理解?

其实我们打印出来的地址并非真实的物理地址,而是虚拟地址(线性地址)

操作系统在给每个进程分配系统的物理内存时,不会让进程知道其他进程占用内存、当前物理内存还剩余多少的情况,而是让每个进程都以为进程自己独占整个系统物理内存。进程之间彼此不知道,不关心对方存在,从而实现一定程度的隔离。

所以进程并不能直接访问到物理内存,也拿不到真正的物理地址,而是通过内核组织起的虚拟地址空间间接访问的。

task_struck 中存在一个 mm 指针,指向一个 mm_struct,这个结构体就是内核为这个进程创建的管理虚拟地址的。

进程虚拟地址空间,本质上是一个内核数据结构对象(类似PCB),记录着系统给进程划分区域的虚拟地址。

二、页表

系统对应还有一张页表,记录着与虚拟地址对应的物理地址。

当进程要访问一个变量时,进程会去找变量的虚拟地址,系统会用页表找到对应的真实物理地址进行访问。

mm_struct + 页表,就是 Linux 系统的虚拟内存管理方案。

在子进程被创建时,不仅 task_struct 被继承一份,mm_struct 也被完全继承一份,页表也被完全继承。

当父或子进程要修改一个变量值时,比如子进程修改 a 的值,系统会先重新分配一块物理内存给子进程的 a,把 a 虚拟地址对应的物理地址替换为新物理地址,然后再修改。这是OS的写时拷贝机制。

fork 后的 id 之所以值不同,也是同样的道理,虽然是同一变量名同一虚拟地址,但被操作系统映射到了不同的物理地址,拿到的值自然也就不同。

现在我们就可以认为,进程 = 内核数据结构(task_struct、mm_struct、页表)+ 代码和数据

进程的独立性,就是内核数据结构各自一份,代码和数据也是独立的(写时拷贝)

页表中有记录着对物理地址的权限的标志位,比如代码区的权限是只读的,那么当进程拿着虚拟地址想要修改代码区的内容时,OS先查到页表中确实有对应条目,再发现对应的物理地址是只读的,就会拒绝进程访问,或者直接杀掉进程。

我们知道 C 中常量字符串是不可以被修改的,但这段代码可以被编译器编过的,而一运行就会出错,是为什么呢?

这是因为这个错误和编译器无关,是发生在系统层面的。常量字符串在代码区,系统查页表时发现进程没有修改权限,于是直接把进程结束掉了。

所以我们要在这样的 char *str 前加 const,这其实是告诉编译器,编程时不要让人改这个字符串,改了要给人报错。

isexists 标志位记录着当前物理地址对应的数据是否存在。当这个数据不存在(还没有被加载进内存、已经被清理等)时,OS 会将这部分数据重新唤入内存,并更新物理地址。

电脑的内存并不大,之所以能跑几十上百个 G 的程序,是因为程序并不是一运行就把全部代码和数据加载进内存的,而是分批加载的。

虚拟地址空间 + 页表,目的是:

1.保护物理内存

2.实现进程管理和内存管理的解耦合

3.让进程以统一的视角看待物理内存

所谓野指针,就是页表中不存在相对应的映射或者没有权限。

全局变量、字符常量,之所以存在全局性,在程序运行时一直有效,是因为他们被存储在已 / 未初始化变量区,在地址空间中,随着进程一直都存在,他们的虚拟地址,也能一直被大家看到。

命令行参数和环境变量会被传递给进程,他们在地址空间中在栈区上边,会继承自父进程。

相关推荐
白鹭22 分钟前
基于LNMP架构的分布式个人博客搭建
linux·运维·服务器·网络·分布式·apache
java叶新东老师1 小时前
linux 部署 flink 1.15.1 并提交作业
linux·运维·flink
程序员JerrySUN2 小时前
Linux系统架构核心全景详解
linux·运维·系统架构
无敌的牛2 小时前
Linux文件理解,基础IO理解
linux·运维·服务器
angushine2 小时前
鲲鹏服务器logstash采集nginx日志
运维·服务器·nginx
未来之窗软件服务2 小时前
跨平台 WebSocket 服务器的设计与实现 —— 基于.NET 8 的跨操作系统解决方案linux,macos,windows——开发工具
linux·服务器·websocket·仙盟创梦ide·东方仙盟
睿思达DBA_WGX2 小时前
由于主库切换归档路径导致的 Oracle DG 无法同步问题的解决过程
运维·数据库·oracle
杰哥的狗2 小时前
nacos连接失败,启动失败常见问题
linux·docker
Jackilina_Stone2 小时前
【faiss】用于高效相似性搜索和聚类的C++库 | 源码详解与编译安装
android·linux·c++·编译·faiss