Skip to content

Commit bb021b5

Browse files
authored
更新进程管理系列文章的md文件
1 parent ac79bc7 commit bb021b5

4 files changed

Lines changed: 293 additions & 21 deletions

File tree

‎os/4_process/deadlock.md‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,29 @@
3333

3434
比如下图,如果线程 A 已经持有的资源,不能再同时被线程 B 持有,如果线程 B 请求获取线程 A 已经占用的资源,那线程 B 只能等待,直到线程 A 释放了资源。
3535

36-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/互斥条件.png)
36+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/互斥条件.png)
3737

3838
### 持有并等待条件
3939

4040
持有并等待条件是指,当线程 A 已经持有了资源 1,又想申请资源 2,而资源 2 已经被线程 C 持有了,所以线程 A 就会处于等待状态,但是**线程 A 在等待资源 2 的同时并不会释放自己已经持有的资源 1**。
4141

42-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/持有并等待条件.png)
42+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/持有并等待条件.png)
4343

4444

4545

4646
### 不可剥夺条件
4747

4848
不可剥夺条件是指,当线程已经持有了资源 ,**在自己使用完之前不能被其他线程获取**,线程 B 如果也想使用此资源,则只能在线程 A 使用完并释放后才能获取。
4949

50-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/不可剥夺条件.png)
50+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/不可剥夺条件.png)
5151

5252
### 环路等待条件
5353

54-
环路等待条件指都是,在死锁发生的时候,**两个线程获取资源的顺序构成了环形链**。
54+
环路等待条件指的是,在死锁发生的时候,**两个线程获取资源的顺序构成了环形链**。
5555

5656
比如,线程 A 已经持有资源 2,而想请求资源 1, 线程 B 已经获取了资源 1,而想请求资源 2,这就形成资源请求等待的环形图。
5757

58-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/环路等待条件.png)
58+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/环路等待条件.png)
5959

6060

6161
---
@@ -291,7 +291,7 @@ $2 = {__data = {__lock = 2, __count = 0, __owner = 87748, __nusers = 1, __kind =
291291

292292
所以我们只需将线程 B 改成以相同顺序的获取资源,就可以打破死锁了。
293293

294-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/资源有序分配.png)
294+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost4@main/操作系统/死锁/资源有序分配.png)
295295

296296
线程 B 函数改进后的代码如下:
297297

@@ -345,4 +345,4 @@ exit
345345

346346
***哈喽,我是小林,就爱图解计算机基础,如果觉得文章对你有帮助,欢迎微信搜索「小林coding」,关注后,回复「网络」再送你图解网络 PDF***
347347

348-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost3@main/其他/公众号介绍.png)
348+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost3@main/其他/公众号介绍.png)

‎os/4_process/pessim_and_optimi_lock.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ CAS 函数就把这两个步骤合并成一条硬件级指令,形成**原子
151151
服务端要怎么验证是否冲突了呢?通常方案如下:
152152

153153
- 由于发生冲突的概率比较低,所以先让用户编辑文档,但是浏览器在下载文档时会记录下服务端返回的文档版本号;
154-
- 当用户提交修改时,发给服务端的请求会带上原始文档版本号,服务器收到后将它与当前版本号进行比较,如果版本号一致则修改成功,否则提交失败。
154+
- 当用户提交修改时,发给服务端的请求会带上原始文档版本号,服务器收到后将它与当前版本号进行比较,如果版本号不一致则提交失败,如果版本号一致则修改成功,然后服务端版本号更新到最新的版本号。
155155

156156
实际上,我们常见的 SVN 和 Git 也是用了乐观锁的思想,先让用户编辑代码,然后提交的时候,通过版本号来判断是否产生了冲突,发生了冲突的地方,需要我们自己修改后,再重新提交。
157157

‎os/4_process/process_commu.md‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
直接开讲!
44

5-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/3-%E6%8F%90%E7%BA%B2.jpg)
5+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/3-%E6%8F%90%E7%BA%B2.jpg)
66

77
---
88

99
每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。
1010

11-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/4-%E8%BF%9B%E7%A8%8B%E7%A9%BA%E9%97%B4.jpg)
11+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/4-%E8%BF%9B%E7%A8%8B%E7%A9%BA%E9%97%B4.jpg)
1212

1313
Linux 内核提供了不少进程间通信的机制,我们来一起瞧瞧有哪些?
1414

