Post

操作系统

操作系统

操作系统角色和功能

对接底层硬件和上层软件,作为一个沟通桥梁。

内核类型(微内核与宏内核)

微内核和宏内核区别是:微内核的用户空间和内核空间可能在不同的地址空间中,宏内核会在同一个地址空间中

进程定义与特性

进程是一次数据操作的资源分配的最基本单位

线程概念与优势

线程是系统运行的基本单位

进程与线程的区别

他们运行调度的单位不一样,能使用的资源也不一样。进程间是不共享资源的,而线程间共享资源。线程是进程的一部分,启动线程的开销小于进程的启动开销。进程有自己的资源空间,而线程会共享一个进程的资源空间。

进程生命周期管理

进程的整个生命周期有以下状态:

  • 创建:进程正在被创建

  • 就绪:进程创建完毕,等待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

  • 内存管理基础

  • 虚拟内存与物理内存

  • 内存分配算法

  • 页面替换策略

  • 文件系统的作用

  • 文件操作与管理

  • 中断与异常处理

  • 系统启动与配置

  • 安全性与保护机制

This post is licensed under CC BY 4.0 by the author.