首页 > 代码库 > Chapter 1:进程和线程

Chapter 1:进程和线程

1.1 进程

操作系统中最核心的概念是进程:这是对正在进行程序的一个抽象。操作系统的其他所有内容都是围绕着进程的概念展开的。

进程是操作系统提供的最古老的也是最重要的抽象概念之一。没有进程的抽象,现代计算将不复存在。

1.1.1 进程模型

一个进程就是一个正在执行程序的实例,包括程序计数器,寄存器和变量的当前值。从概念上说,每个进程都拥有它自己的虚拟CPU。

由于CPU在各进程之间来回快速切换,所以每个进程执行其运算的速度是不确定的。而且当同一进程再次运行的时候,其运算速度也是不可再现的。所以,在对进程编程时决不能对时序做任何确定的假设。

关键思想:一个进程是某种类型的一个活动,它有程序,输入,输出以及状态。单个处理器可以被若干进程共享,它使用某种调度算法决定何时停止一个进程的工作,并转而为另一个进程提供服务。

1.1.2 创建进程

操作系统需要有一种方式来创建进程。有4种主导事件:

1,系统初始化

2,执行了正在运行的进程所调用的进程创建系统调用

3,用户请求创建一个新进程

4,一个批处理作业的初始化

从技术上看,在所有这些情形中,新进程都是由于一个已存在的进程执行了一个用于创建进程的系统调用而创建的。在UNIX系统中,只有一个系统调用可以用来创建新进程:fork。

1.1.3 进程的终止

永恒是不存在的。终止通常由下列条件引起:

1,正常退出。自愿的。

2,出错退出。自愿的。

3,严重错误。非自愿。

4,被其他进程杀死。非自愿。

1.1.4 进程的层次结构

在UNIX中,进程和它的所有子女以及后裔共同组成一个进程组。

在Windows中,没有进程层次的概念。所有的进程都是地位相同的。

1.1.5 进程的状态

尽管每个进程是一个独立的实体,但进程之间经常要相互作用。一个进程的输出结果可能作为另一个进程的输入。

当一个进程在逻辑上不能继续运行时,它就会被阻塞。一个概念上能够运行的进程被迫停止,因为操作系统调度另一个进程占用了CPU。这两种情况是完全不同的。所以进程一般来说有三种状态:

1,运行态。该时刻进程实际占用CPU

2,就绪态。可运行,但因为其他进程正在运行而暂停止

3,阻塞态。除非某种外部事件发生,否则进程不能运行

这三种状态有四种可能的转换。进程调度程序是操作系统的一部分,进程甚至感受不到调度程序的存在。调度程序的主要工作就是决定应当运行哪个进程,何时运行以及它应该运行多长时间。

1.1.6 进程的实现

为了实现进程模型,操作系统维护着一张表格(一个结构数组),即进程表process table。每个进程占用一个进程表项。

所有的中断都从保存寄存器开始。

1.1.7 多道程序设计模型

采用多道程序设计可以提高CPU的利用率。

1.2 线程

1.2.1 线程的使用

只是在有了多线程的概念之后,我们才加入了一种新的元素:并行实体共享同一个地址空间和所有可用数据的能力。对于某些应用而言,这种能力是必需的,而这正是多进程模型所无法表达的,因为它们没有相同的地址空间。

第二个需要多线程的理由:由于线程比进程更轻量级,所以它们比进程更容易创建,也更容易撤销。创建一个线程较创建一个 进程要快10-100倍。

三,多线程可以加快应用程序执行的速度。

四,在多CPU系统中,真正的并行有了实现的可能。

1.2.2 经典的线程模型

进程模型基于两种独立的概念:资源分组处理与执行。进程用于把资源集中到一起,而线程则是在CPU上被调度执行的实体。线程之间是没有保护的,不可能,也没有必要。线程概念试图实现的是,共享一组资源的多个线程的执行能力,以便这些线程可以为完成某一任务而共同工作。

每个线程都有其自己的堆栈。通常每个线程会调用不同的过程,从而有一 个各自不同的执行历史。

1.2.3 POSIX线程

1.2.4 在用户空间中实现线程

最明显的优点是,用户级线程包可以在不支持线程的操作系统上实现。在用户空间管理线程时,每个线程需要有其专用的线程表。

不需要陷阱,不需要上下文切换,也不需要对内存高速缓存进行刷新,这就使得线程调非常快捷。

用户级线程允许每个进程有自己定制的高度算法。

存在问题:

1,如何实现阻塞系统调用?

2,如果一个线程开始运行,那么在该线程中的其他线程就不能运行,除非第一个线程自动放弃CPU。

1.2.5 在内核中实现

2.2.6 混合实现

2.2.7 调度程序激活机制

调度程序激活工作的目标是模拟内核线程的功能,但是为线程包提供通常在用户空间中才能实现的更好的性能和更大的灵活性。调度激活机制的一个目标是作为上行调用的信赖基础。

2.2.8 弹出式线程

一个消息的到达导致系统创建一个处理该消息的线程,就叫做弹出式线程。使用的结果是消息到达与处理开始之间的时间非常短。

2.2.9 使单线程代码多线程化

Chapter 1:进程和线程