@@ -69,7 +69,7 @@ int pipe(int fd[2])
6969
7070
这里表示创建一个匿名管道,并返回了两个描述符,一个是管道的读取端描述符 `fd[0]`,另一个是管道的写入端描述符 `fd[1]`。注意,这个匿名管道是特殊的文件,只存在于内存,不存于文件系统中。
7171
72-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/5-%E7%AE%A1%E9%81%93-pipe.jpg)
72+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/5-%E7%AE%A1%E9%81%93-pipe.jpg)
7373
7474
7575
其实,**所谓的管道,就是内核里面的一串缓存**。从管道的一段写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限。
@@ -78,23 +78,23 @@ int pipe(int fd[2])
7878
7979
我们可以使用 `fork` 创建子进程,**创建的子进程会复制父进程的文件描述符**,这样就做到了两个进程各有两个「 `fd[0]` 与 `fd[1]`」,两个进程就可以通过各自的 fd 写入和读取同一个管道文件实现跨进程通信了。
8080
81-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/6-%E7%AE%A1%E9%81%93-pipe-fork.jpg)
81+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/6-%E7%AE%A1%E9%81%93-pipe-fork.jpg)
8282
8383
管道只能一端写入,另一端读出,所以上面这种模式容易造成混乱,因为父进程和子进程都可以同时写入,也都可以读出。那么,为了避免这种情况,通常的做法是:
8484
8585
- 父进程关闭读取的 fd[0],只保留写入的 fd[1];
8686
- 子进程关闭写入的 fd[1],只保留读取的 fd[0];
8787
8888
89-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/7-%E7%AE%A1%E9%81%93-pipe-fork-%E5%8D%95%E5%90%91%E9%80%9A%E4%BF%A1.jpg)
89+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/7-%E7%AE%A1%E9%81%93-pipe-fork-%E5%8D%95%E5%90%91%E9%80%9A%E4%BF%A1.jpg)
9090
9191
所以说如果需要双向通信,则应该创建两个管道。
9292
9393
到这里,我们仅仅解析了使用管道进行父进程与子进程之间的通信,但是在我们 shell 里面并不是这样的。
9494
9595
在 shell 里面执行 `A | B`命令的时候,A 进程和 B 进程都是 shell 创建出来的子进程,A 和 B 之间不存在父子关系,它俩的父进程都是 shell。
9696
97-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/8-%E7%AE%A1%E9%81%93-pipe-shell.jpg)
97+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/8-%E7%AE%A1%E9%81%93-pipe-shell.jpg)
9898
9999
所以说,在 shell 里通过「`|`」匿名管道将多个命令连接在一起,实际上也就是创建了多个子进程,那么在我们编写 shell 脚本时,能使用一个管道搞定的事情,就不要多用一个管道,这样可以减少创建子进程的系统开销。
100100
@@ -134,7 +134,7 @@ int pipe(int fd[2])
134134
135135
**共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中**。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去,大大提高了进程间通信的速度。
136136
137-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/9-%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98.jpg)
137+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/9-%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98.jpg)
138138
139139
---
140140
@@ -155,7 +155,7 @@ P 操作是用在进入共享资源之前,V 操作是用在离开共享资源
155155
156156
接下来,举个例子,如果要使得两个进程互斥访问共享内存,我们可以初始化信号量为 `1`。
157157
158-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/10-%E4%BF%A1%E5%8F%B7%E9%87%8F-%E4%BA%92%E6%96%A5.jpg)
158+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/10-%E4%BF%A1%E5%8F%B7%E9%87%8F-%E4%BA%92%E6%96%A5.jpg)
159159
160160
具体的过程如下:
161161
@@ -171,7 +171,7 @@ P 操作是用在进入共享资源之前,V 操作是用在离开共享资源
171171
172172
那么这时候,就可以用信号量来实现多进程同步的方式,我们可以初始化信号量为 `0`。
173173
174-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/11-%E4%BF%A1%E5%8F%B7%E9%87%8F-%E5%90%8C%E6%AD%A5.jpg)
174+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/11-%E4%BF%A1%E5%8F%B7%E9%87%8F-%E5%90%8C%E6%AD%A5.jpg)
175175
176176
具体过程:
177177
@@ -257,7 +257,7 @@ int socket(int domain, int type, int protocal)
257257
258258
> 针对 TCP 协议通信的 socket 编程模型
259259
260-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/12-TCP%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B.jpg)
260+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/12-TCP%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B.jpg)
261261
262262
- 服务端和客户端初始化 `socket`,得到文件描述符;
263263
- 服务端调用 `bind`,将绑定在 IP 地址和端口;
@@ -276,7 +276,7 @@ int socket(int domain, int type, int protocal)
276276
277277
> 针对 UDP 协议通信的 socket 编程模型
278278
279-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/13-UDP%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B.jpg)
279+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/13-UDP%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B.jpg)
280280
281281
UDP 是没有连接的,所以不需要三次握手,也就不需要像 TCP 调用 listen 和 connect,但是 UDP 的交互仍然需要 IP 地址和端口号,因此也需要 bind。
282282
@@ -315,7 +315,7 @@ Linux 内核提供了不少进程间通信的方式,其中最简单的方式
315315
316316
那么,就需要**信号量**来保护共享资源,以确保任何时刻只能有一个进程访问共享资源,这种方式就是互斥访问。**信号量不仅可以实现访问的互斥性,还可以实现进程间的同步**,信号量其实是一个计数器,表示的是资源个数,其值可以通过两个原子操作来控制,分别是 **P 操作和 V 操作**。
317317
318-
与信号量名字很相似的叫**信号**,它俩名字虽然相似,但功能一点儿都不一样。信号是进程间通信机制中**唯一的异步通信机制**,信号可以在应用进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件,信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令),一旦有信号发生,**进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号**。有两个信号是应用进程无法捕捉和忽略的,即 `SIGKILL` 和 `SEGSTOP`,这是为了方便我们能在任何时候结束或停止某个进程。
318+
与信号量名字很相似的叫**信号**,它俩名字虽然相似,但功能一点儿都不一样。信号是**异步通信机制**,信号可以在应用进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件,信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令),一旦有信号发生,**进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号**。有两个信号是应用进程无法捕捉和忽略的,即 `SIGKILL` 和 `SIGSTOP`,这是为了方便我们能在任何时候结束或停止某个进程。
319319
320320
前面说到的通信机制,都是工作于同一台主机,如果**要与不同主机的进程间通信,那么就需要 Socket 通信了**。Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信,可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。
321321
@@ -330,6 +330,6 @@ Linux 内核提供了不少进程间通信的方式,其中最简单的方式
330330
331331
***哈喽,我是小林,就爱图解计算机基础,如果觉得文章对你有帮助,欢迎微信搜索「小林coding」,关注后,回复「网络」再送你图解网络 PDF***
332332
333-
![](https://cdn.jsdelivr.net/gh/xiaolincoder/ImageHost3@main/其他/公众号介绍.png)
333+
![](https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost3@main/其他/公众号介绍.png)
334334
335335
----

0 commit comments

Comments
 (0)