天天看点

<<程序是怎么跑起来的>>学习笔记总结一<<程序是怎么跑起来的>>学习笔记总结

<<程序是怎么跑起来的>>学习笔记总结

1. 背景

  1. 作为IT行业从业者,跨行而来,也有6 7年了,虽然一直都有加强基础学习,但学而时习之.不断巩固复习是有很大帮助的,而且经典书常看常新,每次学习,都有不同的感悟.
  2. 计算机基础,其实有几门关键的课程:

操作系统

计算机组成原理

计算机网络

数据库原理

编译原理

数据结构与算法

C语言

汇编语言

java

设计模式

软件工程

数字图像处理

音视频技术

分布式计算

人工智能

2. 总结

  1. 本书<<程序是怎么跑起来的>>是一个日本人编写的,可以看做是计算机组成原理或者是计算机概论的白话版本
  2. 按照学习方法论里面的,如果能够将深奥的原理以简单直白方式描述出来,别人可以很快听懂,那才说明掌握了.这本书就是以这个思路进行编写的,后续大家有意,可以看一下,其实日本出了很多白话版本,图解版本的计算机专业书籍,其实是非常不错的思路. 就跟现有很多技术和框架一样,最终都是让使用者方便,而把复杂细节屏蔽,当需要时再去深入即可.

2.1 CPU是什么

  1. CPU, 全称central processing unit,中央处理器
  2. CPU负责执行机器语言中的一条一条的指令
  3. 内部由寄存器,控制器,运算器,时钟组成.

寄存器是存放数据和指令(指令本身也是数据)

控制器是控制指令执行的, 负责把内存上指令和数据读入寄存器

时钟可以看成是触发器

运算器才是真正执行指令的地方, 负责运行寄存器中的数据

  1. 内存, 一般也称之为主存
  2. 汇编和反汇编, 汇编语言中助记符
  3. 高级语言->汇编语言->机器语言, 计算机只能执行机器语言, 而C,Java, Python等都是高级语言,最终需要转化为机器语言. 汇编语言可以看成是更细粒度的语言,可以让开发者对代码执行过程有更细致的认识.也更加方便问题定位和性能优化
  4. 寄存器划分

累加寄存器, accumulator register, 存储运算的数据和运算后的数据 (1个)

标志寄存器, flag register, 存储运算处理后的CPU状态 (1个)

程序计数器, program register, 存储下一条指令所在内存的地址 (1个)

基址计数器, base register, 存储数据内存的起始地址

变址寄存器, index register, 存储相对基址寄存器的地址

通用寄存器, general purpose register, 存储任意数据

指令寄存器,instruction register, 存储指令,CPU内部使用,程序员无法控制 (1个)

栈寄存器, stack register, 存储栈区域的起始地址 (1个)

  1. 对于程序员来说, CPU可以看做是寄存器的集合体
  2. 程序运行,需要将程序从硬盘中加载到内存中才行
  3. 代码中的判断,循环,跳转等逻辑,最终会落地到寄存器的处理和动作,如标志寄存器, 跳转指令,call 指令等等
  4. 基址寄存器和变址寄存器,这其实是因为代码编译时,代码调用和变量等都会有一个地址值(相对的),但加载到内存后,会有一个真实地址值,这时候将这个真实其实地址值和相对值组合,就可以得到程序实际运行时变量,函数调用时的真实地址值.
安卓和iOS的崩溃解析就是运用了这个原理,可以得到代码崩溃时,具体崩溃在哪一行(程序运行时知道崩溃代码的真实地址, 代码编译打包时得到相对地址信息, 2相比较处理,就可以得到是哪一行代码崩溃了)
  1. CPU指令类型

数据转送指令, 寄存器和内存, 内存和内存,寄存器和外围设备之间的数据读写操作

运算指令, 用累加寄存器执行算数运算, 逻辑运算, 比较运算, 移位运算

跳转至零, 实现条件分支, 循环, 强制跳转等

call/return指令, 函数调用,返回的操作

2.2 数据和二进制

  1. 原码, 反码, 补码
  2. 整数int和浮点数float 默认都是4字节, 32bit位
  3. IC也就是集成电路,因为高低电压比较好实现, 所以机器运行以2进制, 0 1实现. 软件和硬件对应比较匹配.
  4. 二进制, 位权的概念
  5. 移位运算和乘除的关系, 二进制则是2的指数,具体看左移还是右移.

逻辑位移, 就是类似霓虹灯滚动效果,不是数字计算,一般图形场景较多

算数位移,涉及到计算

与,或,非,异或
  1. 数据类型,一个是节约内存资源,一个是可以做类型检查

2.3 计算机和浮点数

  1. 浮点数表示方式:
符号 尾数 * 基数(指数次幂)
  1. 表示案例

1011.0011

分别对应:

8=12^3

0 =02^2

2 =12^1

1 =12^0

0 =02^-1

0 =02^-2

0.125 = 1* 2^-3

0.0625=1*2^-4

上述可以看出,其实浮点数表示方法只能近似而无法精确表示一个小数. 这也是为什么说浮点数需要一个精度的原因,就是表示这个数字需要的近似程度

  1. 浮点数实际表示,因为基数固定就是2, float是32位bit表示,double是64位bit表示; 也就是说符号, 尾数, 指数这三部分组成了32位或者64位浮点数.

