进程与线程

来源:互联网 发布:淘宝网电视机 编辑:程序博客网 时间:2024/05/19 23:58

1.进程和线程

进程是伴随着操作系统被提出的,随着计算机技术的发展,进程暴露出一些弊端。一是,进程是资源分配的单位,创建、切换等过程中的时空开销较大,因此需要引进轻量级进程;二是由于多对称处理机(SMP)出现,可以满足多个运行单位,但是多个进程并行运行的开销过大。因此,线程作为能独立运行的基本单位而出现。

在OS中,通常将进程作为资源分配的基本单位,将线程作为独立运行和独立调度的基本单位。

<1>进程是资源分配的基本单位。
系统资源是指内存、文件或者socket等。比如,现在申请了一块堆内存,操作系统将一段物理内存映射到进程地址空间,这个进程地址空间就是操作系统在程序运行时给每个程序分配的虚拟地址空间,这个虚拟地址空间是这个进程的,进程内的所有线程都能访问这个虚拟地址空间,别的线程或者别的进程中的线程无法访问。

<2>线程是独立运行和独立调度的基本单位。

线程是进程中的一个执行路径,是CPU调度和分派的基本单位,是比进程还小的能独立运行的基本单位。线程的运行就是CPU执行一条一条的指令,函数栈帧的开辟与回退等。

调度就是将现在运行的线程的程序寄存器、寄存器值、栈等从CPU中换出去。将下一个进程要用的资源信息加载到CPU上。哪个线程要运行,哪个线程就等待,直到被加载进CPU(调度)。因此,我们说运行和调度都是指线程,进程只是给线程提供了资源和场地。

线程没有出现的时候,进程其实就做了现在线程的工作。它不但要分配资源还要运行与调度。一个人做三件事,开销怎能不大!

2.多线程
这里写图片描述
一个进程可能有一个或多个线程,这些线程共享进程的内存空间,可以访问进程内存的所有数据,但是线程也有自己的私有存储空间(栈空间、一组寄存器)。

因为线程共享进程的内存空间,所以线程之间切换比进程之间花费的时间少,效率高;线程之间共享数据也很方便,无需用户态和内核态之间的切换。

3.线程的状态
线程的主要状态有:运行——阻塞——就绪
挂起态是基于进程的状态概念,对线程没有实际意义。当进程被换出内存(挂起)时,进程内的所有线程都被换出内存。

与线程状态有关的几种基本操作:
派生:一般情况下,当产生一个新进程的时候,同时为该进程产生了一个线程,线程可在同一进程中产生其他线程,新线程将拥有自己的栈空间和寄存器上下文,新线程被放置在就绪队列中。

阻塞:当线程需要等待某一时间时,它将被阻塞,保存线程上下文信息,处理器转而处理同一进程或者其他进程的就绪线程。

解除阻塞:当阻塞线程的事件发生时,该线程被转移到就绪队列中。

结束:当一个线程运行完成时,其寄存器上下文和栈都被释放。

4.多线程模型

<1>多对一模型
这里写图片描述

多对一模型将多个用户线程映射到一个内核线程上,线程调度器在用户进空间,线程之间的切换没有模式的切换。Windows系统默认采用这种进程模型。

所有与线程管理有关的操作都由在用户态完成,由用户态的线程库管理线程,内核感知不到线程的存在,线程的一系列活动(如:线程切换)内核都不知道。内核继续以进程为单位进程调度,并给进程一个状态。

当进程中的线程发生阻塞时,控制权被交给内核,内核将该进程的状态设置为阻塞态,并切换另一进程运行。因此,在多对一模型下,用户线程阻塞会导致进程阻塞

多对一模型的优点:
1)所有与线程管理有关的数据结构都在用户的地址空间中,线程切换没有内核态和用户态的转移,节省了模式切换的开销;
2)调度算法由用户自己提供,可以根据不同的情景自己实现不同的轮询算法,而不会扰乱底层的操作系统调度器;

多对一模型的缺点:
1)一般情况下,系统调用都会引起阻塞,因此,当线程阻塞时,该进程也阻塞,其他线程也不能执行。
2)多线程处理程序不能应用多处理技术。内核一次只把一个进程分配给处理器,因此,某一时刻只能有进程中的一个线程执行。

<2>一对一模型
这里写图片描述
一个用户使用的线程完全对应一个内核线程,反过来不一定(如;僵死进程导致内核线程未释放)。这样,用户线程就和内核线程保持一致,线程之间的并发是真正的并发。 一对一模型下,一个用户线程阻塞时,不影响其他线程的运行,进程不会阻塞

一对一模型的缺点:
1)由于操作系统控制了内核线程的数量,所以用户线程的线程数量也受到影响。Linux采用一对一模型,可以创建200-300个线程。
2)一对一模型导致用户线程切换时也要切换内核线程,内核线程调度时,上下文切换消耗较大,导致用户线程的执行效率下降。

<3>多对多模型
这里写图片描述

多对多模型集合了多对一模型和一对一模型的优点,将多个用户线程映射到少数但不只一个内核线程上。多对多模型下,一个用户线程阻塞并不会导致所有用户线程阻塞,因为此外还有别的线程可被调度执行。也不会会导致进程阻塞

5.Linux系统,进程和线程必须具备的条件
<1>进程:
*可供执行的程序
*独立的内核栈
*在内核中的task_struct数据结构(户口)
*独立的用户空间

<2>内核线程
*可供执行的程序
*独立的内核栈
*在内核中的task_struct数据结构(户口)

<3>用户线程
*可供执行的程序
*独立的内核栈
*在内核中的task_struct数据结构(户口)
*共享进程的用户空间

6.进程和线程的区别
<1>进程是资源分配的基本单位,线程是运行和调度的基本单位;
<2>一个线程只能在一个进程里,一个进程里至少有一个线程(主线程);
<3>线程执行中,需要协作同步。进程之间要通过进程间通信的方法实现同步;
<4>资源分配给进程,同一进程中的线程共享进程中的资源;
<5>CPU分配给线程,真正在CPU上执行的是线程;
<6>Linux系统上,创建线程的函数pthread_create底层调用的是clone,而fork,vfork,clone这类创建进程/线程的函数实际调用的系统API都是do_fork()。