3 changed files with 281 additions and 184 deletions
@ -0,0 +1,134 @@ |
|||||
|
# 共享内存 + 有名管道 实现无亲缘关系进程通信 |
||||
|
|
||||
|
## 问题概述 |
||||
|
原有的`shm_pc.c`是父子进程通信模型,使用匿名管道进行同步。需要将其修改为两个无亲缘关系进程间的通信模型,分别为生产者进程和消费者进程。 |
||||
|
|
||||
|
## 解决方案 |
||||
|
|
||||
|
### 1. 进程间通信方式选择 |
||||
|
- **共享内存**:用于高效传输大量数据(任务队列) |
||||
|
- **有名管道(FIFO)**:用于无亲缘关系进程间的同步信号传递 |
||||
|
- **信号量**:用于共享内存的互斥访问和任务队列的同步 |
||||
|
|
||||
|
### 2. 核心实现 |
||||
|
|
||||
|
#### 文件结构 |
||||
|
``` |
||||
|
1_shared_memory/ |
||||
|
├── shm_comm/ |
||||
|
│ ├── shm_comm_a.c # 生产者进程 |
||||
|
│ └── shm_comm_b.c # 消费者进程 |
||||
|
``` |
||||
|
|
||||
|
#### 主要功能 |
||||
|
|
||||
|
##### shm_comm_a.c (生产者) |
||||
|
- 创建共享内存(包含环形任务队列) |
||||
|
- 创建有名管道用于同步 |
||||
|
- 向共享内存提交5个测试任务 |
||||
|
- 发送同步信号通知消费者进程 |
||||
|
- 等待消费者处理完成后销毁共享内存 |
||||
|
|
||||
|
##### shm_comm_b.c (消费者) |
||||
|
- 等待并打开有名管道 |
||||
|
- 接收生产者的同步信号 |
||||
|
- 挂载共享内存 |
||||
|
- 创建线程池处理任务 |
||||
|
- 完成所有任务后退出 |
||||
|
|
||||
|
### 3. 关键技术点 |
||||
|
|
||||
|
#### 环形任务队列 |
||||
|
```c |
||||
|
// 共享内存核心结构体 |
||||
|
typedef struct { |
||||
|
Task task_queue[MAX_TASK]; // 共享任务队列 |
||||
|
int front; // 队列头 |
||||
|
int rear; // 队列尾 |
||||
|
int sem_id; // 信号量集ID |
||||
|
} SharedMem; |
||||
|
|
||||
|
// 入队操作(生产者) |
||||
|
shm->rear = (shm->rear + 1) % MAX_TASK; |
||||
|
shm->task_queue[shm->rear] = task; |
||||
|
|
||||
|
// 出队操作(消费者) |
||||
|
Task task = shm->task_queue[shm->front]; |
||||
|
shm->front = (shm->front + 1) % MAX_TASK; |
||||
|
``` |
||||
|
|
||||
|
#### 信号量机制 |
||||
|
- **互斥信号量**(索引0):保护共享内存的互斥访问 |
||||
|
- **空信号量**(索引1):表示队列中的任务数量,初始值为0 |
||||
|
- **满信号量**(索引2):表示队列中的空闲位置数量,初始值为MAX_TASK |
||||
|
|
||||
|
#### 有名管道同步 |
||||
|
```c |
||||
|
// 生产者创建有名管道 |
||||
|
mkfifo(FIFO_PATH, 0666); |
||||
|
|
||||
|
// 生产者发送同步信号 |
||||
|
int fifo_fd = open(FIFO_PATH, O_WRONLY); |
||||
|
write(fifo_fd, "ok", 2); |
||||
|
|
||||
|
// 消费者接收同步信号 |
||||
|
int fifo_fd = open(FIFO_PATH, O_RDONLY); |
||||
|
read(fifo_fd, buf, 2); |
||||
|
``` |
||||
|
|
||||
|
### 4. 编译和运行 |
||||
|
|
||||
|
#### 编译命令 |
||||
|
```bash |
||||
|
gcc -o shm_comm_a shm_comm_a.c -lpthread |
||||
|
gcc -o shm_comm_b shm_comm_b.c -lpthread |
||||
|
``` |
||||
|
|
||||
|
#### 运行步骤 |
||||
|
1. 启动生产者进程: |
||||
|
```bash |
||||
|
./shm_comm_a |
||||
|
``` |
||||
|
|
||||
|
2. 启动消费者进程: |
||||
|
```bash |
||||
|
./shm_comm_b |
||||
|
``` |
||||
|
|
||||
|
### 5. 测试结果 |
||||
|
|
||||
|
生产者进程输出: |
||||
|
``` |
||||
|
[生产者进程] 启动,创建共享内存... |
||||
|
[生产者进程] 已发送同步信号:ok |
||||
|
[提交进程] 提交任务1:测试任务_1 |
||||
|
[提交进程] 提交任务2:测试任务_2 |
||||
|
[提交进程] 提交任务3:测试任务_3 |
||||
|
[提交进程] 提交任务4:测试任务_4 |
||||
|
[提交进程] 提交任务5:测试任务_5 |
||||
|
[生产者进程] 退出 |
||||
|
``` |
||||
|
|
||||
|
消费者进程输出: |
||||
|
``` |
||||
|
[消费者进程] 收到生产者同步信号:ok |
||||
|
[消费者进程] 启动,创建线程池... |
||||
|
[线程140408006018816] 取出任务1:测试任务_1 |
||||
|
[线程140407997626112] 取出任务2:测试任务_2 |
||||
|
[线程140407989233408] 取出任务3:测试任务_3 |
||||
|
[线程140407980840704] 取出任务4:测试任务_4 |
||||
|
[线程140408006018816] 取出任务5:测试任务_5 |
||||
|
[消费者进程] 停止线程池... |
||||
|
[消费者进程] 退出 |
||||
|
``` |
||||
|
|
||||
|
## 总结 |
||||
|
|
||||
|
本实现成功将父子进程通信模型修改为无亲缘关系进程通信: |
||||
|
1. 使用**有名管道**替代匿名管道实现进程同步 |
||||
|
2. 保持了**共享内存**的高效数据传输特性 |
||||
|
3. 维护了**环形任务队列**的高效空间利用 |
||||
|
4. 通过**信号量**确保了共享资源的安全访问 |
||||
|
5. 实现了**线程池**的多任务并行处理 |
||||
|
|
||||
|
测试结果表明,两个无亲缘关系的进程能够稳定通信并正确处理任务。 |
||||
Loading…
Reference in new issue