Ref: https://blog.csdn.net/PinkFriday/article/details/78299857

1.进程

在引入线程的操作系统中,资源分配的基本单位是进程
进程表示单个运行活动集的计算机程序,是系统的资源分配和调度的基本单元,是操作系统结构的基础。

  • 在早期面向进程的计算机结构中,进程是程序的基本执行实体
  • 在面向线程设计的现代计算机结构中,进程是线程的容器

    1.1 进程与程序

    程序是对指令、数据及其组织形式的描述,可以作为目标文件保存在磁盘中,或者作为段存放在内存地址空间中。
    进程是程序运行的一个具体的实例,程序总是运行在某个进程的上下文中。

二者区别:
(1) 进程是动态的,而程序是静态的。
(2) 进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。没有建立进程的程序不能作为1个独立单位得到操作系统的认可。
(3) 1个程序可以对应多个进程,但1个进程只能对应1个程序。进程和程序的关系犹如演出和剧本的关系。
例1:一个程序可以重复运行,开几个窗口,比如网游的“双开”,一个进程可以对应多个程序就是一个DLL文件可一被多个程序运用,比如DirectX9的动态链接库,就是,许多游戏都要有它才能运行。
例2:显示图像的驱动程序,多个程序的显示都是需要他来执行。玩游戏算一个程序,需要显示图像的驱动,声音驱动、IO驱动的同时执行。

1.2 进程结构

进程最经典的定义就是一个执行中的程序的实例。系统中的每个进程都运行在某个进程的上下文中。上下文是由程序正确运行的所需的状态组成的。这个状态包括放在内存中的程序代码和数据,栈,通用目的寄存器的内容,程序计数器,环境变量以及打开文件描述符。

进程的地址空间如下图所示,注意的是这是每个进程都有的独立、私有的空间(代码段总是从 0x400000 开始的),这是通过虚拟内存技术实现的。
image.png

  • .data 是已初始化的全局和静态变量
  • .bss 是未初始化的全局和静态变量(不占空间,只是一个占位符)
  • .text 是已经编译的程序机器代码

结合一个简单的例子就能明白我们写的程序中的各个变量在进程地址空间所处的位置,以及堆区和栈区的区别:

  1. int a = 0; // 全局初始化区
  2. char *p1; // 全局未初始化区
  3. main()
  4. {
  5. int b; // 栈
  6. char s[] = "abc";// 栈
  7. char *p2;// 栈
  8. char *p3 = "123456"; // 123456\0在常量区,p3在栈上。
  9. static int c =0// 全局(静态)初始化区
  10. p1 = (char *)malloc(10);
  11. p2 = (char *)malloc(20);
  12. // 分配得来得10和20字节的区域就在堆区。
  13. strcpy(p1, "123456");// 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
  14. }

进程结构(2):
image.png

  • 代码区:存放 CPU 执行的机器指令,代码区是可共享,并且是只读的。
  • 数据区:存放已初始化的全局变量、静态变量(全局和局部)、常量数据。
  • BBS 区:存放的是未初始化的全局变量和静态变量。
  • 栈区:由编译器自动分配、释放,存放函数的参数值、返回值和局部变量,在程序运行过程中实时分配和释放,栈区由操作系统自动管理,无须程序员手动管理。
  • 堆区:堆是由 malloc() 函数分配的内存块,使用 free() 函数来释放内存,堆的申请释放工作由程序员控制,容易产生内存泄漏。

    1.3 进程特征

    进程特征

  • 动态性:是程序的一次执行,在一个数据集合上的运行过程,具有生命周期;

  • 并发性:进程是可以并发执行的计算;
  • 独立性:是系统进行资源分配和调度的一个独立(基本)单位;
  • 异步性(制约性):进程间的相互制约,使进程执行具有间隙,造成程序执行速度不可预测性,必须对进程的并发执行次序、相对执行速度加以协调;
  • 结构性:进程是具有结构的,由程序块 、数据块、进程控制块三部分组成;

操作系统引入进程的概念的原因:

  • 从理论角度看,是对正在运行的程序过程的抽象。
  • 从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序

image.png

2.线程

线程是运行在进程上下文的逻辑流。一个进程里边可以运行着多个线程,所以线程的粒度比进程小。
线程由内核调度,也有自己的线程上下文,包括一个唯一的整数线程 ID, 栈和栈指针,程序计数器,通用目的寄存器和条件码。
要注意的是,所有运行在一个进程里的线程共享该进程的整个虚拟地址空间。(结合进程的地址空间图)

2.1 线程的内存模型

每个线程独立的线程上下文:一个唯一的整数线程 ID, 栈和栈指针,程序计数器,通用目的寄存器和条件码。
和其他线程共享的进程上下文的剩余部分:整个用户虚拟地址空间,那就是下图的只读代码段,读 / 写数据段,堆以及所有的共享库代码和数据区域,也共享所有打开文件的集合。
image.png
这里要注意的是线程的寄存器是不共享的,通常栈区是被相应线程独立访问的,但是还是可能出现一个线程去访问另一个线程中的栈区的情况。这是因为这个线程获得了指向另一个线程栈区的指针,那么它就可以读写这个栈的任何部分。

2.2 TCB

线程的实体包括程序、数据和 TCB
线程是动态概念,它的动态特性由线程控制块 TCB(Thread Control Block)描述。
TCB 包括以下信息:

  • 线程状态
  • 当线程不运行时,被保存的现场资源
  • 一组执行堆栈
  • 存放每个线程的局部变量主存区
  • 访问同一个进程中的主存和其它资源

用于指示被执行指令序列的程序计数器、保留局部变量、少数状态参数和返回地址等的一组寄存器和堆栈。

wiki 描述:
An example of information contained within a TCB is:

  • Thread Identifier: Unique id (tid) is assigned to every new thread
  • Stack pointer: Points to thread’s stack in the process
  • Program counter: Points to the current program instruction of the thread
  • State of the thread (running, ready, waiting, start, done)
  • Thread’s register values
  • Pointer to the Process control block (PCB) of the process that the thread lives on

The Thread Control Block acts as a library of information about the threads in a system. Specific information is stored in the thread control block highlighting important information about each process.

3.进程与线程区别

  • 进程是操作系统资源分配和调度的最小单位,线程是程序执行的最小单位。
  • 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
    而线程是共享进程中的数据的,使用相同的地址空间,因此 CPU 切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
  • 线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC) 进行。不过如何处理好同步与互斥是编写多线程程序的难点。
  • 多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了;
    一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。

进程与线程的同步:

  • 进程:无名管道、有名管道、信号、共享内存、消息队列、信号量
  • 线程:互斥量、读写锁、自旋锁、线程信号、条件变量

Ref: https://www.cnblogs.com/valjeanshaw/p/11469514.html
进程:进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,
线程:线程是 CPU 调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

联系:线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
区别:理解它们的差别,从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)

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