NoteDeep
从职责划分来看,进程是一种主存资源的管理和调度,线程主管cpu的执行。系统管理着多项任务(进程),多个任务并不是共同执行的,而是轮流在执行,每次任务的切换都会保存当前任务的上下文,加载下个任务的上下文,然而线程的执行共享相同的上下文环境。
从粒度大小来看,一个进程管理着整个任务,多个线程共同管理一个任务,所以进程是线程的超集。个人认为这个超集概念不是很合理,用管理者和员工的关系来形容更合适,但超集二字更方便读者去描述这种微妙关系。


进程和线程简单而基本靠谱的定义如下:
1. 进程:计算机资源的基本调度单位
2. 线程:CPU的基本调度单位
这两个概念虽然过于简单,但是完全可以为理解OS/线程/进程打下坚实的基础。

进程是系统权限的集合。进程是资源调度,线程是执行调度。
线程是 CPU 调度的最小单位。

在CPU看来,所有的任务都是一个一个轮流执行的,一个任务可以被CPU执行,说明它所申请的除了CPU以外的所有资源,都已经获得。这里除了CPU以外的所有资源构成程序的执行环境,也称为程序的上下文。
一个进程的处理过程是:加载上下文—>CPU执行—>保存上下文
进程的切换,也是同样的处理过程,每次都要加载上下文和保存上下文。这样每次的调入、调出,对系统来说,是会造成一定的开销的。于是就引入了“线程”这个概念,一个进程可以分为一个或多个线程,这些线程共享一样的上下文,也就是说,属于同一个进程的线程之间的切换,就少了加载/保存上下文,开销减少,效率就提高了。
进程是资源分配的最小单位,在没有引入线程以前,进程既是最小资源分配单位,也是最小调度单位。后来引入了线程,最小调度单位就是线程,资源分配和调度分开了,目的是为了更好的利用CUP。


抛开各种技术细节,从应用程序角度讲:

1、在单核单线程计算机里,资源是无法被cpu并行访问的。

没有操作系统的情况下,一个程序一直独占着全部cpu。

如果要有两个任务来共享同一个CPU,程序员就需要仔细地为程序安排好运行计划--某时刻cpu和由程序A来独享,下一时刻cpu由程序B来独享

而这种安排计划后来成为OS的核心组件,被单独名命为“scheduler”,即“调度器”,它关心的只是怎样把单个cpu的运行拆分成一段一段的“运行片”,轮流分给不同的程序去使用,而在宏观上,因为分配切换的速度极快,就制造出多程序并行在一个cpu上的假象。

2、为了提高程序运行的效率,内存是必不可缺的。(内存的内容也是保存在物理存储器上的,只是存取速度很快)在计算机里,同一资源如果被多个进程共用,那么为了合理使用共享资源,资源会被复制成不同的副本存储在内存中,这涉及到内存对应的物理存储器的资源分配,也就是说需要一组特定的物理层api来控制存储器的空间分配。(在一个没有内存管理组件的操作系统上,程序员需要手工为每个进程安排运行的空间 --进程A使用物理地址0x00-0xff,进程B使用物理地址0x100-0x1ff,等等)

然而这样做有个很大的问题:每个程序都要协调商量好怎样使用同一个物理存储器上的不同空间,然而计算机硬件千差万别种类繁多,一款适配所有的硬件的程序几乎是不存在的,这使得这种定制的方案没有可行性。
为了解决这个麻烦,计算机系统引入了“虚拟地址”的概念来实现软硬件分离的分层思想,从三方面入手来做:

1)硬件上,CPU增加了一个专门的模块叫MMU,负责转换虚拟地址和物理地址。
2)操作系统上,操作系统增加了另一个核心组件:memory management,即内存管理模块,它管理物理内存、虚拟内存相关的一系列事务。
3)应用程序上,发明了一个叫做【进程】的模型,(注意)每个进程都用【完全独立的】虚拟地址空间,然而经由操作系统和硬件MMU协作,映射到不同的物理地址空间上。不同的【进程】,都有各自独立的物理内存空间,不用一些特殊手段,是无法访问别的进程的物理内存的。

3、现在,不同的应用程序,可以不关心底层的物理内存分配,也不关心CPU的协调共享了。然而还有一个问题存在:一个进程中某些程序可能运行时长比较长,然而cpu也一直盲等待,所以其他程序想要在该进程中共享CPU,这时候,一个叫【线程】的模型就出现了,它们被包裹在进程里面,在调度器的管理下共享CPU,拥有同样的虚拟地址空间,同时也共享同一个物理地址空间,然而,它们无法越过包裹自己的进程,去访问别一个进程的物理地址空间。

4、进程之间怎样共享同一个物理地址空间呢?不同的系统方法各异,符合posix规范的操作系统都提供了一个接口,叫mmap,可以把一个物理地址空间映射到不同的进程的上下文中,由不同的进程来共享。

PS:在有的操作系统里,进程不是调度单位(即不能被调度器使用),线程是最基本的调度单位,调度器只调度线程,不调度进程,比如VxWorks

文档仍然说到:Threads are scheduled globally across all processes.即调度的基本单位是线程,不是进程。调度器在调度任务时,只知道线程,不知道进程这个东西,对于进程的管理,是OS别的组件的事情。

评论列表

  • jianle
    jianle

    我提交了一个修改,麻烦查看下哟~  2018年5月24日 16:32