64位浮点数: 符号部分1位, 指数部分11位, 尾数部分52位

32位浮点数: 符号部分1位,指数部分8位, 尾数部分23位

  1. EXCESS表示方式

小数点前面是0, 小数点后面第一位不能是0

0.75十进制数,表示为0.75*10^0

将指数部分表示范围的中间值设为0, 使得负数不需要用符号来表示

  1. 浮点精度问题应对:
  1. 无视,一些场景下,精度丢失可以接受
  2. 转为整数进行计算
  3. 使用类似BCD,java的big decimal等方式都是可以应对的

2.4 如何使用内存

  1. 目前计算的数据存储,外层可以是磁盘,中间就是内存,再进一步就是CPU高速缓存
  2. 内存是CPU可以访问的最大数据存储源,所以磁盘中数据为了能够让CPU访问,一般都需要加载到内存中.
  3. 内存硬件:

电源, 地址信号, 数据信号, 控制信号,

VCC, GND是电源引脚

A0-A9是地址信号引脚

D0-D7是数据信号引脚

RD, WR是控制信号引脚(读和写)

这里地址信号是0–9,是个,2^10次方,就是1024bit位,1kb的内存存储

  1. 内存使用的最小单位是1字节,也就是8bit位
  2. 指针其实就是数据的内存地址,表示数据存放在内存中的地址值

由此而来,大家可以引申出对数组,链表,队列,栈,二叉查找树等等的理解了

队列其实就是用环形缓冲区实现–对比一下hadoop shuffle中的环形缓冲区,是否可以关联起来了呢?

链表则是一个一个的节点串联,节点之间地址不用连续. 单向链表,双向链表,环等

二叉查找树, 可以对照二分查找数组,但数组的插入删除不方便,改为二叉数. 如果需要应对最坏情况,改为平衡树, B+树其实就是二叉平衡树

2.5 内存和磁盘

  1. 所有程序都需要读取到内存中才能运行
  2. 内存中数据断电丢失,硬盘中数据不会
  3. 磁盘缓存和虚拟内存

磁盘缓存,就是讲一部分内存当做磁盘的缓存,这一部分数据直接在内存中,读取时不需要去磁盘中加载,速度更快

虚拟内存,就是一部分磁盘空间当做内存,这样可以极大增加可用内存空间,但涉及到内存数据交换和更新机制

缓存机制涉及到现在java web开发以及大数据开发各个方面,可以说未来缓存技术还会不断发展和壮大.典型的如redis,各个内存数据库等

虚拟内存有分页和分段,windows采用分页方式,这样一些内存中数据以页为单位跟磁盘中数据做交换更新. 一页数据是4KB

  1. 内存节约解决思路
DDL,dynamic link library, 动态链接库. 就是讲各个程序共有的部分抽离出来,这样就不用加载到内存中的程序文件每个都包含这些公共部分. 这一点在iOS, 安卓设备中尤其常见,因为早期移动设备包括现在配置都无法和桌面设备的配置比较,所以更加注重这一块
  1. 磁盘物理结构:

磁盘划分:扇区, 可变长.目前一般都是扇区方式

扇区: 将磁盘看成一个个同心圆, 这些同心圆就是磁道,把磁道按照一定大小划分,就是扇区.这是因为磁头读取数据如果要切换位置,是机械运动,而这种操作是需要尽量避免的.

所需磁盘会有随机读写和顺序读写十倍甚至百倍级别性能差异的原因

windows对扇区做了进一步包装,整数倍的扇区就是簇,一般是512KB. 不管多小文件,最小也会占用一个簇.

扩展一下,小文件之所以读写慢就是因为如果分散在不同扇区中,磁头就需要做更频繁的物理运动来切换扇区,所以小文件和大文件读写和传输性能差异是非常明显的.

2.6 数据压缩

  1. 数据是以01方式表示保存在计算机存储介质中如内存,磁盘. 而为了有限空间保存更多数据,发明了数据编码,发明了压缩算法
  2. 压缩分为可逆压缩和不可逆压缩,顾名思义,可逆压缩就是压缩后数据可以解压缩回原始数据,不可逆则不可返回
  3. 数据压缩思路:

行程长度编码算法,就是计算数据连续重复出现多少次,记录下对应次数(RLE, run length encoding)

哈夫曼编码,关键思路就是频繁出现的用小于8位编码表示,不常出现的则可以用大于8位编码.(最后都是8的倍数来表示)

哈夫曼可以为各个文件单独构造编码体系,所以哈夫曼压缩后数据是2部分,一个是哈夫曼编码信息,一个是压缩后数据文件

将字符或者其他最小信息单位,按照最高频到最低品排序,出现次数.将最小出现次数的2个连接起来,对次数求和,然后从后往前推进.超过2层按照一样规则推进.

最后就可以得到一个哈夫曼树,左边树连线标记0, 右边树连线标记1,从顶部到对应数据的连线上数字就是对应的哈夫曼编码

  1. 图形数据压缩:

图形数据分为静态和动态,静态就是一张图,动态就是连续图–视频

静态数据可以使用各类图片格式对应的压缩算法进行压缩

动态数据则可以使用各类视频格式对应压缩算法压缩

  1. 不同类型数据的压缩算法都有对应较优的方式,但没优一种压缩算法适合所有类型数据的并保证较优的.

继续阅读