操作系统进程管理

267 阅读4分钟

系统调用

使进程从用户态陷入内核态, 在内核态进行特权指令的调用, 完成后再回到用户态.

这里需要两次CPU状态切换, 需要进行CPU上下文切换

CPU上下文切换

CPU上下文包括:

  1. 程序计数器
  2. CPU寄存器(高速缓存)

切换过程为:

  1. 保存CPU上下文
  2. CPU上下文切换到待执行的内核态指令位置
  3. 跳转到内核态运行内核程序
  4. 恢复CPU上下文, 切换到用户态

进程

操作系统维护进程表, 表项称为进程表项/进程控制块PCB, 该表项包含进程状态的信息:

  • 程序计数器
  • 堆栈指针
  • 内存分配状况
  • 打开文件的状态
  • 调度信息(优先级...)
  • ...

用来在进程重新调度运行时恢复

进程时计算机资源分配的单位, 将一组相关的资源集中在一起

进程中非线程的内容有:

  • 地址空间
  • 全局变量
  • 打开文件
  • 子进程
  • 即将发生的报警
  • 信号&信号处理程序
  • 账户信息

信号量

是一种语言需要支持的功能

down时信号量值-1

up时信号量+1

记录累计唤醒次数

更复杂的生产者消费者模型用full, empty, mutex实现

  • mutex表示互斥
  • full在缓冲区满时停止生产者
  • empty在缓冲区空时停止消费者

可能造成死锁

互斥量

用原子操作将互斥量的值置为0或非0

进程切换仅在时钟中断/其他中断时才会发生, 用关闭中断可以解决一定的并发问题, 但关闭中断是针对CPU核心的, 在多核处理器中其他核心依然可以被中断, 访问并发的变量

管程

为避免死锁发明的由过程,变量,数据结构构成的模块/软件

管程的数据结构只有在管程内的进程可以调用

管程通过判断变量值, 将请求的进程wait; 通过signal/notify将进程唤醒进入管程

synchronized就是管程的一种实现方式. synchronized是针对对象的, 对其中一个方法家里锁, 则不允许其它线程访问该对象的其它方法

消息传递

信号量是一种语言成分, 而消息传递是一种系统调用.

将send, receive系统调用方法加入库例程, 不同进程可以调用

屏障

所有进程达到屏障, 才可继续向下执行

共享内存

可以通过缓冲区/其他数据结构实现, 还可以是共享文件

线程

线程是运行在进程上文中的程序流.

线程上下文包括:

  • 线程ID
  • 栈指针
  • 程序计数器
  • 通用寄存器
  • 条件码

线程出现的原因

  • 共享地址空间和数据
  • 更轻量, 切换上下文简单
  • 同一任务可分为不同线程, 对同一组数据进行操作

线程的地址空间不互相隔离, 每个线程可以读写另一个线程的堆栈

线程创建

进程从单个线程开始, 该线程可创建新的线程, 通常线程间不存在父子关系而是平等的

线程运行

  • create
  • exit
  • join 阻塞, 直到另一线程exit
  • yield 主动放弃CPU(由于线程不会被中断强制让出CPU, 因此可通过这种方式调度)

用户空间线程

POSIX线程是IEEE定义的UNIX线程标准, 其线程包为Pthread. 目的时实现可移植的线程

用户空间线程由用户管理, 每个进程需要有专用的线程表, 可使用进程专有的线程调度算法

内核空间线程

内核中有记录所有线程的线程表, 不需进程记录.

线程创建通过系统调用完成, 对线程阻塞也需要系统调用, 代价更高

但不需自己实现新的非阻塞的系统调用

混合实现线程

使用内核线程, CPU对其进行调度

在用户空间将多个用户级线程多路复用到一个内核线程上