现代操作系统 进程管理
待更新,还没写完。
进程与线程
进程
- 独立的虚拟地址空间
进程的状态
-
新生状态:进程刚被创建
-
预备状态:正在准备队列,可以被调度执行
-
运行状态:正在cpu核上运行
-
阻塞状态:进程需要等待外部事件,无法被调度
-
终止状态:进程完成了执行,不会再被调度
子进程终止到被父进程wait回收的期间为僵尸进程
PCB
保存了进程标识符,内存,file_table,context
linux API for managing process
fork
- 虚拟内存空间独立,但复制了fd table指向的是相同的文件抽象,而偏移量是记在这个抽象里的
- 父子进程默认属于一个进程组,可以向进程组内所有进程发送信号。
第一个kernel process : kthreadd
-
缺点:粗暴拷贝,性能差(在没有COW前),不可组合
-
父进程使用
wait
来
exec
线程
为什么要有线程?
- 创建进程的开销大
- 进程间的数据共享同步麻烦
进程线程的最大区别:地址空间的共享不同
线程是操作系统调度和管理程序的最小单位
线程的地址空间
用户态与内核态
用户态线程不受内核态管理,创建开销小。其系统调用需要内核态线程协助完成。
TCB
- 内核态TCB:与PCB结构类似,上下文切换时使用
- 用户态TCB:pthread结构体,是内核态的扩展,拥有本地存储TLS
线程的操作
- 创建:pthread_create(),其中创建应用态线程还会创建TLS
- 合并:pthread_join
- 退出:pthread_exit 线程在执行完任务后会隐式调用
- 暂停:pthread_yield 让出CPU资源,比如其在等待io
线程的上下文
常规寄存器 程序计数器 栈指针 条件码
上下文切换过程:
- 用户栈到内核栈
- 保存上下文到内核栈
- 切换内核栈
- 从内核栈恢复上下文
- 内核栈到用户栈
纤程
- 一个内核线程对应多个纤程
- 上下文切换不用进内核
- 允许用户态自主调度
- 协程是程序语言对纤程的支持
进程/线程调度
调度器在准备队列上调度一个任务到一个CPU核上运行一段时间
- 调度:协调请求对于资源的使用
- 不同调度需求:throughput, response time, scalability, low cost, real-time(截止时间要求)
调度策略
RR
-
过长->趋近于FCFS
-
过短->切换开销大
优先级翻转
-
概念:低优先级任务占用资源->高优先级任务被阻塞
-
解决方法:优先级继承
然而,multi-tenant 环境下,CPU应对不同tenant的时间公平,而非对任务公平-
Lottery Scheduling
生成一个随机数,看在什么区间
-
Ticket transfer: 应用程序将手中ticket交给服务端,确保服务端可以尽快执行
-
Stride Scheduling : ticket越大stride越小,每执行一个程序增加其pass 每次执行pass小的
多核调度策略
追踪负载