Linux:再谈进程地址空间

文章目录

      • [1. 动静态库部分的进程地址空间](#1. 动静态库部分的进程地址空间)
        • [1.1 程序没有加载前的地址(程序)](#1.1 程序没有加载前的地址(程序))
        • [1.2 程序加载后的地址(进程)](#1.2 程序加载后的地址(进程))
        • [1.3 动态库的地址](#1.3 动态库的地址)
      • [2. 信号部分的进程地址空间](#2. 信号部分的进程地址空间)
      • [3. 多线程部分的进程地址空间](#3. 多线程部分的进程地址空间)
  • 序:本章将对过去的地址空间的内容进行一个补充,从动静态库到信号,以及即将发的多线程的部分。

1. 动静态库部分的进程地址空间

1.1 程序没有加载前的地址(程序)

问题一:程序编译好之后,其内部有地址的概念吗???

答案肯定是有的!

在程序编译好后,里面也有一个虚拟的地址,每个地址对应不同的指令,这些不同的虚拟地址又分为了不同的区块,和进程地址空间差不多,这是因为,编译器的设计也是要考虑操作系统的,我们将此时的虚拟的地址叫做逻辑地址!!!其中,CPU的内置的多个指令叫做内置指令集(精准指令集和复杂指令集),CPU执行指令是从初始地址开始一条条往下执行的,遇到跳转的时候就跳转过去,最后还是要跳转回来继续往下执行。

1.2 程序加载后的地址(进程)

看下图:

当程序从磁盘加载到物理内存中之后,每一条指令都会有他们自己的物理地址,当要执行该程序时,首先要知道该程序的起始地址,要知道从哪里开始执行,此时,我们之前提到过,程序生成时会生成一个表头,该表头内就有一个entry入口地址,此时将entry入口地址加载带CPU的EIP/PC寄存器中,CPU就会通过task_struct中的cwd和exe,知道该程序的工作路径和可执行程序的位置,从而用CPU寄存器中的entry地址开始执行指令。
但此时,由于虚拟地址和物理地址还没有通过页表进行映射,此时就会发生缺页中断,从而建立起物理地址和虚拟地址的映射关系,其中CPU内读取到的指令,内部可能有数据,可能也有地址(被加载进物理内存后就变成了虚拟地址),当访问的该虚拟地址内容不存在就发生缺页中断就行了!!!此时这就形成了一个循环,而且我们发现我们访问的地址全部是虚拟地址!!!

1.3 动态库的地址

如图:
关键问题:共享库大了,映射到哪里呢?所以共享库被加载到固定位置是不可能的!!!

当CPU通过正文代码访问程序时,刚好访问到动态库函数时,就会根据动态库的映射去共享区中找到这个函数,如果动态库中的方法是绝对编址的,那么就意味着,动态库一定要被加载到某个固定的位置,而我们知道动态库被加载到固定位置是不可能的,所以用偏移量的方式对库中的函数进行相对编址,这样,库在哪里,也能根据偏移量找到相对于的函数了!!!这就是为什么我们在加载动态库的时候要加入-fPIC(与位置无关码)选项,这个就代表着相对编址

问题一:静态库为什么不谈加载,不谈与位置无关?

因为静态库是在编译程序时,直接加载到程序内的,静态库中的方法是加载到程序内后,该方法的地址是固定的!!!

2. 信号部分的进程地址空间

在之前的学习中,我们知道,CPU内部的信号int 80(是一条汇编语句) 从用户态陷入内核态,这样就有进程权利去访问操作系统的数据了
如图:

问题一:用户页表有几份?

有几个进程就有几分用户级页表 -- 进程具有独立性

问题二:内核页表有几份?

只有一份,每个进程看到的3 ~ 4G(内核空间)的东西都是一样的,看到的内核级页表是一样的,看到的操作系统的代码和数据也是一样的,整个系统中,进程再怎么切换,3 ~ 4G的空间的内容是不变的!!!
进程视角:我们调用系统中的方法,就是在进程自己的地址空间中进行执行的!!!
操作系统视角:任何一个时刻,都有进程在调度(执行)。我们想执行操作系统的代码,就可以随时执行!!!
操作系统的本质:基于时钟中断的一个死循环!
在计算机硬件中,有一个时钟芯片,每隔一个很短很短的时间,都会向计算机发送时钟中断

3. 多线程部分的进程地址空间

如图:

CPU中有个CR3寄存器,其中存的就是页表的页目录地址,也有寄存器存储的是进程控制块的地址

问题一:虚拟地址是如何转换到物理地址的?(32位虚拟地址为例)

其中32位虚拟地址并非一个整体,而是分为了三个部分32=10+10+12。而页表也不是一张表那么简单!!!

32 = 10 + 10 + 12,通过前20位,就已经知道页框的起始位置了。
页框的起始位置 + 虚拟地址最后12位(你要访问的物理内存在页框中的偏移量) = 物理地址中的数据
所以创建一个进程依旧是一个很重的工作。
所以至此以后,我们知道了虚拟地址是如何映射物理地址的,那么访问任何变量都是起始地址+类型 == 页框的起始地址 + 偏移量。

问题一:如何理解资源分配给线程?

线程目前分配资源,本质就是分配地址空间的范围。

总结:

本章从进程地址空间的角度补充了动静态库,信号,以及多线程部分的知识,让我们更加深入了解了进程地址空间!!!

相关推荐
Android洋芋7 小时前
PrintFriendly网页文章转PDF插件工具及技术分析
运维·服务器·pdf·网页转pdf
Elastic 中国社区官方博客7 小时前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
大数据·运维·前端·人工智能·elasticsearch·搜索引擎·全文检索
RoboWizard7 小时前
金士顿高速闪存盘 单双接口适配多元存储需求
大数据·运维·人工智能·智能手机·云计算
hkj88087 小时前
Ubuntu 20.04 安装 OpenJDK 17
linux·运维·ubuntu
huainingning7 小时前
防火墙重启后ssl登录提示证书过期临时解决方法
linux·服务器·ssl
YF02117 小时前
Android compose详解
android
sulikey7 小时前
服务器安装Docker教程。如何在云服务器安装Docker容器?
运维·服务器·ubuntu·docker·安装教程·云服务器
IT小码哥丶7 小时前
Android进阶之事件分发机制深度剖析
android
许彰午8 小时前
17-22-运维与高级主题
运维·网络
万联WANFLOW8 小时前
外贸独立站:服务器放海外国内后台卡,放国内海外客户打不开——这道两头难怎么破?
运维·网络·数据库·经验分享