feat: 增加进程基本部分
This commit is contained in:
parent
100231852c
commit
6031dc3198
|
|
@ -1,221 +0,0 @@
|
|||
## 图论常见算法
|
||||
|
||||
### Dijkstra算法
|
||||
用于求解单个源最短路问题:
|
||||
|
||||
1. 初始化:将所有顶点的距离设为正无穷,源顶点设为0;
|
||||
2. 迭代:从源顶点出发,遍历所有边,更新顶点的距离;
|
||||
3. 检验:检查是否存在负权重环,如果有则返回错误;
|
||||
4. 返回:返回所有顶点的距离。
|
||||
|
||||
|
||||
|
||||
### Bellman-Ford算法
|
||||
|
||||
#### 数学公式
|
||||
|
||||
对于图 $G=(V,E)$,Bellman-Ford算法通过迭代松弛更新每个顶点的最短路径估计:
|
||||
|
||||
$$d(v) = \min\{d(u) + w(u,v) | (u,v) \in E\}$$
|
||||
|
||||
其中:
|
||||
- $d(v)$ 是从源顶点到顶点 $v$ 的最短路径估计
|
||||
- $w(u,v)$ 是边 $(u,v)$ 的权重
|
||||
- 迭代次数最多为 $|V|-1$ 次
|
||||
|
||||
#### Python实现
|
||||
|
||||
```python
|
||||
def bellman_ford(graph, source):
|
||||
"""
|
||||
Bellman-Ford算法求单源最短路径
|
||||
|
||||
参数:
|
||||
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
|
||||
source: 源顶点
|
||||
|
||||
返回:
|
||||
distances: 各顶点到源顶点的最短距离
|
||||
"""
|
||||
# 初始化距离
|
||||
distances = {v: float('inf') for v in graph}
|
||||
distances[source] = 0
|
||||
|
||||
# 获取所有顶点
|
||||
vertices = list(graph.keys())
|
||||
|
||||
# 最多进行 |V|-1 次迭代
|
||||
for _ in range(len(vertices) - 1):
|
||||
# 对每条边进行松弛操作
|
||||
for u in graph:
|
||||
for v, w in graph[u]:
|
||||
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||
distances[v] = distances[u] + w
|
||||
|
||||
# 检测负权重环
|
||||
for u in graph:
|
||||
for v, w in graph[u]:
|
||||
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||
raise ValueError("图中存在负权重环")
|
||||
|
||||
return distances
|
||||
|
||||
|
||||
# 示例使用
|
||||
if __name__ == "__main__":
|
||||
# 构建图 (邻接表)
|
||||
graph = {
|
||||
'A': [('B', 4), ('C', 2)],
|
||||
'B': [('C', 3), ('D', 2), ('E', 3)],
|
||||
'C': [('B', 1), ('D', 4)],
|
||||
'D': [('E', -5)], # 负权重边
|
||||
'E': []
|
||||
}
|
||||
|
||||
try:
|
||||
distances = bellman_ford(graph, 'A')
|
||||
print("Bellman-Ford 结果:", distances)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常用算法Python实现
|
||||
|
||||
### 1. Dijkstra算法
|
||||
|
||||
#### 数学公式
|
||||
|
||||
Dijkstra算法维护一个优先队列,每次选取具有最小距离估计的顶点:
|
||||
|
||||
$$d(v) = \min_{u \in S} \{ d(u) + w(u,v) \}$$
|
||||
|
||||
其中 $S$ 是已确定最短路径的顶点集合。
|
||||
|
||||
#### Python实现
|
||||
|
||||
```python
|
||||
import heapq
|
||||
|
||||
def dijkstra(graph, source):
|
||||
"""
|
||||
Dijkstra算法求单源最短路径
|
||||
|
||||
参数:
|
||||
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
|
||||
source: 源顶点
|
||||
|
||||
返回:
|
||||
distances: 各顶点到源顶点的最短距离
|
||||
"""
|
||||
# 初始化距离
|
||||
distances = {v: float('inf') for v in graph}
|
||||
distances[source] = 0
|
||||
|
||||
# 优先队列: (距离, 顶点)
|
||||
pq = [(0, source)]
|
||||
visited = set()
|
||||
|
||||
while pq:
|
||||
# 取出最小距离的顶点
|
||||
current_dist, u = heapq.heappop(pq)
|
||||
|
||||
# 如果已访问则跳过
|
||||
if u in visited:
|
||||
continue
|
||||
visited.add(u)
|
||||
|
||||
# 更新邻接顶点的距离
|
||||
for v, w in graph.get(u, []):
|
||||
if v not in visited and current_dist + w < distances[v]:
|
||||
distances[v] = current_dist + w
|
||||
heapq.heappush(pq, (distances[v], v))
|
||||
|
||||
return distances
|
||||
|
||||
|
||||
# 示例使用
|
||||
if __name__ == "__main__":
|
||||
# 构建图 (邻接表)
|
||||
graph = {
|
||||
'A': [('B', 4), ('C', 2)],
|
||||
'B': [('C', 3), ('D', 2), ('E', 3)],
|
||||
'C': [('B', 1), ('D', 4)],
|
||||
'D': [('E', 5)],
|
||||
'E': []
|
||||
}
|
||||
|
||||
distances = dijkstra(graph, 'A')
|
||||
print("Dijkstra 结果:", distances)
|
||||
# 输出: {'A': 0, 'B': 3, 'C': 2, 'D': 5, 'E': 8}
|
||||
```
|
||||
|
||||
### 2. Bellman-Ford算法
|
||||
|
||||
#### 数学公式
|
||||
|
||||
对于图 $G=(V,E)$,Bellman-Ford算法通过迭代松弛更新每个顶点的最短路径估计:
|
||||
|
||||
$$d(v) = \min\{d(u) + w(u,v) | (u,v) \in E\}$$
|
||||
|
||||
其中:
|
||||
- $d(v)$ 是从源顶点到顶点 $v$ 的最短路径估计
|
||||
- $w(u,v)$ 是边 $(u,v)$ 的权重
|
||||
- 迭代次数最多为 $|V|-1$ 次
|
||||
|
||||
#### Python实现
|
||||
|
||||
```python
|
||||
def bellman_ford(graph, source):
|
||||
"""
|
||||
Bellman-Ford算法求单源最短路径
|
||||
|
||||
参数:
|
||||
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
|
||||
source: 源顶点
|
||||
|
||||
返回:
|
||||
distances: 各顶点到源顶点的最短距离
|
||||
"""
|
||||
# 初始化距离
|
||||
distances = {v: float('inf') for v in graph}
|
||||
distances[source] = 0
|
||||
|
||||
# 获取所有顶点
|
||||
vertices = list(graph.keys())
|
||||
|
||||
# 最多进行 |V|-1 次迭代
|
||||
for _ in range(len(vertices) - 1):
|
||||
# 对每条边进行松弛操作
|
||||
for u in graph:
|
||||
for v, w in graph[u]:
|
||||
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||
distances[v] = distances[u] + w
|
||||
|
||||
# 检测负权重环
|
||||
for u in graph:
|
||||
for v, w in graph[u]:
|
||||
if distances[u] != float('inf') and distances[u] + w < distances[v]:
|
||||
raise ValueError("图中存在负权重环")
|
||||
|
||||
return distances
|
||||
|
||||
|
||||
# 示例使用
|
||||
if __name__ == "__main__":
|
||||
# 构建图 (邻接表)
|
||||
graph = {
|
||||
'A': [('B', 4), ('C', 2)],
|
||||
'B': [('C', 3), ('D', 2), ('E', 3)],
|
||||
'C': [('B', 1), ('D', 4)],
|
||||
'D': [('E', -5)], # 负权重边
|
||||
'E': []
|
||||
}
|
||||
|
||||
try:
|
||||
distances = bellman_ford(graph, 'A')
|
||||
print("Bellman-Ford 结果:", distances)
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
```
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
# 进程管理
|
||||
|
||||
## 1. 进程的组成
|
||||
|
||||
**进程(Process)** 是程序在一个数据集合上的一次执行过程,是系统进行资源分配和调度的基本单位。
|
||||
|
||||
进程的组成包括:
|
||||
|
||||
- **程序代码**:描述进程所要完成的功能
|
||||
- **数据集**:程序在执行时所需要的数据和工作区
|
||||
- **进程控制块(PCB)**:**进程存在的唯一标志**,包含以下信息:
|
||||
- 进程标识符(PID)
|
||||
- 进程状态
|
||||
- 进程优先级
|
||||
- CPU现场保护区(寄存器、程序计数器等)
|
||||
- 内存管理信息(页表/段表指针)
|
||||
- I/O状态信息
|
||||
- 记账信息
|
||||
- 调度信息
|
||||
|
||||
## 2. 进程内存映像
|
||||
|
||||
进程的内存空间布局(内存映像)从低地址到高地址依次为:
|
||||
|
||||
| 区域 | 说明 |
|
||||
|------|------|
|
||||
| **代码段(Text)** | 存放可执行代码,通常只读 |
|
||||
| **数据段(Data)** | 存放已初始化的全局变量和静态变量 |
|
||||
| **BSS段** | 存放未初始化的全局变量和静态变量(初始化为0) |
|
||||
| **堆(Heap)** | 动态分配内存,向上增长 |
|
||||
| **共享库** | 共享代码和数据 |
|
||||
| **栈(Stack)** | 存放函数调用、局部变量,向下增长 |
|
||||
| **环境/命令行参数** | 环境变量和命令行参数 |
|
||||
|
||||
## 3. 进程状态和转换
|
||||
|
||||
### 三状态模型
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 就绪: 创建
|
||||
就绪 --> 运行: 调度
|
||||
运行 --> 就绪: 时间片用完
|
||||
运行 --> 阻塞: 等待事件
|
||||
阻塞 --> 就绪: 事件完成
|
||||
运行 --> [*]: 终止
|
||||
```
|
||||
|
||||
- **创建态(New)**:进程正在被创建
|
||||
- **就绪态(Ready)**:已获得除CPU外的所有资源,等待CPU
|
||||
- **运行态(Running)**:正在CPU上执行
|
||||
- **阻塞态(Blocked/Waiting)**:因等待I/O或其他资源而暂停
|
||||
- **终止态(Terminated)**:进程执行完毕
|
||||
|
||||
### 五状态模型
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 创建: 新建进程
|
||||
创建 --> 就绪: 初始化完成
|
||||
就绪 --> 运行: 调度
|
||||
运行 --> 就绪: 时间片用完
|
||||
运行 --> 阻塞: 等待事件
|
||||
阻塞 --> 就绪: 事件完成
|
||||
运行 --> 终止: 退出
|
||||
终止 --> [*]: 释放资源
|
||||
```
|
||||
|
||||
在基本三状态基础上增加:
|
||||
- **创建态**:分配PCB,初始化资源
|
||||
- **终止态**:释放资源,保留PCB
|
||||
|
||||
### 七状态模型
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 创建: 新建进程
|
||||
创建 --> 就绪挂起: 创建完成
|
||||
创建 --> 就绪: 直接调入内存
|
||||
|
||||
就绪挂起 --> 就绪: 激活
|
||||
就绪 --> 就绪挂起: 挂起
|
||||
|
||||
就绪 --> 运行: 调度
|
||||
运行 --> 就绪: 时间片用完
|
||||
运行 --> 阻塞: 等待事件
|
||||
阻塞 --> 就绪: 事件完成
|
||||
|
||||
阻塞 --> 阻塞挂起: 挂起
|
||||
阻塞挂起 --> 阻塞: 激活
|
||||
|
||||
运行 --> 终止: 退出
|
||||
终止 --> [*]: 释放资源
|
||||
```
|
||||
|
||||
在五状态基础上增加挂起状态:
|
||||
- **就绪挂起**:在外存,准备调入内存
|
||||
- **阻塞挂起**:在外存,等待事件完成
|
||||
|
||||
## 4. 进程的通信
|
||||
|
||||
进程间通信(IPC,Inter-Process Communication)主要有以下方式:
|
||||
|
||||
### 4.1 高级通信方式
|
||||
|
||||
| 方式 | 说明 |
|
||||
|------|------|
|
||||
| **管道(Pipe)** | 半双工,用于父子/兄弟进程间通信 |
|
||||
| **命名管道(FIFO)** | 无亲缘关系的进程也可通信 |
|
||||
| **消息队列** | 消息链表,按类型优先級排队 |
|
||||
| **共享内存** | 多个进程共享同一块内存区域(最快) |
|
||||
| **信号量** | 计数器,用于进程同步 |
|
||||
| **套接字(Socket)** | 可用于不同主机间进程通信 |
|
||||
|
||||
### 4.2 低级通信方式
|
||||
|
||||
- **信号(Signal)**:异步通知机制
|
||||
|
||||
### 4.3 通信机制比较
|
||||
|
||||
| 机制 | 效率 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| 共享内存 | 最高 | 频繁数据交换 |
|
||||
| 管道/消息队列 | 中等 | 少量数据、顺序访问 |
|
||||
| 信号量 | 快 | 同步控制 |
|
||||
|
||||
## 5. 线程与多线程模型
|
||||
|
||||
### 5.1 线程的概念
|
||||
|
||||
**线程(Thread)** 是CPU调度的基本单位,是进程中的一个执行流。同一个进程中的线程共享进程的地址空间和资源。
|
||||
|
||||
### 5.2 线程与进程的区别
|
||||
|
||||
| 特征 | 进程 | 线程 |
|
||||
|------|------|------|
|
||||
| 资源拥有 | 独立资源 | 共享进程资源 |
|
||||
| 调度单位 | 进程 | 线程 |
|
||||
| 地址空间 | 独立地址空间 | 共享地址空间 |
|
||||
| 开销 | 大(创建/切换开销大) | 小(轻量级) |
|
||||
| 通信 | 需要IPC | 直接读写共享数据 |
|
||||
| 独立性 | 独立 | 依赖进程 |
|
||||
|
||||
### 5.3 线程的组成
|
||||
|
||||
每个线程拥有:
|
||||
- **线程ID**
|
||||
- **程序计数器(PC)**
|
||||
- **寄存器集合**
|
||||
- **栈**
|
||||
|
||||
线程共享:
|
||||
- **代码段、数据段**
|
||||
- **堆**
|
||||
- **文件描述符**
|
||||
- **信号处理器**
|
||||
- **当前工作目录**
|
||||
- **用户ID/组ID**
|
||||
|
||||
### 5.4 多线程模型
|
||||
|
||||
| 模型 | 说明 | 优点 | 缺点 |
|
||||
|------|------|------|------|
|
||||
| **多对一** | 多个用户线程映射到一个内核线程 | 效率高 | 一个线程阻塞导致整个进程阻塞 |
|
||||
| **一对一** | 每个用户线程映射到一个内核线程 | 并发性好 | 线程创建开销大,受限内核线程数 |
|
||||
| **多对多** | 多个用户线程映射到多个内核线程 | 综合两者优点 | 实现复杂 |
|
||||
|
||||
### 5.5 线程的状态
|
||||
|
||||
线程状态与进程类似:
|
||||
- **就绪**:已准备好运行
|
||||
- **运行**:正在CPU执行
|
||||
- **阻塞**:等待资源或事件
|
||||
- **终止**:执行完毕
|
||||
|
||||
### 5.6 线程的实现方式
|
||||
|
||||
1. **用户线程(User Thread)**:内核不知道线程存在,线程库管理
|
||||
2. **内核线程(Kernel Thread)**:OS直接支持,内核管理
|
||||
3. **轻量级进程(LWP)**:一对一模型中的中间层
|
||||
|
||||
---
|
||||
|
||||
> **核心要点**:
|
||||
> - PCB是进程存在的唯一标志
|
||||
> - 进程是资源分配单位,线程是CPU调度单位
|
||||
> - 线程共享进程资源,创建/切换开销小
|
||||
> - 进程通信需要IPC,线程间可直接通信
|
||||
Loading…
Reference in New Issue