「OS」万年难题之进程与线程的联系和区别

所有接触过进程和线程概念的人,相信都思考过或者被问到过这个问题,进程和线程有什么区别?

大家也一定看到过很多种说法,其中大致可以归纳出这样的结论:
– 进程是操作系统对一个运行中程序的一种抽象,是计算机中的程序关于某数据集合上的一次运行活动,进程是系统资源分配的最小单位。
– 线程是进程中的运行控制流,是系统资源调度的最小单位,一个进程可以有多个线程,但一个线程只能属于一个进程。

上面的说法看起来很简单,实际上包含了许多内容,需要我们细细的去品味。

对于计算机来说,它是由各种软硬件资源组成的,按照冯·诺依曼结构来看,我们可以吧计算机资源抽象CPU+存储器+IO,那么计算机中的资源可以分为两类
– 存储资源
– 计算资源

其中,CPU自然是计算资源(当然,CPU中也包含寄存器、缓存等 储存资源,不过一般寄存器和cpu计算核心是协同调度的,这里我们不将他们分割开来),而计算资源是由系统调度的,对于系统来说,CPU资源是很稀缺的,毕竟,现代的CPU只有不超过两位数的核心,为了同时运行多个程序,系统需要将cpu时间分成多个时间片,按照一定的调度策略,来分给各个运行中的程序使用。
而存储资源,自然就是内存、硬盘这些存储设备,当一个程序在运行的时间,除了需要CPU资源之外,当然也需要存储资源,而存储资源相对CPU资源来说,并没有那么稀缺(当然,一台物理计算机上的可用存储资源也是有限的,这里我们是相对而言),而且大多数现代操作系统中使用了虚拟存储器机制,进程所能使用的存储资源甚至可以大于物理内存的大小,物理内存只是作为磁盘的缓存,当物理内存不够用时,只需按照置换规则将一些内存页换出即可,存储分配也是有计算机来完成的。

由上所述,当我们创建一个进程的时候,我们可以将其满足其存储需求,却不一定能机时满足其计算资源的需求,没有CPU,这个进程是无法运行的,那么他只能在就绪队列中等待被调度,在没有线程概念的那个时代,或者在没有实现内核级线程的系统中,进程就是分配存储资源和被调度的最小单位。

后来,随着CPU性能的越发强大,真正人们发现只依靠进程没法完全发挥CPU的强大性能,一个进程中往往只有一个执行流,一旦当前进程被阻塞,就只能让出CPU,由系统调度新的进程运行,而往往这种模式是不合理的,你可以想想在使用QQ的时候,你下载了一个文件,需要等文件下载完才能继续和别人聊天吗,于是,线程的概念被提出了,在许多系统中,线程被称为轻量级进程,对于一个线程而言,他代表了进程中的一个执行流,多个线程可以并发执行,一个进程中的线程共享进程中的许多资源,包括进程的地址空间,堆,全局变量、静态变量灯,对于线程来说,他只需要一组通用寄存器,程序计数器,以及线程栈就可以运行,这意味着系统对线程的调度花费的更少,当一个进程中的个线程阻塞,并不会导致整个进程的阻塞,操作系统这时可以将cpu资源给进程中另一个线程使用,而且此时不会发生进程的切换,所以,当线程概念被提出的时候,线程就成了系统资源调度的最小单位(这里可以直接理解为计算资源或者更简单暴力的理解成CPU)。

实际上,对于进程和线程的关系,从不同的角度去看,都会有不同收获,而且在不同的系统中,对于线程的实现是不同的,在早期的linux系统中,是没有真正的实现内核级线程的,而现在linux对于线程的实现,也十分的简单,linux内核中进程和线程都是用task_struct来描述,都是用clone系统调用来实现,他们之间唯一的区别就是,线程和其他的线程共享地址空间,linux也并未对线程实现特殊的调度方法。当然,之所以这样是因为linux本身的进程实现就已经很轻量级了。

另外一种观点,也是很有意义的,实际上进程在执行的过程中,不同的时间段,是处在不同的上下文中的,当发生进程切换的时候,势必也发生了上下文的切换,而对于线程来说,由于他们同于与一个进程之中,在线程切换时,是没有发生上下文的切换的,这样就减少了系统的消耗,只是在进程内,多个线程将CPU的时间段使用分的更细了。总结就是,进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注