1. 物理内存与磁盘的关系
如何理解物理内存?
物理内存的宽度为1字节
如使用c语言,可以定义出char类型(1字节),在虚拟地址空间上可以把1字节的单位映射到内存中
如果认为内存是按照字节为单位去划分的,实际上是不正确的
把数据从磁盘换入物理内存,把数据从物理内存换入磁盘,是一个高频的工作,物理磁盘是一个机械设备,作为外设
整体会很常慢,使整机的效率低下,若过多进行IO,就导致过多的寻址操作,即 效率低下
当有100MB的空间写到磁盘中,1次写入到磁盘中,还是分100次写入,每次写入1MB的数据 那个效率高?
1次写入到磁盘中肯定是更高,因为只需要一次寻址操作
说明OS和磁盘进行IO交互时,绝对不是按照字节为单位的,而是要按照 块(4KB) 为单位
若只想修改一个比特位,也必须IO4KB,因为 4KB 作为一个块 是一个整体
若要把文件加载到内存,以4KB为单位,需要在两个方面下考虑
1.文件系统 +编译器
若要从外设磁盘中读取4KB,前提是文件系统认4KB,文件本身按照4KB进行存储
所以文件在磁盘时,就以块为单位的4KB
文件也包括可执行程序和动态库,也是需要存到磁盘上的,都要按照4KB为单位储存到磁盘上
2.操作系统+内存
当磁盘按照4KB的方式把数据存好, 物理内存也要提供保存4KB的数据空间
把物理内存中存放数据的空间称之为 页框
磁盘中数据块称之为 页帧
内存在实际进行内存管理的时候,也要是4KB为单位的
内存管理的本质:将磁盘中特定的4KB块(数据内容)放入到哪一个物理内存的4KB空间(数据保存的空间)
凭什么物理内存要分为一个个4KB大小?
操作系统要管理这些配置
而管理的本质是先描述,在组织
先描述
内核中,有对应的配置数据结构struct page 来管理对应的配置
struct page 是一个结构体,包含这个配置的状态
再组织
通过数组的方式来进行管理
数组有下标存在,物理内存中分别对块进行编号0-n ,
若想要在查询物理内存中那些位置被占用,通过找到对应数组下标,即可看到对应的结构体里面对应的状态
若没有分配,则将状态置为1
若以块方式存储,则多出的空间是否浪费?
假设访问一段代码只有10个字节,load时以4KB为块进入磁盘中,则会多出来2KB的空间
局部性原理的特性, 允许提前加载正在访问数据的相邻或者附近的数据
通过预先加载要访问数据的附近的数据来减少未来的IO次数
多加载进来的数据,本质就是 数据的预加载
如果还不懂,则点击查看:局部性原理详细解释
2. 虚拟地址到物理地址的转换
一个虚拟地址对应32个比特位
虚拟地址不是被整体使用的,被划分 10 +10 +12
当前页表需要2^10行
根据前10个比特位的二进制序列,找到页表1所对应的位置
页表1的左侧代表 前10个比特位,右侧代表另一个页表的起始地址
根据 第二个 10个比特位,找到页表2对应的位置
页表2的左侧代表 第二个 10个比特位 , 右侧代表物理地址(页框的起始地址)
对应页框的起始地址+ 虚拟地址的低12个比特位对应的地址数据 本质为 页内偏移
定位到页框内的任意地址
3. 缺页中断
申请物理内存后,不一定立马用,若立马申请物理内存,不用就导致内存一直被占着,处于闲置的状态,不是高效的表现
实际申请malloc内存时,操作系统只要给你在虚拟地址空间上申请就行了,当真正访问时,操作系统会自动申请或者填充页表以及申请具体物理内存
MMU查询页表找不到,但确实空间已经申请了,就会触发缺页中断,
OS会执行对用的处理方法 即申请物理内存用于填充页表,再返回继续执行代码
4. 为什么字符常量区是不允许被修改的?
hello world在常量区,只能被读取,不能被修改,所以*s=‘w’,是错误的
s里面保存的是指向的字符的虚拟起始地址
*s寻址时,会伴随虚拟地址到物理地址的转换
通过查页表的方式,对操作进行权限查询,发现只有读的权限,但没有修改的权限,所以MMU(内存管理单元)异常,
OS识别到异常,给目标进程发送信号 即 在内核态转换为用户态时,进行信号处理—终止进程
5. 线程缺点
1. 性能损失
创建过多的线程,只有少数在运行,大多数的线程来回被调度 造成性能损失 即多线程创建不合理
2.健壮性降低
如果一个线程出现问题,可能会对整个进程造成影响
3.缺乏访问控制
每个执行流通过同一个地址空间看到的资源是相同的
对于健壮性降低的验证
共有三个死循环,若只有一个执行流,三个死循环不可能执行
若都执行了一定有三个执行流
说明有三个执行流
LWP称为轻量级进程 即线程
每个线程的PID相同,说明属于同一个进程
PID与LWP相同,说明是主线程
在线程2中设置非法操作,使线程崩溃
运行时会发生段错误, 刚开始线程是可以运行的,但是发生段错误后,进程崩溃了
在多线程程序中,任何一个线程崩溃了,最终都会导致进程崩溃
缺乏访问控制的验证
定义一个全局变量,线程1和主线程把全局变量的地址和全局变量的数据打印出来
线程2把全局变量的地址和数据的同时,把数据++
当有一个线程中的数据修改后,所有的线程中的数据都跟着修改
以全局变量为例,在多线程场景中,多个线程看到的是同一个全局变量