type
status
date
slug
summary
tags
category
icon
password
多线程,是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,进而提升整体处理性能。
一、进程与线程
1. 进程
关于进程,我们从两个角度出发来观察它。
1.1 系统角度
具有一定独立功能的程序关于某个数据集合上的运行活动,是系统进行资源分配和调度的最小独立单位。
怎么理解上面这句话呢?
首先,进程是“动”的,不是静态的,程序躺在硬盘里,不是进程,进程是要“运行的”。其次,具有独立功能,一个进程完成在运行的过程中,要完成一定功能。最后,在某个数据集合上的处理,任何程序都在数据集合上进行数据的采集、处理、分析到给出人们想要的数据。
从上面,可以得出进程的三个特征:
特性:
- 独立性:独立存在的实体,拥有自己独立资源和私有地址空间;
- 动态性:进程是一个正在系统中活动指令集合,具有生命周期和各种状态;
- 并发性:多个进程可在单处理器并发执行;
1.2 编码角度
进程作为一个正在执行的程序的实例是UNIX的一个基本概念,该实例可以通过
Process ID
(进程ID,即PID)来唯一表示。尽管同一个可执行程序可以并发地启动多个实例,但是每一个实例都有一个不同的PID。进程组可以包括多个进程,进程组用于向该进程组发送信号来控制这些进程。
父进程可以通过fork创建子进程,并且预期子进程会消亡。进程和父进程的亲属关系保存在父进程ID(Parent Process Identifier)中。进程在运行结束之后,会返回一个整数,子进程返回的整数由其父进程收集,所以父进程的生命周期一般比子进程生命周期长。
2. 线程
线程是进程的一个实体,是进程执行单元,是程序中独立、并发的执行流,是CPU调度和分派的基本单位,是比进程更小的能独立运行的基本单位。
线程本身基本上不拥有系统资源,只拥有在运行中必不可少的资源(寄存器、栈等),一个线程可以创建和撤销另一个线程。
3. 进程与线程联系与区别
- 联系
- 包含:一个线程属于一个进程,一个进程可以拥有多个线程;
- 资源:资源分配给进程,同一进程内的所有线程共享该进程的所有资源;
- 同步:线程在执行过程中需要协调同步。不同进程间的线程要利用消息通信的办法实现同步;
- 粒度:真正在处理机上运行的是线程;
- 区别
- 调度:线程作为分派和调度的基本单元,进程作为拥有系统资源的基本单元;
- 并发性:不仅进程间可以并发,线程间也可以并发;
- 开销:进程的创建和撤销都比较大;
二、进程生命周期
下图是一个进程的生命周期,其中SXXX是
<sys/proc.h>
头文件中定义的常量(代码见参考1)。上面各常量对应的状态如下:
2.1. 状态
2.1.1 SIDL
表示一个暂时的空闲状态,进程在刚刚父进程通过fork创建出来出于该状态。
- 在这个状态中,进程仍被定义为“正在初始化”,不会响应任何信号,也不会进行任何操作,因为这个进程还在进行内存布局的设置工作以及加载要求的依赖模块。一旦所有初始化工作完成之后,那么该进程就可以执行了,而且不会返回到SIDL。
- 处于SIDL一定是单线程的,因为线程只能在过后才能被派生(spawn)。
- 下一个状态
- SRUN:初始化完成
2.1.2 SRUN
可运行状态(runnable)与正在运行状态(running)
- 如果一个进程被加入运行队列等待运行,就出于可运行状态,但是这个进程并没有真正运行,因为CPU忙于其他进程。只有当CPU的寄存器都加载了属于某个进程(进程中的线程)的寄存器值,才会出于正在运行状态。
- 如果正在运行的进程时间片用完,或者被其他更高优先级的进行抢占,那么这个处于正在运行的进程会被“踢出”CPU,并返回到运行队列
- 下一个状态:
- SRUN:时间片用完或被抢占
- SSLEEP:等待资源
- SSTOP:信号
- SZOMB:exit()
2.1.3 SSLEEP
- 当进程处于等待时,处于睡眠状态,也称阻塞状态
- 资源通常是I/O相关资源(如文件和设备),也包括同步对象(互斥体和锁)
- 当进程在等待时,就没有必要占用CPU,甚至没有必要存在于运行队列中,将会进入睡眠。一直睡眠,直到资源可用,进程会被重新放入运行队列等待执行。
- 睡眠的进程也可以被信号唤醒。
- 下一个状态:
- SURN:资源可用,或者被信号唤醒
2.1.4 SSTOP
- 通过一个特殊信号(TSOP、TOSTOP)可以让进程停止执行。
- 进程停止执行后,会挂起该进程所有线程,进程相当于“深度睡眠”。
- 下一个状态:
- SRUN:收到CONT信号,进程可以切回到可运行状态。
2.1.5 SZOMB
僵尸状态,当一个进程通过从main()函数返回或通过调用exit()函数完成执行时,这个进程被从内存中清理干净,从而完全终止。终止一个进程会同时终止其所有四线程。但是在进程完成终止之前,会短暂处于僵尸状态。
- 进程的最后要给父进程一个返回值,对父进程出来说,唯一要做的事情,就是通过wait()等待子进程,一遍手机子进程返回的值。有时,子进程生命周期长于父进程,此时,子进程会被其祖先进程“收养”。祖先进程是PID为1的进程(macOS中该进程是launchd),这个进程的生命周期超过了所有其他进程:从引导到关机一直存在。
- 那些生命周期超过子进程,但仍然抛弃自己子进程转移到其他事情的父进程会使得其子进程处于僵尸状态。僵尸进程只是进程的空壳,所有的资源都释放了,但仍然占用PID,而且以或Z状态出现进程列表中。只有父进程最终想起它们,并且通过wait操作等待它们——收集子进程返回值——时,或者父进程自己死亡,将它们交予PID为1的进程收养是,子进程才能完全死去。
- 下一个状态
- DEAD:父进程wait操作、或父进程死亡,被PID为1的进程收养
2.1.6 DEAD
进程已退出,不占用资源,不在进程列表出现。
2.2 UNIX 信号
当进程在运行时,只执行自己的代码。进程运行时,可能会遇到信号。
- 信号是一种软件终端,表示进程发生异常,或者发生外部事件。
- 信号由操作系统发送给进程,用于表示发生了某种条件,而这种条件通常是因为某类硬件错误或程序异常而产生的。
- macOS定义了31个信号,详细见
<sys/signal.h>
# | 信号 | 来源 | 意义 | 进程P/线程T | 默认处理 |
1 | HUP | Tty | Terminal hangup (for daemons: reload conf). | P | K |
2 | INT | Tty | Generated by terminal driver on stty intr. | P | K |
3 | QUIT | Tty | Generated by terminal driver on stty quit. | P | K,C |
4 | ILL | HW | Illegal instruction. | T | K,C |
5 | TRAP | HW | Debugger trap/assembly ("int 3"). | T | K,C |
6 | ABRT | OS | abort() | P | K,C |
7 | POLL | OS | If _POSIX_C_SOURCE — pollable event. | P | K,C |
ㅤ | ㅤ | ㅤ | Else, emulator trap. | T | K,C |
8 | FPE | HW | Floating point exception, or zero divide. | T | K,C |
9 | KILL | User, OS (rare) | The 9mm bullet. Kills, no saving throw. Usually generated by user (kill -9). | P | K |
10 | BUS | HW | Bus error. | T | K,C |
11 | SEGV | HW | Segmentation violation/fault — NULL dereference, or access protection or other memory. | T | K,C |
12 | SYS | OS | Interrupted system call. | T | K,C |
13 | PIPE | OS | Broken pipe (generated when P on read of a pipe is terminated). | T | K |
14 | ALRM | HW | Alarm. | P | K |
15 | TERM | OS | Termination. | P | K |
16 | URG | OS | Urgent condition. | P | I |
17 | STOP | User | Stop (suspend) process. Send by terminal on stty stop. | P | S |
18 | TSTP | Tty | Terminal stop (stty tostop, or full screen in bg). | P | S,T |
19 | CONT | User | Resume (inverse of STOP/TSTOP). | P | I |
20 | CHLD | OS | Sent to parent on child’s demise. | P | I |
21 | TTIN | Tty | TTY driver signals pending input. | P | S,T |
22 | TTOU | Tty | TTY driver signals pending output. | P | S,T |
23 | IO | OS | Input/output. | P | I |
24 | XCPU | OS | ulimit –texceeded. | P | K |
25 | XFSZ | OS | ulimit –fexceeded. | P | K |
26 | VTALRM | OS | Virtual time alarm. | P | K |
27 | PROF | OS | Profiling alarm. | P | K |
28 | WINCH | Tty | Sent on terminal window resize. | P | I |
29 | INFO | OS | Information. | P | I |
30 | USR1 | User | User-defined signal 1. | P | K |
31 | USR2 | User | User-defined signal 2. | P | K |
2.2.1 信号来源分类
HW:硬件异常或错误
OS:操作系统,内核代码某个地方错误
Tty:终端驱动程序
User:用户通过kill命令发送的信号(用户可以通过这个命令模拟其他所有信号)
2.2.2 默认处理
如果没有注册处理程序,在收到信号的采取操作
C——SA_CORE:除非另外指定,进程会产生核心转储。
I——SA_IGNORE:即使没有设置信号处理程序,也会忽略掉信号
K——SA_KILL:除非捕捉到信号,否则进程会终止
S——SA_STOP:除非捕捉到信号,否则进程会暂停运行。
T——SA_TTYSOP:等同于SA_STOP,但是预留个TTY使用。
参考
链接
- 《深入解析Mac OS X & iOS 操作系统》