先来介绍下CPU:
CPU容量小 需要别人给她指令但是运转速度快 主要是寄存器构成的
1. 通过控制器从内存中读入指令和数据到寄存器中并根据结果来控制整个计算机
2. 而运算器负责运算从内存读入的寄存器的数据
3. 时钟负责发出CPU开始计时的时钟信号
4. 运行速度:CPU>内存>硬盘
5. 只是用来运行指令 但是不能保存指令 指令是在内存中
6. 第一条指令是在内存的最顶端
寄存器有很多类型 可以存指令还有数据
电脑的运行过程
CPU一开始从内存中读入指令 是跳转指令然后去BIOS(系统的自检 检查内存 硬盘显卡之类的有无问题) 从中断向量表获取指令 然后把操作系统从硬盘中唤醒 运输到内存中
**总结:CPU运转很快 但是 得从别人那获取指令才知道做什么**
比如指向一个斐波那契数列 是操作系统设置好进程 设置好程序计数器然后让CPU开始计算 如果之前的程序抢占了CPU 那CPU就会执行那个程序的指令 而被抢占的则是保存记录 等待继续操作
CPU最重要的是寄存器和程序计数器(用来记住要执行的下一条指令地址)
CPU还有个缓存 如果CPU访问内存一个位置 以后还会多次访问 并且附近的位置也会很快被访问到 这是程序的局部性原理把他们加入到缓存里会快很多 但是操作系统如果做程序切换那么缓存会失效。
CPU还可以进行流水线操作
CPU所在的是一个批处理的计算机系统 意思就是说 内存中有多个任务 而CPU的任务就是运行计算完成这些任务 如果一个任务遇到了IO操作(速度很慢 内存和硬盘都在加载数据) 那么操作系统就让CPU执行下一个任务
注意:程序在内存中是由地址的动态重定位意思就是 每次运行的时候会记录下每个程序的其实地址 CPU专门有个寄存器来存储初始位置 这样子切换程序的时候不会有数据覆盖
CPU还会增加一个寄存器来记录程序在内存中的长度 这样每次程序访问的时候都会拿地址和这个长度比较判断有没有越界
上述的寄存器和计算内存地址的方法 统称 MMU(内存管理单元)
磁盘缓存就是将硬盘的东西读入内存中 下次访问的时候速度快一点
但是遇到问题 程序很大怎么办?
这个时候根据 局部性原理 把一个程序分成多个小块 按块装在到内存中 叫页框
因为大部分程序都是集中运行在着几个页框中 于是这些页也叫做工作集 这些工作的真实内存映射到对应的物理内存 这个程序其他未加载的部分其实并没有运行 这就涉及到了 虚拟内存是把磁盘作为部分的内存使用 通过分页式或者分段式将正在运行的内容加载到内存中不用的放在磁盘里 这样看起来内存变大了 其实没有
如果真实的内存满了 那么久将现有的页框置换到硬盘上 加载其他的页框进来
每次运行的内存中页框都是要去找对应 物理内存 于是就 将那些最常访问的页框以及对应的物理内存放在缓存中
对于CPU加载程序的时候会分段加载到内存中 对应的也对程序进行标准话 分为代码段 数据段 堆栈段之类的 然后操作系统记住每一段的开始和结束地址 如果一个程序非法访问那么就 杀死它
CPU涉及到函数的调用 : 这个时候可以先介绍一下线程
1. 线程生活在线程池里面
2. 程序可以理解为多个线程的结合体
3. 线程被加载到内存 然后进入CPU 但是需要排队 如果线程赖着CPU不走 就会被垃圾回收掉
4. 每个线程只能在CPU上运行一端时间(或者被其他线程抢占资源打断或者出现IO流这样的耗时操作) 然后再保存自己的信息再等待 等着被唤醒
在就绪和运行中轮转 知道把工作做完
5. 线程有时候需要加锁 如果出现死锁 那么就得kiss掉一个 所以加锁的时候要记住 按照操作系统的算法比较大小 然后从最大的开始加锁
6. 线程是存在线程池中 如果电脑重启那么一切都会置空
7. 线程是被加载到内存中然后开始操作的 过程是 先将class文件加载到方法区中
class的过程:
1. class文件进入方法区等待调用一个线程 线程进来提取了代码指令就开始在工作台进行操作(栈帧)也可以说是一个函数调用 多个工作台组成一个java栈 一个工作台就是一个栈帧依次执行最上的 然后销毁 加入的话也是压在最上面 在工作台里面还有一个局部变量区和操作数栈 最后把操作后的数弹出 这里的操作数算是在操作数栈里面 而不像CPU是放在一个个寄存器里
总结:1. 程序(线程集)被加载到内存中
注意:程序是分段的 意思就是说 程序不是整个都被加载到内存中 而是加载目前需要的个体 也可以理解为线程
2. 从线程从方法区中的class调用指令 然后逐个执行里面线程中的函数调用(栈帧)
执行的过程是CPU来操作的 CPU从内存中读取指令和数据到寄存器 然后根据结果操作整个计算机
3. 线程在栈帧操作的时候会创建栈区 临时保存变量 结束后删除 如果是new的话就会在堆中创建长期的对象 如果不用了就垃圾回收系统自动回收对象。
4. 线程也可被中断 因为CPU去执行其他线程了
5. 函数的调用 CPU执行线程中的指令的时候 逐行往下执行 遇到函数调用就 根据目标函数的地址进入改函数继续执行 最后到结尾 返回函数调用的结果和执行指令(跳转到调用初始的位置的下一行) 回到函数调用的位置执行下一行
额外涉及补充:
通过DLL实现函数共有 节约内存
哈夫曼编码大幅提升压缩比率
运行环境是操作系统+硬件
windows克服了应用在不同cpu的差异
源代码如何运行
编译器可以通过freeBSD的ports机制生成合适的本地代码但是本地文件( obj文件)无法直接运行 需要链接成可执行的exe文件 需要导入库和 直接和exe文件结合的静态链接库 可执行文件的运行条件是需要 再配置信息
堆栈方法区
程序加载的时候还会创建堆和栈: 简单讲一下堆栈方法区
数据都保存在栈中 操作的时候把数据一个一个加入那个桶 得出计算结果然后返回
2. 堆的话是 如果new一个对象出来 对象就在堆里面 内部有个计数器 如果没有标志使用就是废弃的对象会被垃圾回收 干掉