操作系统
操作系统角色和功能
对接底层硬件和上层软件,作为一个沟通桥梁。
内核类型(微内核与宏内核)
微内核和宏内核区别是:微内核的用户空间和内核空间可能在不同的地址空间中,宏内核会在同一个地址空间中
进程定义与特性
进程是一次数据操作的资源分配的最基本单位
线程概念与优势
线程是系统运行的基本单位
进程与线程的区别
他们运行调度的单位不一样,能使用的资源也不一样。进程间是不共享资源的,而线程间共享资源。线程是进程的一部分,启动线程的开销小于进程的启动开销。进程有自己的资源空间,而线程会共享一个进程的资源空间。
进程生命周期管理
进程的整个生命周期有以下状态:
创建:进程正在被创建
就绪:进程创建完毕,等待CPU调度时间片
运行:进程正在CPU时间片上运行
等待/阻塞:进程因外部事件的发生而暂停执行
就绪挂起:进程时间片用完,等待下一段时间片到来被调度运行,并且已被移动到辅存
阻塞挂起:进程仍然处于阻塞状态,但是被移动到了辅存
终止:进程正在被回收资源
进程调度策略
FCFS:先到先运行
优先级分配:运行前设置进程的优先级,高优先级优先分配
时间片:每个进程都有一定的时间可以运行,时间片到达则需要挂起等待下一个时间片
短作业优先:优先调度运行时间短的进程,运行时间长的进程可能会饥饿
高响应:总和等待时间和运行时间进行分配优先级
多级轮转:每个进程都会先进一级优先级运行一段时间,然后被安排到二级优先级。每次运行会优先运行一级优先级进程,没有了才才会运行二级优先级进程。
一些进程种类
孤儿进程:被pid=1的init进程托管的进程
僵尸进程:信息没有同步完毕给父进程,就直接终止的进程。当信息同步完毕后,僵尸进程会回收
守护进程:在后台一直持续运行的进程
并发与并行计算
并发只要保证一批任务在一段时间里同时运行。一般使用的是分时复用。
并行指在多个核心上,一批任务在同一个时间点同时运行。
同步机制(锁、信号量、屏障)
锁:互斥锁、读写锁、乐观锁、悲观锁、死锁、活锁、CAS算法(自旋锁)
死锁的发生需要4个条件:互斥条件、占有且等待条件、循环等待、非抢占条件
活锁就是在出现竞争时,两边都释放条件,让对方优先使用,容易造成资源浪费
互斥锁是比较底层的锁,当一个线程占有了互斥锁,另一个线程尝试请求互斥锁会阻塞
读写锁与读写操作相关,读锁之间不影响,写锁会阻塞所有读锁和后续写锁
乐观锁适用于冲突较少:先修改共享资源,如果最后没有冲突,则提交成功。如果有冲突则提交失败。
悲观锁适用于冲突较多,但时间慢:互斥锁、读写锁、自旋锁都是。
CAS是compareAndSwap,一种底层的原子操作,先匹配指针的原值是否被修改,如果没有则进行交换指针,如果有修改,则返回失败。golang中还有类似其他的原子操作进行修改数值和指针,这些操作都是cpu指令操作,所以不存在锁和竞争,是线程安全的。
信号与信号量:
信号量是一种信号同步工具,一般分为P(wait)操作和V(signal)操作
信号一般用于通知进程,让进程自行决定运行特定的逻辑。SIGKILL和SIGSTOP是无法被捕获的
同步屏障:所有线程/进程都到达某点才能继续运行。线程协程中类似sync.WaitGroup。
死锁的成因与解决策略
死锁的发生需要4个条件:互斥条件、占有且等待条件、循环等待、非抢占条件
死锁的解决可以从3个点方向出发
死锁预防:在发生前,保证4个条件中的一个不满足。
死锁避免:在运行前,使用银行家算法对资源进行调优。
死锁解决:杀死其中一个进程。
进程间通信
FIFO: 命名管道
管道
信号
消息队列
共享内存
socket
分页和分段机制
为了解决整个程序装载到内存无法一次性找到一整块空间的问题。引入了分段和分页。
分段是将程序的不同部分拆分,按照虚拟内存和物理内存映射关系,放到不同的物理内存中。而分页则更为细分,由页号和页内偏移量决定。
分页置换算法:
FIFO
LRU: 最久未使用。链表+map:尝试map找到指定node,移动到链表头,没有则直接加入到链表头,并移除链表尾
时钟置换:时钟轮:一个页被访问,标志为1。需要置换的时,尝试轮询访问标志,如果为1置为0,如果为0则可以换页。
抖动问题:刚置换出的页,又被需要加载到内存
I/O多路复用
select: 数组遍历,每次从内核态拷贝FD,再遍历获取哪些IO可以进行操作。1024上限,轮询控制
poll: 链表遍历,由select演变而来,没有上限,轮询控制
epoll:红黑树组织,只有第一次FD操作需要拷贝,后续调用epoll_wait不拷贝。他是回调控制
使用边缘触发模式时,当被监控的 Socket 描述符上有可读事件发生时,服务器端只会从 epoll_wait 中苏醒一次,即使进程没有调用 read 函数从内核读取数据,也依然只苏醒一次,因此我们程序要保证一次性将内核缓冲区的数据读取完;
使用水平触发模式时,当被监控的 Socket 上有可读事件发生时,服务器端不断地从 epoll_wait 中苏醒,直到内核缓冲区数据被 read 函数读完才结束,目的是告诉我们有数据需要读取;
Reactor和Proactor
Other TODO
内存管理基础
虚拟内存与物理内存
内存分配算法
页面替换策略
文件系统的作用
文件操作与管理
中断与异常处理
系统启动与配置
安全性与保护机制