【Linux】 ——重新理解进程和线程

进程与线程

  • 一、进程与线程
  • 二、进程是什么?
    • 2.2、描述进程PCB
    • 2.3、Linux下查看进程信息
      • 常用命令总结
    • 2.4、进程的状态
  • 三、线程是什么?
  • 四、进程和线程的区别

一、进程与线程

其实要想说好进程和线程的区别,是一个既简单又困难的问题(博主是真学渣,只能一步一步的来)如果简单的记得“进程操作系统资源分配的基本单位,线程是CPU调度的基本单位”,很难让自己的能力得到提升。因为学计算机的应该百分之九十都记得这句话吧。我先给你看看关于进程这一节的思维导图(图片不清晰的话,可以先保存再看,图侵删),句句都是重点有没有
【Linux】 ——重新理解进程和线程_第1张图片

二、进程是什么?

先回忆下程序,程序是一组集合,静态的存储在磁盘中。进程可以理解为正在执行的程序,操作系统将程序加载到内存,形成一个逻辑实例,这就是进程,操作系统为其分配所需资源,包括CPU、文件、IO设备、网络句柄等。所以也就可以得出咱开头说的那一句进程是是操作系统分配资源的最小单位
【Linux】 ——重新理解进程和线程_第2张图片
当进程所需要的资源就绪后,就可以等待CPU调度,其中除了CPU之外,进程所拥有的其他资源构成了进程的执行环境,即进程上下文,一个进程执行完其获取的CPU时间后,就需要被切换,切换前,需要保存其上下文,切换后,等待CPU下一次调度。

2.2、描述进程PCB

也就是说进程是一条动态执行的程序的实例,进程信息被存放在PCB中,PCB是描述进程的结构体,在Linux下就是task_struct结构体,这个结构体包含很多内容,我只挑几个有用的讲解一下:

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。比如fork()函数返回的pid
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址,有pc/ip。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据:进程的硬件上下文信息,程序运行时会在寄存器中存储临时变量,如果程序没有执行完需要使用此信息恢复。
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

如果你还是觉得上述内容有些难懂,我画了个图:
【Linux】 ——重新理解进程和线程_第3张图片
操作系统创建一个进程必须创建出与其对应的进程pcb,也就是图中的task_struct,结构体里面包含的成员就是上面我介绍的那些。页表中存放虚拟内存与实际的物理地址的映射关系。

2.3、Linux下查看进程信息

常用命令总结

  • ps -l 列出与本次登录有关的进程信息;
  • ps -aux 查询内存中的进程信息;
  • ps -aux | grep *** 查询***j进程的详细信息
  • top查看内存中进程的动态信息
  • kill -9 pid 杀死进程

2.4、进程的状态

  • R运行状态:进程要么进行,要么在运行队列中
  • S睡眠状态:进程在等待时间完成(可中断休眠)
  • D磁盘休眠状态:进程等待I/O结束(不可中断休眠)
  • T停止状态:发送SIGTOP信号使进程T状态,发送SIGCONT信号让进程继续
  • X死亡状态:不会在任务列表中看到
  • Z僵尸进程:子进程退出,父进程没有读取到子进程的返回代码,子进程一直等待父进程回收
  • 孤儿进程:父进程先退出,子进程就会变成孤儿进程,孤儿进程会被init进程所领养。

三、线程是什么?

同一时间段,进程只能执行一个任务(读文件A的时候,不能读文件B),符合计算机单核CPU的环境。但是随着技术的发展,业界开始为计算机配备多喝CPU,为了提高计算机的性能,操作系统引入了线程。一个进程可以创建多个线程,进程是独立的,它拥有独立运行的数据段和代码段,每个线程拥有自己运行所需要的堆栈,程序计数器等资源。同时线程可以共享父进程的资源,所以需要控制线程同步的方式(比如互斥锁)(其实线程这里博主也有一个特别长的思维导图,有兴趣的小伙伴可以私我,我给发,这里贴图片的话就太长了)
【Linux】 ——重新理解进程和线程_第4张图片

那我们从上图中发现,当多个pcb指向同一块程序地址空间时,也就意味着这些pcb可以进程共享程序地址空间,但是在cpu看来都是一个个的pcb,所以在上图中,cpu认为有3个进程,并对他们进行调度,由于三个pcb共享程序地址空间,相比于传统的进程来说就非常的轻量化,所以这里提炼出一句很重要的话“线程其实就是一个轻量级的进程”,线程是进程内部的一个执行流。

进程执行,其实就是进程中的线程获取到CPU时间后运行,所以线程是CPU调度的最小单位。一个进程可以创建多个线程,多核CPU可以同时调度多个线程,所以一个进程可以并发执行多个任务。

四、进程和线程的区别

根本区别:我们开头说的,进程是资源分配的基本单位,线程是资源调度的基本单位

  • 开销方面:每个进程都有独立的代码和数据空间,进程之间开销比较大;线程可以看作是一个轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的堆栈和程序计数器,线程间切换的开销比较小。
  • 所处环境:在操作系统中能同时运行多个进程,而在一个进程中有多个线程同时执行(通过CPU调度,每个时间段只有一个线程执行)
  • 内存分配:系统在运行的时候会为每个进程分配不同的内存空间;而对线程来说,除了CPU之外,系统不会为线程分配内存(线程所使用的的资源来自其所属进程的资源)
  • 包含关系:没有线程的进程可以看作是单线程的,如果一个进程内有多个线程,则执行不是一条线的,而是多条线的。线程是进程的一部分,所以线程也被称为轻量级进程

这里还有个简单的比喻,有兴趣的朋友可以瞅瞅

做个简单的比喻:进程=火车,线程=车厢

线程在进程下行进(单纯的车厢无法运行)

一个进程可以包含多个线程(一辆火车可以有多个车厢)

不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)

同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)

进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)

进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)

进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)

进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-“互斥锁”
进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”

(博主最近状态不好,几天才整理出一篇博文,还是那句话,有问题希望提出…)

你可能感兴趣的:(Linux,C++)