Linux中进程与线程的区别、线程的创建、等待与退出

时间:2022-10-05 14:56:25

进程与线程的区别

在了解线程与进程之间的区别前我们先来认识线程与进程,我们从概念入手,什么是线程、什么是进程,再进行进程与线程之间的不同点与相同点比较,优点与缺点进行比较理解。

进程的概念

进程(Process)就是程序的一次实例化,是分配资源的实体
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动
是资源分配的基本单位

但是如果单单这样理解是完全不够的,我们必须要深入理解,怎么理解?
我们来结合进程中的PCB来理解,一个进程中有三大块,进程控制块(PCB)、数据段、代码段。我们主要分析PCB

首先在LInux下,用来描述PCB的是一个叫 task_struct 的结构体,来描述一个PCB,从而操作系统通过PCB来管理一个进程。

我们来看看 task_struct 主要的信息

  1. 标识符:用来描述本进程的唯一标识符,区别其他进程
  2. 状态:用来表示当前进程的状态,退出码,退出信号
  3. 优先级:相对于其他进程之间的优先级
  4. 程序计数器:用于记录程序的下一条指令的地址
  5. 内存指针:其中有代码和数据相关的指针,还有共享内存块指针
  6. 上下文:进程执行时寄存器中的数据 (用来程序切换是记录的上下文)
  7. I/O状态 :包括显示I/O请求,分配I/O设备和被进程使用的文件列表
  8. 记账信息:其中包含各种时间
  9. 其他

我么可以在Linux下用 top 命令查看当前进程
Linux中进程与线程的区别、线程的创建、等待与退出
我们再看看进程的特征

动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
并发性:任何进程都可以同其他进程一起并发执行
独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源的独立单位;
异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
结构特征:进程由程序、数据和进程控制块三部分组成。

线程的概念

什么是线程?

线程是进程中一个控制序列,每个进程都最少有一个线程,线程是调度的基本单位。在linux中线程也是一个轻量级的进程。

线程因为是轻量级进程也有三大块,线程控制块(在linux中是因为线程就是轻量级进程所以线程的控制块也叫PCB)、数据段、代码段。但是大部分都是共享的。
我们先看看在Linux下线程
Linux中进程与线程的区别、线程的创建、等待与退出
在上面图中,PID为进程的ID、PPID为进程的父进程ID、LWP为线程的ID
简单介绍线程,我们来对比着学习

线程与进程的区别与联系

区别

  • 资源分配:资源分配的基本单位,而线程是调度的基本单位

  • 进程与进程之间是独立的,一个进程的异常终止不会影响其它进程,而线程与线程之间大部分是共享的,一个线程的异常终止会影响其它线程,会使进程终止。

  • 线程与线程大部分共享,但是也有一部分数据私有,线程ID、上下文(切换时候寄存器中的值)、自己独享一个栈空间、错误码、信号屏蔽字、调度的优先级。

  • 调度和切换:线程上下文切换比进程上下文切换要快得多。

  • 一个进程中有多个线程时候,线程共享以下,在进程与进程之间的切换所花费消耗的大于线程与线程之间切换的花销

  • 线程比进程占用的资源要小,一个线程的创建远小于进程的创建。
  • 进程与进程之间是独立的,所以在并发过程中,用同步互斥少,相对安全,代码编写容易。线程之间大多数资源共享,所以往往要加上同步互斥锁。
  • 线程创建出来的线程是平等的没有上下级,而进程创建出进程就为该进程的子进程

联系

  • 进程与线程之间的关系:线程是存在进程的内部,一个进程中可以有多个线程,一个线程只能存在一个进程中。
  • 一个线程的结束进程不一定会退出,但是进程的退出,线程将退出。
  • 一个进程中的多个线程共享:1)一个进程中线程与线程之间同的虚拟地址空间、2)共享文件描述符、3)每种信号的处理方式、4)当前的工作目录、5)用户ID和组ID

    线程ID和在进程地址空间的布局

    线程ID在线程库NPTL中提供的pthread_create创建出来的是一个地址,我们可以通过

pid_t gettid(void) // 获取线程ID

通过

pid_t getpid(void) // 获取进程ID

进程的虚拟地址空间既线程在虚拟地址空间中的布局,我们来画一个图来解释
Linux中进程与线程的区别、线程的创建、等待与退出
我们前面讲过,线程在进程中,那么线程中的自己私有的东西,是存放在mmap内存共享区中的。
那么线程ID为在每个维护自己线程的起始位置的地址。

线程的创建、等待与退出

我们是采用用POSIX线程库,来进行一些相关函数接口的解释,所以我们要在编译的时候添加上 -lpthread

线程的创建

先看函数

未完。。