关于进程和线程,大家总是说的一句话是“进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元”。这句话理论上没问题,我们来看看什么是所谓的“资源”呢。
什么是计算机资源
经典的冯诺依曼结构把计算机系统抽象成 CPU + 存储器 + IO,那么计算机资源无非就两种:
1. 计算资源
2. 存储资源
CPU是计算单元,单纯从CPU的角度来说它是一个黑盒,它只对输入的指令和数据进行计算,然后输出结果,它不负责管理计算哪些”指令和数据“。 换句话说CPU只提供了计算能力,但是不负责分配计算资源。
计算资源是操作系统来分配的,也就是常说的操作系统的调度模块,由操作系统按照一定的规则来分配什么时候由谁来获得CPU的计算资源,比如分时间片
存储资源就是内存,磁盘这些存储设备的资源。在这篇计算机底层知识拾遗(一)理解虚拟内存机制 我们说了操作系统使用了虚拟内存机制来管理存储器,从缓存原理的角度来说,把内存作为磁盘的缓存。进程是面向磁盘的,为什么这么说呢,进程表示一个运行的程序,程序的代码段,数据段这些都是存放在磁盘中的,在运行时加载到内存中。所以虚拟内存面向的是磁盘,虚拟页是对磁盘文件的分配,然后被缓存到物理内存的物理页中。
所以存储资源是操作系统由虚拟内存机制来管理和分配的。进程应该是操作系统分配存储资源的最小单元。
再来看看线程,理论上说Linux内核是没有线程这个概念的,只有内核调度实体(Kernal Scheduling Entry, KSE)这个概念。Linux的线程本质上是一种轻量级的进程,是通过clone系统调用来创建的。何谓“轻量级”会在后面细说。进程是一种KSE,线程也是一种KSE。所以“线程是操作系统调度的最小单元”这句话没问题。
什么是进程
进程是对计算机的一种抽象,
1. 进程表示一个逻辑控制流,就是一种计算过程,它造成一个假象,好像这个进程一直在独占CPU资源
2. 进程拥有一个独立的虚拟内存地址空间,它造成一个假象,好像这个进程一致在独占存储器资源
线程的性质:
1.线程是进程内的一个相对独立的可执行的单元。若把进程称为任务的话,那么线程则是应用中的一个子任务的执行。
2.由于线程是被调度的基本单元,而进程不是调度单元。所以,每个进程在创建时,至少需要同时为该进程创建一个线程。即进程中至少要有一个或一个以上的线程,否则该进程无法被调度执行。
3.进程是被分给并拥有资源的基本单元。同一进程内的多个线程共享该进程的资源,但线程并不拥有资源,只是使用他们。
4.线程是操作系统中基本调度单元,因此线程中应包含有调度所需要的必要信息,且在生命周期中有状态的变化。
5.由于共享资源【包括数据和文件】,所以线程间需要通信和同步机制,且需要时线程可以创建其他线程,但线程间不存在父子关系。
进程与线程之间的关系
从一定意义上讲,进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行。
在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统内多个程序间并发执行的程度。
多线程使用的情形:
前台和后台工作情况;
异步处理工作情况;
需要加快执行速度情况;
组织复杂工作的情况;
同时有多个用户服务请求的情况等。
线程机制的优点:
多线程运行在同一个进程的相同的地址空间内,和采用多进程相比有以下优点:
1.创建和撤销线程的开销较之进程要少。创建线程时只需要建立线程控制表相应的表目,或有关队列,而创建进程时,要创建PCB表和初始化,进入有关进程队列,建立它的地址空间和所需资源等。
2.CPU在线程之间开关时的开销远比进程要少得多。因开关线程都在同一地址空间内,只需要修改线程控制表或队列,不涉及地址空间和其他工作。
3.线程机制也增加了通讯的有效性。进程间的通讯往往要求内核的参与,以提供通讯机制和保护机制,而线程间的通讯是在同一进程的地址空间内,共享主存和文件,无需内核参与。