cpu组成
结构:
1.寄存器:
1)通用寄存器:存放需要运算的数据
2.控制单元
1)程序计数器:存储cpu要执行的下一条指令的地址(在内存中)
2)指令寄存器:存放程序计数器指向的指令
3.逻辑运算单元:进行逻辑运算
cpu处理过程
三步:1.取2.运算与执行3.自增
如何程序跑的更快
程序执行时间 = 时钟周期时间*指令周期数
cpu缓存
Cache(掉电丢失)高速缓冲:1.数据缓存,指令缓存2. 单核独有 3.多核缓存共享
cpu访问数据
1.逐级访问
如何让cpu跑的更快
核心:尽可能让cpu在cache中读取数据
怎么做:提高缓存命中率
原理:cache每次从内存中读取缓存块,大小位64字节(不够补满,多了再来一块)。
那么,cache是以缓存块存储,怎么找到具体数据?
组标记,cpu Line索引,偏移量,有效位
具体四步骤:1.取程序计数器中的内存地址信息得到cpu索引。
2.判断有效位是否有效
3.判断内存中组地址与组标记是否相同
4.在内存地址中通过偏移量读取字。
提高命中率
提高缓存命中率:顺序存储,提前缓存。
提高指令命中率:分支预测器(经常性执行一条件,cpu会自动缓存指令)
提升多核cpu缓存命中率(避免切换cpu后,出现高速缓存不匹配,将cpu和线程绑定)
除了读数据以外,还有将数据从cpu写回内存
写直达:每改一次数据就访问内存并写入。(频繁访问内存时间开销过大)
写回:(第一次修改,只修改寄存器的值(并做标记),(有标记)第二次修改数据,我才访问内存)
为了提高cpu效率,才用写回带来的问题
多核多线程时带来的缓存一致性问题:我已修改的数据还没写入内存,另一个线程读取了我的旧数据,生成错误结果。
解决缓存一致性问题的思想
1.写传播:既然是由其他核不知道,数据以修改引起的,那我就每次修改后,广播给其他核(通过总线嗅探),其他核收到后,更改L1cache中的对应缓存。
2.事务的串形化:不仅要知道变了,还得知道是怎么变的(先后顺序,最后是谁留下)
具体解决缓存一致性的方法MESI协议
1.Modified,已修改:我修改的数据被我自己标为已修改
2.Exclusive,独占:这个数据只有我自己有
3.shared,共享:这个数据大家都有了
4.invalidated,已失效:有人修改了这个数据,读时,需要去内存
四种状态的转换,其两两相互对立
两种情况的转换:1.从内存中读数据2.修改内存中的数据
读时:其他核没有是独占,有是共享,有修改(先把修改写入内存)再读与修改一同变共享
写时:独占直接修改,修改直接更新内存,共享修改后(其余都变失效)
伪共享问题:让cache的缓存作用失去了效果
解决:宏定义
cpu如何选择线程
调度算法:1.公平调度 = 运行时间+1/权重
权重:由nice通过转换表而来,nice越小权重越大。
nice:是优先级,越小优先级越高,范围-20到19
中断
上半部分硬中断:硬件触发,快速处理。
下半部分软中断:内核触发,异步完成上半部分未处理的工作。
linux中指令:/proc/softirqs
watch -d cat /proc/softirqs 实时查看。
原码,反码,补码
为什么负数用补码表示?
为了统一正数与负数的加减操作
计算机怎么存小数?
浮点数:符合位,指数位,尾数位。
linux内核理念
MultiTask,多任务:多个任务可以同时并发或并行
SMP,对称多处理:多个cpu地方相当,权限相同,每个程序被任意分配处理
ELF,可执行文件链接格式:
宏内核:是一个完整可执行程序,有最高权限,有所有模块:进程调度,内存管理,文件系统,设备驱动。
为什么要有虚拟内存?
如单片机直接操作内存物理地址时,只能运行一个程序,不同程序同时运行时可能存在数据覆盖。
操作系统如何解决这个问题?
每个进程都有自己独立的虚拟地址空间,通过操作系统将虚拟地址交错映射到物理地址上
即:通过cpu中的内存管理单元MMU的映射关系,转变成物理地址,再通过物理地址访问内存。