适度打开,很多情况保持黑箱即可。
计算机组成
CPU
CPU制作
硅提纯->切片->镀膜->光刻(全球只有一家在做 荷兰)->切割->封装->测试
Inter
详细流程
CPU原理
计算机最主要的解决问题就是怎么代表数字,二进制,十进制
晶体管工作
晶体管的工作原理
汇编语言执行过程
汇编语言的本质:机器语言的助记符 其实它就是机器语言
计算机通电 -> CPU读取内存中程序(电信号输入)
->时钟发生器不断震荡通断电(GHz,计算机主频) ->推动CPU内部一步一步执行
(执行多少步取决于指令需要的时钟周期)
->计算完成->写回(电信号)->写给显卡输出(sout,或者图形)
量子计算器
CPU组成
PC指令寄存器(Program Counter)
CSPI,记录当前指令地址
Registers 寄存器
暂时存储CPU计算所需要的数据,从内存里拷贝的指令,每个cpu中数量很多。离CPU最近,读写速率最高,<1ns。
ALU Arithmetic & Logist Util 运算单元
做a+b计算时首选寄存器AX读取数值a,寄存器BX读取数值BX,ALU读取到ADD指令,从两个寄存器中读取数据并进行电路运算再讲结果放入寄存器DX中,寄存器DX再将结果写入到内存固定位置
CU 控制单元 Control Util
对中断信号做控制用
MMU 内存管理单元
内存管理,现在寄基本上使用软件实现
cache 缓存
速度比寄存器稍慢,L1 1ns,L2 3ns,L3 15ns,L4 80ns。每核按照块来读取缓存中的数据,每次读取的单位是line,即三层缓存都是按照Line进行范围读取,但是如果有某核修改数据,会造成多核计算数据不同步,所以缓存针对不同核读取相同数据还有缓存一致性协议。如果缓存数据查过cache line 那么当在单个核访问缓存时会先加总线锁(访问内存的总线)。排斥其他核进行访问。缓存行大小不固定,例如因特尔的缓存行是64字节。
缓存行对齐
对于有些特别敏感的数据,会存在线程高竞争的访问,为了保证不发生伪共享,可以使用缓存行对齐编程方式。
JDK7:disruptor:填充缓存行,保证这个变量单据占据一个缓存行。
JDK8:@Contended 需要加上JVM参数:-XX:RestrictContended才会生效。
超线程
一个ALU对应多个PC|Registers
存储器层次结构
CPU指令执行顺序
CPU同时执行多指令,执行的指令的顺序不是按顺序的,这种乱序叫做指令重排序。如果要从CPU级别来阻止指令重排序:
-
源语:会在指令之间加入内存屏障,使得读取暂定,不会多读取从而改变顺序。lfence(读屏障)、mfence(读写屏障)、sfence(写屏障),因特尔独有
-
汇编指令:(lock是锁内存子系统,所以范围很广)总线锁。基本都有该指令
-
JVM层级:JSR内存屏障。
指令重排序规则:
as-if-serial : 不管硬件什么顺序,单线程执行的结果不变,看上去像是serial
合并写技术(Write Combining)
为了提高写效率,CPU在写入L1的是时候,WC同时会写入L2。大小4字节
NUMA(Non Uniform Memory Access)
NUMA:分配内存会有限分配该线程所在CPU最近的内存。
操作系统
内核 Kenerl
分为微内核、宏内核:
微内核:弹性部署,5G,IoT(Integer of Thing)
宏内核:PC phone
CPU分不同指令级别
内核ring0级可以进行任何指令,读写修改内存等等,但是ring3只能用于计算。内核和内存同样可以操作CPU但是因为运行指令不同所以CPU可以根据指令来做区分,应用要运行ring0命令只能像内核进行申请访问。
进程 线程 纤程
进程和线程区别:
进程是操作系统分配资源的最小单位(资源是有很多,主要是内存空间),线程时操作系统执行调度的基本单位,线程共享进程的内存资源,没有自己独立的内存空间。Fiber(纤程):线程中的线程,用户态的线程,不用和内核打交道,所以纤程切换很快,完全由线程来管理。纤程实际上是把线程当做CPU,而且占用资源少,相比操作系统创建线程基础空间1M,Fiber只用1k。
目前支持纤程的语言有:Kotlin,Scala Go,Python(额外的类库)
进程
程序运行时序
构成
针对每个进程,操作系统都会为其分配独立的资源:独立的地址空间,内核数据结构(进程描述符),全局变量,数据段…
进程描述符:PCB(Process Control Block)
僵尸进程
父进程创建子进程后,会维护子进程的的一个PCB结构,子进程退出,由父进程释放,如果父进程没有释放那这时的子进程就是僵尸进程。僵尸进程实际不会占用资源,实际上占用的资源就只有进程描述符。
孤儿进程
子进程结束前父亲进程已经结束,孤儿进程会统一称为init的孩子,由一号进程维护。
进程调度
每个进程都有自己专属的调度方案,且可自定义。
抢占式:由进程调度器强制开始或停止某一进程的执行
非抢占式:除非占用CPU的进程主动退出,否则一直不退出
Linux内核进程调度
Linux 2.5使用O(1)调度策略,每个进程占用相同时间片进行计算,轮询所有进程。
LinuxL2.6使用CFS(Completely Fail Shcedule)完全公平任务调度策略,按照优先级分配时间片的比例,记录每个进程的执行时间,如果某个进程小于分配的比例,则在下次分配会进程补偿,优先执行。
进程类型
IO密集型,大部分时间用于等待IO
CPU密集型,大部分时间用于计算
进程优先级
实时进程>普通进程
实时进程使用SCHEDULE_FIFO和SCHED_RR(轮询,优先级相同情况下)
普通进程使用CFS
中断
中断控制器中还保存了中断向量表,其中保存了不同中断指令对应的操作。
中断分为硬中断和软中断,硬中断是由硬件发出信息从而中断cpu占用资源(主要是写入内存中固定的位置,再由内存中对应的软件进行处理),软中断则是由应用发起的中断,例如读写磁盘或者内存中的信息。但是现在的软中断已经不再使用系统函数来产生中断而是直接将中断命令放到硬件中,sysenter原语的汇编指令。
中断的指令都是在寄存器中保存,当有信号到cpu后会迅速的找到中断指令并执行。
缺页中断(异常):在需要用到数据页没有存储在内存中,产生中断,从磁盘中加载数据页,实际上是产生缺页异常,由内核进行处理并加载。
内存管理
1.分页:计算机中实际上是将内存分为无数个大小为4k的页框,把程序(硬盘上)分成4K大小得块,用到哪块加载那块, 也支持大分页。如果内存已满会将内存中最不常用的内存页放到交换分区(swap)中,再加载新的程序。使用LRU算法。
(LRU LeetCode 146)
2.虚拟内存,程序间使用的内存地址不再是真实的物理地址,而是虚拟地址,这样A进程永远不会访问到其他进程的地址。进程的虚拟空间就是寻址空间-64位系统就是2^64,比物理空间大很多,单位是位。进程是独享整个系统内存和CPU。
内存地址
线性地址实际上是将物理地址按端划分,在每段上的偏移量就是逻辑地址,在内存满后通过置换将其他内容置换到硬盘的交换空间中。内存映射是偏移量+段的基地址=线性地址。线性地址是通过OS+MMU(Memory Management Unit)硬件来进行管理映射的。
ZGC
算法:Colar Pointers,GC信息记录在指针上,不是记录在头上。
64位的寻址空间