《码农翻身》笔记

本文最后更新于:2022年6月13日 中午

通过拟人化的方式讲解了计算机中的很多较难理解的知识,内容覆盖面较广,且未太深入,读起来易理解

线程的切换

线程池等待cpu进行调度,每个线程只会被运行一段时间,然后切换到其它线程

死锁,两个线程相互等对方释放,出现死锁

按照资源的“大小”顺序来申请锁

tcp/ip

三次握手,分组交换,失败重传

缓存

缓存比内存和硬盘快

程序的局部性原理

时间局部性

当程序的某条指令被执行后,不久后可能再次被执行;如果某些数据被访问后,则可能会被再次访问

空间局部性

当访问一个内存单元后,过不久其附近的内存单元也可能被访问

通过这个原理可以将程序分块进行装载到内存中,不用一次性全部加载

将这一小块称为页框page frame,每页4kb大小

流水线

提前准备好其它事情类似于多辆车要洗车,打蜡

进程控制块

MMU 内存管理单元

地址的动态重定位

例如两个程序都操作了500的位置,第二个程序的起始地址就不是0,cpu操作时会先加上基址寄存器的指再去操作

分时系统

每个程序只会运行一段时间

虚拟内存:分页

给程序分配一块很大的虚拟内存,然后映射真实物理地址,操作系统维护一个页表来管理

如果访问到没有被映射到物理内存的页面,就会产生页中断,触发缺页处理程序,操作系统会再去硬盘中调取,把内容读取到内存,然后重新修改页表

分段

将程序进行分段

代码段

数据段

堆栈段

当程序访问非法内存的时候,操作系统会重新获得控制权,从而kill掉进程

程序在不断的运行中会分块加载到内存中,专业术语叫做分页

文件的存放

采用索引式存放,专门找一个磁盘块来记录文件的磁盘号,这样无论是顺序访问,还是随机访问就都很快了,缺点是这个索引块也要占空间

后面出现了inode的结构,里面不仅仅保存了磁盘块编号,还保存了权限,所有者,修改日期等,如果磁盘块的编号过多,可以使用间接块,指向另一个磁盘块,有一次间接块,二次间接块和三次间接块

为了防止在对文件的操作的同时出现了系统崩溃,在操作前操作系统都会先记录操作日志,重启时检查日志项,以查看哪一项未做,然后重新做一遍

操作日志(Journal) 文件系统

管理空闲块

链式法

位图法,给每个磁盘块通过01来标记是否被使用,这种方式简洁高效,节省空间

文件系统

有很多种类,如NTFS,FAT,Ext2,Ext3

例如 LInux Ext2 为例,文件系统在这个硬盘上的布局是有MBR(Master Boot Record) 和多个磁盘分区组成的, MBR中会记录引导代码和磁盘分区表,磁盘分区表会记录磁盘的起始位置,是否位活动分区,如果是互动分区,操作系统会找到它,然后进行载入

中断式I/O

例如在读取文件的过程中,cpu可以去执行其它进程,等文件读取完成,会发出一个中断信号,cpu会执行中断程序,然后来读取拿到的文件

在处理中断的过程中,有一个中断控制器,它会负责调度中断的优先级,然后分配给cpu处理

这是一种异步的,事件驱动的处理思想,在nodeajax中应用广泛

转换代码

  • 词法分析 生成tokens

  • 语法分析 生成ast语法数

  • 语义分析 检查代码是否编写正确,标识符类型,作用域是否正确,运算是否合法

  • 中间代码生成

  • 代码优化

  • 代码生成

线程锁

自旋锁,多个线程操作同一个共享变量的时候,操作系统会给他分配一个锁,只有获得这个锁,才可以对这个变量进行操作,与此同时,其它线程会不断的轮训来抢这把锁,除非它的时间片到了,必须让出cpu的执行时间。

问题:

如果函数出现递归,那么就会出现死锁,

函数第一次运行的时候申请到了锁🔐,然后递归再次运行自己,这时候锁已经被申请过了,所以第二次只能等待,轮训的去申请,这时候就出现了死锁

改进:

解决重入问题,每次申请的锁的时候记录一下是谁申请的,再用一个计数器来记录重入的次数,当这个持有锁的函数再次进入的时候把计数器+1,释放锁的时候也是一样的,把计数器-1,直到减为0

解决****占用问题:当其它线程尝试申请锁的时候,会把它放到队列中,不会再轮训的去申请锁了,等到锁被释放了,再通知这个线程去抢锁

信号量

再生产者,消费者模型中,可能会出现相互等待的问题,如消费者消费过快,需要等待生成者的数据,或者生成者过快,需要等待消费者消费完。

此时操作系统通过信号量来解决该问题

尾递归

当递归调用师函数体中最后执行的语句,并且它的返回值不属于表达式的任何一部分时,这个递归就是尾递归,有些语言的现代编译器会对这种代码进行优化,递归的时候不会生成新的堆栈帧,会复用堆栈。

js的Safari已经对尾递归进行了优化,但是其它浏览器都没有对其进行实现

事务

要么全部完成,要不一个不做

原子性 Atomicity

一致性 Consistency

隔离性 Isolation

持久性 Durability

简称ACID

幂等性

多次执行,不会有变化

互斥锁

同一时间只有获得锁的线程可以去操作共享的资源,其它线程会被阻塞,放在锁池(Lock Pool)中

采用不加锁的方式

  1. 线程读取值,如A

  2. 做完一系列操作

  3. 准备重新写入A,这时候会拿A和内存中的值进行比较,如果一致则写入,不一致则再次循环

  这一步是原子性操作,不会存在数据不一致的问题 compareAndSwap,简称CAS

java提供了一系列Atomic类,,针对对象的比较是比较引用,同时增加版本号,以解决删除后再次添加的问题

web

网络

非对称加密

我给A发消息的时候,用A的公钥进行加密,A收到后会用自己的私钥进行解密

A的公钥是公开的,地球人都知道

但是这种RSA的加密,解密速度太慢了

改进

先用加密的方式发送一个对称加密的私钥,后续的加密解密都采用这个对称加密的私钥,这个速度比之前快了百倍

redis

缓存一致性hash算法

余数算法

先对key进行hash,然后用这个结果对服务器的个数取余,这个弊端是,出现新增和删除集群的时候,缓存会出现问题

就近缓存

redis集群的服务器分布在类似时钟的环形上,当新增和删除服务器的时候只会影响一定区间的数据

hash槽

每台服务器管理固定区间的缓存,如果有新增服务器,则其他服务器可以将一部分数据交给它管理

故障转移

hash槽分组后,每组都有多台服务器(node),其中会有一台master,其它被称为salvemasterslave的数据是一样的,只是做了备份,如果master挂了slave会替换掉master,这里会用某种算法选出一个slave作为新的master

redis集群(cluster)会管理客户端发过来的请求,控制具体在哪个服务器获取数据

nginx高可用性

需要多台nginx服务器

通过keepalived形成master-slave的结构,当一台挂了,其它的会顶上, 对外暴露的是统一ip地址

mysql高可用性

也采用master-slave的架构

master主写,slave主读,实现读写分离,在这之上加一层中间层,来分发读写的操作,发到不同的数据库中


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。