当前位置: 首页 > article >正文

1.24 共享内存和信号灯集

使用共享内存+信号灯集实现两个进程之间相互对话。

程序代码:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stst.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <sys/sem.h>
#include <sys/un.h>

#define SHM_SIZE 1024
#define KEY 1234
#define SEM_KEY 5678

// 信号灯操作函数
void sem_op(int semid, int num, int op) {
    struct sembuf sb;
    sb.sem_num = num;
    sb.sem_op = op;
    sb.sem_flg = 0;
    if (semop(semid, &sb, 1) == -1) {
        perror("semop");
        exit(EXIT_FAILURE);
    }
}

// 发送进程
void sender() {
    int shmid, semid;
    char *shmaddr;

    // 创建共享内存
    if ((shmid = shmget(KEY, SHM_SIZE, IPC_CREAT | 0666)) == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    // 附加共享内存
    if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    // 创建信号灯集
    if ((semid = semget(SEM_KEY, 2, IPC_CREAT | 0666)) == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    // 初始化信号灯
    if (semctl(semid, 0, SETVAL, 1) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
    if (semctl(semid, 1, SETVAL, 0) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    char message[SHM_SIZE];
    while (1) {
        // 等待可以发送消息
        sem_op(semid, 0, -1);

        printf("Sender: ");
        fgets(message, SHM_SIZE, stdin);
        if (strncmp(message, "quit", 4) == 0) {
            strcpy(shmaddr, "quit");
            sem_op(semid, 1, 1);
            break;
        }
        strcpy(shmaddr, message);

        // 通知接收进程有新消息
        sem_op(semid, 1, 1);
    }

    // 分离共享内存
    if (shmdt(shmaddr) == -1) {
        perror("shmdt");
        exit(EXIT_FAILURE);
    }
}

// 接收进程
void receiver() {
    int shmid, semid;
    char *shmaddr;

    // 获取共享内存
    if ((shmid = shmget(KEY, SHM_SIZE, 0666)) == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    // 附加共享内存
    if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    // 获取信号灯集
    if ((semid = semget(SEM_KEY, 2, 0666)) == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    while (1) {
        // 等待有新消息
        sem_op(semid, 1, -1);

        if (strncmp(shmaddr, "quit", 4) == 0) {
            break;
        }
        printf("Receiver: %s", shmaddr);

        // 通知发送进程可以继续发送
        sem_op(semid, 0, 1);
    }

    // 分离共享内存
    if (shmdt(shmaddr) == -1) {
        perror("shmdt");
        exit(EXIT_FAILURE);
    }

    // 删除共享内存和信号灯集
    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
        perror("shmctl");
        exit(EXIT_FAILURE);
    }
    if (semctl(semid, 0, IPC_RMID) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }
}

int main() {
    pid_t pid;

    // 创建子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程作为接收进程
        receiver();
    } else {
        // 父进程作为发送进程
        sender();
    }

    return 0;
}


http://www.kler.cn/a/518425.html

相关文章:

  • 【flutter版本升级】【Nativeshell适配】nativeshell需要做哪些更改
  • Linux系统之gzip命令的基本使用
  • MATLAB提供的颜色映射表colormap——伪彩色
  • 【C语言算法刷题】第2题 图论 dijkastra
  • 【软件架构】软件的十二种架构简介
  • RabbitMQ 多种安装模式
  • SSM框架探秘:Spring 整合 SpringMVC 框架
  • 神经网络基础 | 给定条件下推导对应的卷积层参数
  • 图神经网络系列论文阅读DAY1:《Predicting Tweet Engagement with Graph Neural Networks》
  • tomcat的accept-count、max-connections、max-threads三个参数的含义
  • 【openwrt】openwrt odhcpd IPv6 prefix_filter选项说明
  • Google Protocol Buffers的.NET与Python
  • Python之百度财务数据可视化分析
  • 7-Zip高危漏洞CVE-2025-0411 poc 攻击者可绕过安全机制远程执行代码
  • WPF 使用iconfont
  • Sentinel 控制台集成 Nacos 实现规则配置双向同步和持久化存储(提供改造后源码)
  • DRF开发避坑指南01
  • Ubuntu20.04 运行 PL-VIO
  • BoosterX:电脑加速的智能管家,便携、绿色、操作简单
  • NVIDIA JetPack 6.2 为 NVIDIA Jetson Orin Nano 和 Jetson Orin NX 模块带来了超级模式
  • NIO | 什么是Java中的NIO —— 结合业务场景理解 NIO (二)
  • FPGA实现光纤通信(3)——光纤8b/10b编码数据回环
  • [C++技能提升]类注册
  • 大数据k-means聚类算法:基于k-means聚类算法+NLP微博舆情数据爬虫可视化分析推荐系统
  • FireCrawl开源 AI 网络爬虫工具,自动爬取网站及子页面内容,预处理为结构化数据
  • JVM面试题解,垃圾回收之“分代回收理论”剖析