首先需要声明一些因为不同操作系统所产生的一些概念上的差别,但是在比较二者之间的本质时并没有什么明显的区别:
Windows系统:在windows系统下有专门的定义线程的数据结构,可以说在在windows系统下,进程就是线程的更小划分,线程同样和进程一样是作为分配资源和系统运行的独立基本单位。
Linux系统:在Linux系统下并没有专门定义关于线程的数据结构,所谓的Linux下的线程其本质是用Linux下的进程数据结构来模拟实现的,但是为了用户的交互性考虑,Linux下的线程在系统调用的基础上,封装了一系列的系统调用库,最为熟知的就是<pthread.h>库。
进程与程序的比较
1)进程是程序及其数据在计算机的一次运行活动,是一个运行过程,我们可以认为进程是一个动态的概念。进程的运行实体是程序,一个程序可以被多个进程使用,离开程序的进程没有存在的意义,而程序是一组有序的指令的集合,是一种静态概念。
2)进程是程序的一次执行,需要动态的创建和消亡,具有一定的生命周期,可以算是一种临时变量吧,是暂时存在的;而程序则是一组代码的集合,它是永久存在的,可以长期保存在存储器中。
3)一个进程可以执行一个或多个进程,一个程序也可以构成过个进程;进程可以创建进程,而程序则不能形成新的程序。
4)进程和程序的组成不同。进程是由操作系统专门定义的一种数据结构,从概念上来说,进程由进程控制块(PCB)、数据段、代码段三部分组成;程序则是一组有序指令的集合。
进程和线程的比较
要比较进程和线程首先需要简单的说一下进程和线程:
进程:进程是并发执行的的程序在执行过程中分配和管理资源的基本的独立的单位,是一个动态的概念,每一个进程都由一个PCB在进程队列标识着,他们都有各自独立的地址空间,即进程地址空间,关于进程地址空间的大小并不是固定的,而是和当前的处理机的一次能处理的二进制位数有关系,一个16位的处理机进程空间的大小是2的16次方,一个32位的处理机进程地址空间是2的32次方,说到这想必你已经掌握了进程地址空间大小的计算方法。
进程的基本状态:初始状态,执行状态,等待状态,就绪状态,终止状态。
线程:首先说一个特例就是单进程程序或者说是没有线程的进程,因为可以把它看成是单线程程序,而为了满足大量不确定数量的用户来向服务器发送请求的这种状况,为了避免为每一个用户创建一个请求进程这种耗费资源的事情,在现在的操作系统上都引入了多线程编程来解决这种诸如此类的问题。所以,有时候我们也将线程称为轻量级进程,也是CPU调度的基本单位。
1)调度的基本单位
一句话,在传统的操作系统中,进程是作为独立调度和分派的基本单位,在引入线程的操作系统中,线程是作为独立调度和分派的基本单位。
2)并发性
并发性可以说是现代操作系统中最基本的一个特性之一,因此多进程之间可以实现并发运行,多线程也是可以并发运行的,不多此处的多线程是属于同一个进程中的多个线程之间可以并发执行。
3)拥有资源
进程拥有其运行时需要的所有资源,是系统中一个拥有资源的基本单位,而从线程的角度来说,线程只是拥有一点运行时必不可少的,能保证独立运行的资源。
4)独立性
关于独立性我们可以先从进程和线程自身进行分析:
进程的是用于提高独一性的,也就是通常所说的降低模块之间的耦合度,但是不同的进程之间有时候又避免不了要进行相互间的通信,因此在独立的基础上要想实现多进程之间的共享,操作系统又为我们引进了进程间通信的概念;而线程的设计我们在上面就已经解释过了,主要是为了实现同一进程中的资源共享,但是线程也不能做到绝对的共享,他本身也需要独立私有东西们最主要的有以下三类:(1)独立的栈空间(2)独立的上下文运行环境(3)独立的调度信息(像什么线程号Tid之类的一般都存放在调度信息之中)
5)系统开销
关于系统开销的问题我们要从进程和线程的整个生命周期进行分析:
进程创建:以大多数进程的创建来说,首先需要调用fork函数创建父进程和子进程(调用系统函数,产生了一次系统开销),将创建出来的进程PCB挂接到进程的PCB等待队列上(PCB属于一个独立的进程管理的数据结构,此处产生了一个内存空间的分配,这个分配涉及到虚拟地址空间的建立,将虚拟地址空间通过页表和MMU映射到物理内存中的对应位置);
进程中间的状态再此不再细述,如果不了解可以参看本人前面博客;
进程的终止:进程的终止主要分为三种状态,主要说一下进程正常终止的情况,再此孤儿进程、僵尸进程等的特殊情况在此将不再赘述,调用wait或waitpid函数(调用函数产生系统调用开销),此时子进程并不是立即就被释放而是依旧存在系统中,而是要将子进程的退出信息按照退出码的方式传递给父进程,而被终止的子进程直达父进程调用wait函数或是父进程自己终止掉时才释放进程占用的系统资源,而在此期间操作系统必须一直维护系统中的这些资源。
线程的创建:因为线程是相当于进程的更小划分,因此在线程创建的时候,并不需要在申请系统资源,只要执行进程中为该线程的分配的执行流(调用pthread_create()函数);
线程的终止:在次此依然只讨论线程正常终止的情况,线程终止时的情况有点像malloc和free的状况,我们只需要通过一个指针来进行管理,通过(pthread_join()函数)接收指针的返回来值即可;
综上:进程产生的系统开销圆圆大于线程产生的系统开销。