【网络应用程序设计】实验二:进程间的协调通信

个人博客:https://alive0103.github.io/
代码在GitHub:https://github.com/Alive0103/XDU-CS-lab
能点个Star就更好了,欢迎来逛逛哇~❣

主播写的刚够满足基本功能,多有不足,仅供参考,还请提PR指正,很高兴能帮到你

一、 实验内容

在linux平台上实现1个父进程、10个以上子进程,其中一些子进程具有特定任务(如完成:显示、计算、报警等),各进程之间利用管道、信号灯和共享内存实现数据传送。

实验目的
掌握Linux平台下进程创建与控制方法
理解管道(Pipe)、共享内存(Shared Memory)和信号量(Semaphore)三种IPC机制
实现多进程协作系统架构设计
验证进程间数据同步与互斥控制的正确性

实验原理

进程架构设计

graph TD
    Parent[父进程] -->|管道| Calc[计算进程x4]
    Parent -->|共享内存| Display[显示进程x3]
    Calc -->|共享内存| Alert[报警进程x3]
    Alert -->|管道| Parent

IPC机制对比

在这里插入图片描述

实验步骤

环境搭建

# 创建实验目录
mkdir ~/ipc-lab && cd ~/ipc-lab

# 安装开发工具
sudo apt install -y g++ make

# 验证内核支持
cat /proc/sys/kernel/shmmax  # 显示共享内存最大尺寸

关键代码实现

进程创建模块

for (int i = 0; i < CHILD_NUM; ++i) {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程分工控制
        if (i < 4) calc_worker();
        else if (i < 7) display_worker();
        else alert_worker();
        exit(0);
    }
}

共享内存控制模块

// 创建共享内存
int shmid = shmget(key, sizeof(SharedData), IPC_CREAT|0666);

// 内存映射
SharedData* shared = (SharedData*)shmat(shmid, NULL, 0);

// 资源释放
shmdt(shared);
shmctl(shmid, IPC_RMID, NULL);

完整代码

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <cstring>
#include <fcntl.h>

#define THRESHOLD 100

struct SharedData {
    int calculation;
    bool alarm_status;
};

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

void P(int semid) {
    struct sembuf op = {0, -1, SEM_UNDO};
    semop(semid, &op, 1);
}

void V(int semid) {
    struct sembuf op = {0, 1, SEM_UNDO};
    semop(semid, &op, 1);
}

int main() {
    // 创建IPC key
    key_t key = ftok("keyfile", 65);
    
    // 共享内存初始化
    int shmid = shmget(key, sizeof(SharedData), IPC_CREAT|0666);
    SharedData* shared = static_cast<SharedData*>(shmat(shmid, nullptr, 0));
    shared->calculation = 0;
    shared->alarm_status = false;

    // 信号量初始化
    int semid = semget(key, 1, IPC_CREAT|0666);
    union semun arg;
    arg.val = 1;
    semctl(semid, 0, SETVAL, arg);

    // 创建通信管道
    int data_pipe[2], alert_pipe[2];
    pipe(data_pipe);
    pipe(alert_pipe);

    const int CHILD_NUM = 10;
    for (int i = 0; i < CHILD_NUM; ++i) {
        pid_t pid = fork();
        if (pid == 0) {
            // 计算进程 (0-3)
            if (i < 4) {
                close(data_pipe[1]);  // 关闭写端
                int input;
                while (read(data_pipe[0], &input, sizeof(input)) > 0) {
                    P(semid);
                    shared->calculation = input * 2;
                    V(semid);
                }
                exit(0);
            }
            // 显示进程 (4-6)
            else if (i < 7) {
                while (true) {
                    P(semid);
                    std::cout << "Current Value: " << shared->calculation 
                              << "\tAlarm: " << (shared->alarm_status ? "TRIGGERED" : "NORMAL")
                              << std::endl;
                    V(semid);
                    sleep(1);
                }
            }
            // 报警进程 (7-9)
            else {
                close(alert_pipe[0]);  // 关闭读端
                while (true) {
                    P(semid);
                    if (shared->calculation > THRESHOLD && !shared->alarm_status) {
                        shared->alarm_status = true;
                        const char* msg = "VALUE EXCEEDED THRESHOLD!";
                        write(alert_pipe[1], msg, strlen(msg)+1);
                    } else if (shared->calculation <= THRESHOLD) {
                        shared->alarm_status = false;
                    }
                    V(semid);
                    sleep(1);
                }
            }
        }
    }

    // 父进程逻辑
    close(data_pipe[0]);
    close(alert_pipe[1]);

    // 发送测试数据
    for (int i = 1; i <= 10; ++i) {
        int val = i * 20;
        write(data_pipe[1], &val, sizeof(val));
        sleep(2);
    }

    // 接收报警信息
    char alert_msg[256];
    while (read(alert_pipe[0], alert_msg, sizeof(alert_msg)) > 0) {
        std::cout << "\n[ALERT] " << alert_msg << std::endl;
    }

    // 清理资源
    wait(nullptr);
    shmdt(shared);
    shmctl(shmid, IPC_RMID, nullptr);
    semctl(semid, 0, IPC_RMID);
    close(data_pipe[1]);
    close(alert_pipe[0]);

    return 0;
}

实验结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alive~o.0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值