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位(你要访问的物理内存在页框中的偏移量) = 物理地址中的数据
所以创建一个进程依旧是一个很重的工作。
所以至此以后,我们知道了虚拟地址是如何映射物理地址的,那么访问任何变量都是起始地址+类型 == 页框的起始地址 + 偏移量。

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

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

总结:

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

相关推荐
淡淡的香烟1 分钟前
Android12 launcher3修改App图标白边问题
android
滴水之功15 分钟前
C语言数据结构-链式栈
linux·c语言·数据结构
liulilittle16 分钟前
Ubuntu 18.04 升级内核到 5.X(< 5.10)
linux·运维·服务器·ubuntu
老攀呀21 分钟前
CentOS系统上挂载磁盘
linux·运维·centos
梅孔立25 分钟前
centos原系统安装了Python3.7.9兼用在安装一个python3.8
linux·运维·centos
aqi0030 分钟前
FFmpeg开发笔记(六十一)Linux给FFmpeg集成H.266编码器vvenc
linux·ffmpeg·音视频·直播·流媒体
sanggou36 分钟前
CentOS 7.6 升级 Openssl 及 Openssh 方法文档
linux·运维·centos
It's Q43 分钟前
接口自动化可视化展示
运维·python·测试工具·自动化
yi个名字1 小时前
Linux环境变量与地址空间
linux·前端·计算机网络
虾球xz1 小时前
WSL 下面 Buildroot + QEMU 环境记录一下
linux·嵌入式·qemu