Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
氷泠
CSBookNotes
提交
3c3a4831
C
CSBookNotes
项目概览
氷泠
/
CSBookNotes
上一次同步 1 年多
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
CSBookNotes
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
3c3a4831
编写于
4月 09, 2021
作者:
2
2293736867
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
线程与进程的通信方式+线程与协程的比较
上级
d627ef91
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
166 addition
and
124 deletion
+166
-124
OperatingSystem/Chapter2/README.md
OperatingSystem/Chapter2/README.md
+166
-124
SoftwareTesting/Chapter3/png.odg
SoftwareTesting/Chapter3/png.odg
+0
-0
未找到文件。
OperatingSystem/Chapter2/README.md
浏览文件 @
3c3a4831
# 目录
*
[
1 前趋图
](
#1-前趋图
)
*
[
2 程序执行特征
](
#2-程序执行特征
)
*
[
2.1 顺序执行的特征
](
#21-顺序执行的特征
)
*
[
2.2 并发执行的特征
](
#22-并发执行的特征
)
*
[
3 进程
](
#3-进程
)
*
[
3.1 定义
](
#31-定义
)
*
[
3.2 组成
](
#32-组成
)
*
[
3.3 特征
](
#33-特征
)
*
[
3.4 基本状态
](
#34-基本状态
)
*
[
3.5 基本状态的切换
](
#35-基本状态的切换
)
*
[
3.6 创建与终止状态
](
#36-创建与终止状态
)
*
[
3.7 挂起与激活
](
#37-挂起与激活
)
*
[
4 `PCB`
](
#4-pcb
)
*
[
4.1 `PCB`定义
](
#41-pcb定义
)
*
[
4.2 作用
](
#42-作用
)
*
[
4.3 组成
](
#43-组成
)
*
[
4.3.1 进程标识符
](
#431-进程标识符
)
*
[
4.3.2 处理机状态
](
#432-处理机状态
)
*
[
4.3.3 进程调度信息
](
#433-进程调度信息
)
*
[
4.3.4 进程控制信息
](
#434-进程控制信息
)
*
[
5 用户态与系统态
](
#5-用户态与系统态
)
*
[
6 `OS`内核功能
](
#6-os内核功能
)
*
[
6.1 支撑功能
](
#61-支撑功能
)
*
[
6.2 资源管理功能
](
#62-资源管理功能
)
*
[
7 进程创建
](
#7-进程创建
)
*
[
7.1 引起进程创建的事件
](
#71-引起进程创建的事件
)
*
[
7.2 创建过程
](
#72-创建过程
)
*
[
8 进程终止
](
#8-进程终止
)
*
[
8.1 引起终止的事件
](
#81-引起终止的事件
)
*
[
8.2 终止过程
](
#82-终止过程
)
*
[
9 阻塞/唤醒/挂起/激活
](
#9-阻塞唤醒挂起激活
)
*
[
9.1 阻塞与唤醒
](
#91-阻塞与唤醒
)
*
[
9.1.1 引起阻塞与唤醒的事件
](
#911-引起阻塞与唤醒的事件
)
*
[
9.1.2 阻塞过程
](
#912-阻塞过程
)
*
[
9.1.3 唤醒过程
](
#913-唤醒过程
)
*
[
9.2 挂起与激活
](
#92-挂起与激活
)
*
[
9.2.1 挂起过程
](
#921-挂起过程
)
*
[
9.2.2 激活过程
](
#922-激活过程
)
*
[
10 进程同步
](
#10-进程同步
)
*
[
10.1 制约关系
](
#101-制约关系
)
*
[
10.2 同步机制应该遵循的原则
](
#102-同步机制应该遵循的原则
)
*
[
11 实现互斥
](
#11-实现互斥
)
*
[
11.1 硬件同步机制
](
#111-硬件同步机制
)
*
[
11.2 信号量机制
](
#112-信号量机制
)
*
[
11.2.1 整型信号量
](
#1121-整型信号量
)
*
[
11.2.2 记录型信号量
](
#1122-记录型信号量
)
*
[
11.2.3 `AND`型信号量
](
#1123-and型信号量
)
*
[
11.2.4 信号量集
](
#1124-信号量集
)
*
[
12 信号量集应用
](
#12-信号量集应用
)
*
[
12.1 实现互斥操作
](
#121-实现互斥操作
)
*
[
12.2 实现前趋关系
](
#122-实现前趋关系
)
*
[
13 管程
](
#13-管程
)
*
[
13.1 定义
](
#131-定义
)
*
[
13.2 特性
](
#132-特性
)
*
[
14 进程通信
](
#14-进程通信
)
*
[
14.1 定义
](
#141-定义
)
*
[
14.2 分类
](
#142-分类
)
*
[
14.3 实现方式
](
#143-实现方式
)
*
[
15 线程
](
#15-线程
)
*
[
15.1 进程的基本属性
](
#151-进程的基本属性
)
*
[
15.2 线程引入
](
#152-线程引入
)
*
[
15.3 进程与线程比较
](
#153-进程与线程比较
)
*
[
15.4 线程的三个状态
](
#154-线程的三个状态
)
*
[
15.5 `TCB`
](
#155-tcb
)
*
[
15.6 线程实现方式
](
#156-线程实现方式
)
*
[
15.6.1 内核支持线程
](
#1561-内核支持线程
)
*
[
15.6.2 用户级线程
](
#1562-用户级线程
)
*
[
15.6.3 组合方式
](
#1563-组合方式
)
*
[
15.7 线程实现
](
#157-线程实现
)
*
[
15.7.1 `KTS`实现
](
#1571-kts实现
)
*
[
15.7.2 `ULS`实现
](
#1572-uls实现
)
*
[
15.7.2.1 运行时系统
](
#15721-运行时系统
)
*
[
15.7.2.2 内核控制线程
](
#15722-内核控制线程
)
*
[
15.8 线程创建与终止
](
#158-线程创建与终止
)
*
[
15.8.1 线程创建
](
#1581-线程创建
)
*
[
15.8.2 线程终止
](
#1582-线程终止
)
# 1 前趋图
# 1 前趋图
一个有向无循环图,用来描述程序段或进程之间执行的先后次序关系。每个结点表示一个程序段或一个进程,结点间的有向边用来表示两个节点之间存在的偏序或前趋关系。
基本术语:
...
...
@@ -442,54 +362,142 @@ p3()
-
信息掩蔽:管程中的数据只能由管程中的过程访问
# 14 进程通信
## 14.1 定义
进程通信是指进程之间的信息交换。
# 14 进程通信方式
## 14.2 分类
高级进程通信工具可以简单分为四类:
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,一个进程把数据从用户空间拷到内核缓冲区,另一个进程再从内核缓冲区把数据读走,这种机制被称为进程间通信(
`IPC`
)。
-
共享存储器系统:相互通信的进程共享某些数据结构或共享存储区,可以分为基于共享结构的通信方式以及基于共享存储区的通信方式
-
管道通信系统:利用管道进行通信
-
消息传递系统:将通信的数据封装在消息中,利用操作系统提供的一组通信命令在进程间进行消息传递,完成进程间的数据交换,可以分为直接通信方式和间接通信方式
-
客户机-服务器系统:分为套接字、远程过程调用、远程方法调用三类
常见的7种
`IPC`
方式:
-
管道/匿名管道
-
有名管道
-
信号量
-
消息队列
-
信号
-
共享内存
-
套接字
## 14.
3 实现方式
主要分为两种
:
## 14.
1 管道/匿名管道
特点
:
-
直接消息传递系统
-
信箱通信
-
管道是半双工的,数据只能向一个方向流动,需要双工的时候只能建立两个半双工的管道
-
只能用于父子进程或者兄弟进程之间
-
一个进程向管道中写的内容被管道另一端的进程读出,写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据
管道的实质:
# 15 线程
## 15.1 进程的基本属性
两个:
-
是一个内核缓冲区,进程以
`FIFO`
方式从缓冲区存取数据
-
可以看做一个循环队列,读写位置都是自动增长的,不能随意改变
-
**进程是一个可拥有资源的独立单位**
-
**进程是一个可独立调度和分派的基本单位**
管道局限:
## 15.2 线程引入
在引入线程的
`OS`
中,
**线程作为调度和分派的基本单位**
(而不是进程作为调度和分派的基本单位)。
-
只支持单向数据流
-
只能用于父子进程或兄弟进程
-
没有名字
-
缓冲区有限
-
传送的内容是无格式字节流,这意味着两个读写管道的进程必须事先约定好数据的格式
## 1
5.3 进程与线程比较
线程又叫轻型进程或进程元,传统进程叫重型进程,下面从几个方面对两者进行比较:
## 1
4.2 有名管道
有名管道与匿名管道的区别在与提供了一个路径名与其关联,以有名管道的形式存在于文件系统中,这样就克服了匿名管道只能与父子进程或者兄弟进程通信的缺点。
-
调度的基本单位:不引入线程的
`OS`
中,进程是调度和分派的基本单位,而引入后,线程是调度和分派的基本单位
-
并发性:引入线程后,不同进程之间可以并发执行,同一进程的多个线程也可以并发执行,不同进程的不同线程也可以并发执行
-
资源:进程可以拥有资源,是系统中拥有资源的一个基本单位,而线程本身并不拥有系统资源,只是仅有一点必不可少的线程运行所必须的资源,多个线程能够共享进程所拥有的资源
-
独立性:不同进程的独立性比同一进程的不同线程的独立性要高
-
系统开销:创建/撤销进程所需要的开销远大于创建/撤销线程所需要的开销
-
支持多处理机:传统的单线程进程只能运行在一个处理机上,而多线程进程可以将多个线程分配到多个处理机上
值得注意的是,无论是有名管道还是匿名管道都会存在阻塞问题:
-
匿名管道:匿名管道无需打开,创建时直接返回文件描述符,如果写入匿名管道的数据超过最大值,会阻塞写操作,如果管道中没有数据,会阻塞读操作
-
有名管道:有名管道打开的时候,需要确保另一个进程存在,不存在将会阻塞
## 14.3 信号
特点:
-
可以在任何时候发送给某一进程,无需知道进程的状态
-
如果进程未处于执行状态,那么内核会将该进程保存起来直到进程恢复执行并传递给它为止
-
如果进程阻塞,则信号的传递会被延迟,直到其取消阻塞才被传递给进程
信号的生命周期如下:
-
信号被某个进程产生,并设置此信号传递的对象,然后传递给操作系统
-
操作系统根据进程是否阻塞,如果阻塞则先保存信号,直到不阻塞为止,如果没有阻塞则直接传递信号
-
目标进程收到信号后,根据信号进行处理,比如终止当前代码的执行等等
## 14.4 消息队列
消息队列是存放在内核中的消息链表,每个消息队列由消息队列标识符表示。与管道(匿名管道存在于内存中,有名管道存在于实际文件中)不同的是,消息队列存放在内核中,只有内核重启或显示本地删除一个消息队列的时候,该消息队列才会被真正删除。
特点:
-
允许一个或多个进程向它写入与读取消息
-
可以实现消息的随机查询,消息不一定要以先进先出的方式读取,也可以按照消息的类型读取
-
消息队列克服了信号承载信息量少、管道只能承载无格式字节流以及缓冲区大小受限等缺点
目前主要有两种类型的消息队列:
`POSIX`
消息队列以及
`System V`
消息队列。
## 14.5 共享内存
共享内存使得多个进程可以直接读写同一块内存空间,是最快的
`IPC`
方式,针对其他通信机制运行效率低效而设计的。
同时,由于多个进程共享一段内存,因此需要依靠某种同步机制(比如信号量)来达到进程间的同步和互斥。
## 14.6 信号量
信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步,为了获得共享资源,需要执行以下操作:
-
创建一个信号量:需要调用者指定初始值,通常是共享资源的数量
-
等待一个信号量:会测试这个信号量的值,如果小于0就阻塞,否则将其减1,也叫
`P`
操作
-
挂出一个信号量:将信号量的值加1,也叫
`V`
操作
为了保证信号量操作的原子性,通常在内核中实现,
`Linux`
环境中有三种类型:
-
`Posix`
有名信号量
-
`Posix`
基于内存的信号量
-
`System V`
信号量
## 14.7 套接字
套接字是一种通信机制,通过套接字,客户/服务器系统的开发工作既可以在本地单机上进行,也可以跨网络进行。
套接字的特性由三个属性确定:
-
域
-
端口号
-
协议类型
### 14.7.1 域
域是套接字通信中使用的网络介质,最常见的域有两种:
-
`AF_INET`
:指网络,一般用于跨网络通信
-
`AF_UNIX`
:表示
`UNIX`
文件系统,就是文件的输入输出
### 14.7.2 端口号
每一个基于
`TCP/IP`
网络通信的程序都被赋予了唯一的端口和端口号,端口是一个信息缓冲区,用于保留
`Socket`
中的输入/输出信息。
### 14.7.3 协议类型
三种:
-
流套接字:在域中通过
`TCP/IP`
连接实现,同时也是
`AF_UNIX`
常用的套接字类型,流套接字提供一个有序的、可靠的、双向字节流的连接,因此发送的数据可以确保不丢失、重复或乱序到达,而且出错重传机制
-
数据报套接字:不需要建立连接和维持一个连接,在域中通常是通过
`UDP/IP`
实现,发送数据的长度有限制,数据包可能会出现丢失、复制或错乱到达
-
原始套接字:允许对较低层次的协议直接访问,比如
`IP`
、
`ICMP`
协议,换句话说,如果需要发送不是基于
`TCP/UDP`
协议的数据,必须使用原始套接字
### 14.7.4 套接字建立过程
简单来说,套接字需要服务器先监听一个端口,并循环等待连接,接着客户端进行连接,具体来说,对于服务端:
-
首先通过系统调用
`socket`
创建一个套接字
-
接着通过系统调用
`bind`
给套接字起名字
-
再接着系统调用
`listen`
设置一个监听队列
-
最后通过系统调用
`accept`
接受客户端的连接
而客户端的过程如下:
-
通过
`socket`
创建一个未命名的套接字
-
然后将服务器的命名套接字作为一个地址来调用
`connect`
来与服务器建立连接
-
一旦连接建立就可以实现双向的数据流通信
# 15 线程
## 15.1 线程引入
在引入线程的
`OS`
中,
**线程作为调度和分派的基本单位**
(而不是进程作为调度和分派的基本单位)。
## 15.
4
线程的三个状态
## 15.
2
线程的三个状态
-
执行状态:获得处理机执行
-
就绪状态:线程已具备各种执行条件,获得
`CPU`
即可执行
-
阻塞状态:线程在执行中因某事件受阻而处于暂停状态
## 15.
5
`TCB`
## 15.
3
`TCB`
类似
`PCB`
,系统为每个线程也分配了一个
`TCB`
,包含的信息有:
-
线程标识符
...
...
@@ -500,8 +508,8 @@ p3()
-
信号屏蔽
-
堆栈指针
## 15.
6
线程实现方式
### 15.
6
.1 内核支持线程
## 15.
4
线程实现方式
### 15.
4
.1 内核支持线程
`Kernel Supported Threads`
,
`KTS`
,内核支持线程,在内核的支持下运行,创建、阻塞、撤销和切换都是在内核空间实现的,优点如下:
-
多处理器系统中,能够调度同一进程中的多个线程并发执行
...
...
@@ -513,7 +521,7 @@ p3()
-
切换开销大,对用户切换线程而言,需要从用户态切换到内核态,系统开销较大
### 15.
6
.2 用户级线程
### 15.
4
.2 用户级线程
`User Level Threads`
,
`ULT`
,用户级线程,在用户空间内实现,对线程创建、撤销、同步与通信无需内核的支持,与内核无关。
优点:
...
...
@@ -527,7 +535,7 @@ p3()
-
系统调用阻塞:大多数的系统调用会将线程阻塞
-
不能最大化利用线程:单纯的用户级线程实现中,多线程应用不能利用多处理机进行多重处理的优点,也就是进程中只能有一个线程运行
### 15.
6
.3 组合方式
### 15.
4
.3 组合方式
基于上面的两种方式,提出了一种组合的方式,形成了三种不同的模型:
-
多对一模型:将用户线程映射到一个内核线程
...
...
@@ -536,27 +544,61 @@ p3()
## 15.
7
线程实现
### 15.
7
.1 `KTS`实现
## 15.
5
线程实现
### 15.
5
.1 `KTS`实现
-
创建进程时分配一个任务数据区(
`Per Task Data Area`
),其中包括若干
`TCB`
空间
-
当进程创建一个线程时,便分配一个
`TCB`
,并分配必须的资源
-
继续创建线程时继续分配
`TCB`
### 15.
7
.2 `ULS`实现
### 15.
5
.2 `ULS`实现
`ULS`
在用户空间实现,所有用户级线程都具有相同的结构,运行在中间系统上,实现中间系统主要有以下两种方式:
#### 15.
7
.2.1 运行时系统
#### 15.
5
.2.1 运行时系统
运行时系统实质是用于管理和控制线程的函数的集合,线程切换通过调用运行时系统的函数来完成,当线程需要资源时,将请求传递给运行时系统,由运行时系统通过相应的系统调用获取资源。
#### 15.
7
.2.2 内核控制线程
#### 15.
5
.2.2 内核控制线程
又叫轻型进程
`LWP`
(
`Light Weight Process`
),
`LWP`
可通过系统调用获得内核提供的服务,用户级线程运行时,只需将它连接到一个
`LWP`
上。
通常把
`LWP`
做成一个缓冲池,叫“线程池”,用户级线程连接到其中一个
`LWP`
上,而该
`LWP`
又与内核级线程连接,这样就可以实现用户级线程与内核无关。
## 15.8 线程创建与终止
### 15.8.1 线程创建
## 15.6 线程创建与终止
线程创建:
-
创建新线程时,利用线程创建函数,并提供相应参数
-
创建完成后返回一个线程标识符
### 15.8.2 线程终止
线程终止:
-
通过调用相应函数或系统调用进行终止
## 15.7 线程通信方式
线程之间通信主要是用于同步而不是数据交换,包括:
-
锁机制:包括互斥锁、读写锁、条件变量以及自旋锁
-
信号量机制:包括匿名线程信号量和有名线程信号量
-
信号机制:类似进程中的信号机制
-
使用全局变量
# 16 进程与线程比较
线程又叫轻型进程或进程元,传统进程叫重型进程,下面从几个方面对两者进行比较:
-
调度的基本单位:不引入线程的
`OS`
中,进程是调度和分派的基本单位,而引入后,线程是调度和分派的基本单位
-
并发性:引入线程后,不同进程之间可以并发执行,同一进程的多个线程也可以并发执行,不同进程的不同线程也可以并发执行
-
资源:进程可以拥有资源,是系统中拥有资源的一个基本单位,而线程本身并不拥有系统资源,只是仅有一点必不可少的线程运行所必须的资源,多个线程能够共享进程所拥有的资源
-
独立性:不同进程的独立性比同一进程的不同线程的独立性要高
-
系统开销:创建/撤销进程所需要的开销远大于创建/撤销线程所需要的开销
-
支持多处理机:传统的单线程进程只能运行在一个处理机上,而多线程进程可以将多个线程分配到多个处理机上
# 17 线程与协程比较
协程是一种轻量级线程,又叫微线程,协程的调度完全由用户控制。特点包括:
-
执行效率高
-
不需要多线程的锁机制
与线程的主要区别在于:
-
线程是同步机制,而协程是异步机制
-
协程能保留上一次调用的状态,每次重入时,将相当于进入上一次调用的状态
SoftwareTesting/Chapter3/png.odg
0 → 100644
浏览文件 @
3c3a4831
文件已添加
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录