实验3:利用Linux的消息队列通信机制实现三个线程间的通信

news2024/9/20 16:49:01

调用原型

POSIX信号量–无名信号量

POSIX信号量是Pthread线程库提供的一种同步机制,包括无名信号量和有名信号量两种机制。无名信号量,常用于多线程间的同步,也可用于相关进程间的同步(需置于相关进程间的共享内存区中)。有名信号量通过IPC名字进行进程间的同步,特点是把信号量保存在文件中,可用于线程、相关进程和不相关进程间的同步。

#include <semaphore.h>
int sem_init(sem_t *sem,int pshared,unsigned int value)

创建无名信号量,sem(信号量名称),pshared一般为0(多线程间的同步),value(信号量的初始值)

int sem_wait(sem_t *sem)

阻塞申请资源

int sem_post(sem_t *sem)

释放资源

IPC消息队列通信机制

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
消息缓冲区struct msgbuf

需重新定义

struct msgbuf{
    long mtype;
    char mytext[1024];
}
int msgget(key_t key,int msgflag)

创建消息队列

int msgnd(int msqid,struct msgbuf* msgp,size_t msgsz,int msgflg)

发送消息

ssize_t msgrcv(int msqid,struct msgbuf* msgp,size_t msgsz,long msgtyp,int msgflg)

接收消息

int msgctl(int msqid,int cmd,struct msqid_ds* buf)

删除消息队列

Pthread线程库

#include <pthread.h>
pthread_create()

创建线程

pthread_join()

阻塞等待进程

pthread_exit()

线程结束

具体实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <unistd.h>

sem_t mutex_que;
sem_t over1,over2;
sem_t s_server,r_server;
sem_t msgid_mutex;

int msgid=-1;

struct msgbuf
{
    long mtype;
    char mytext[1024];
};

void* sender1(){
    int flag1=1;
    struct msgbuf buf;
    int error;
    while(flag1){
        memset(&buf,0,sizeof(buf));
        sem_wait(&s_server);
        sem_wait(&msgid_mutex);
        if(msgid==-1){
            msgid=msgget(0,IPC_CREAT);
            if(msgid==-1){
                printf("message queue error --sender1\n");
                sem_post(&msgid_mutex);
                exit(1);
            }
        }
        sem_post(&msgid_mutex);
        sem_wait(&mutex_que);
        printf("sender1> ");
        scanf("%s",buf.mytext);
        buf.mtype=1;
        if(!strncmp(buf.mytext,"exit",4)){
            flag1=0;
            strcpy(buf.mytext,"end1");
        }else{
            strcat(buf.mytext," --sender1");
        }
        error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);
        if(error==-1){
            printf("sender1 message send error\n");
            sem_post(&mutex_que);
            exit(1);
        }
        sem_post(&mutex_que);
        sem_post(&r_server);
    }
    //wait for signal over
    sem_wait(&s_server);
    sem_wait(&over1);
    sem_wait(&mutex_que);
    error=msgrcv(msgid,&buf,sizeof(buf.mytext),2,IPC_NOWAIT);
    if(!strncmp(buf.mytext,"over1",5)){
        printf("sender1: ");
        printf("%s --receiver\n",buf.mytext);
        sem_post(&mutex_que);
        sem_post(&s_server);
        pthread_exit(NULL);
    }
}

void* sender2(){
    int flag2=1;
    struct msgbuf buf;
    int error;
    while(flag2){
        memset(&buf,0,sizeof(buf));
        sem_wait(&s_server);
        sem_wait(&msgid_mutex);
        if(msgid==-1){
            sem_post(&s_server);
            sem_post(&msgid_mutex);
            continue;
        }
        sem_post(&msgid_mutex);
        sem_wait(&mutex_que);
        printf("sender2> ");
        scanf("%s",buf.mytext);
        buf.mtype=1;
        if(!strncmp(buf.mytext,"exit",4)){
            flag2=0;
            strcpy(buf.mytext,"end2");
        }else{
            strcat(buf.mytext," --sender2");
        }
        error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);
        if(error==-1){
            printf("sender2 message send error\n");
            sem_post(&mutex_que);
            exit(1);
        }
        sem_post(&mutex_que);
        sem_post(&r_server);
    }
    //wait for signal over
    sem_post(&s_server);
    sem_wait(&over2);
    sem_wait(&mutex_que);
    error=msgrcv(msgid,&buf,sizeof(buf.mytext),2,IPC_NOWAIT);
    if(!strncmp(buf.mytext,"over2",5)){
        printf("sender2: ");
        printf("%s --receiver\n",buf.mytext);
        sem_post(&mutex_que);
        sem_post(&s_server);
        pthread_exit(NULL);
    }
}

void* receiver(){
    int flag1=1;
    int flag2=1;
    struct msgbuf buf;
    int error;
    while(flag1!=0||flag2!=0){
        memset(&buf,0,sizeof(buf));
        sem_wait(&r_server);
        sem_wait(&mutex_que);
        error=msgrcv(msgid,&buf,sizeof(buf.mytext),1,IPC_NOWAIT);
        if(flag1&&!strncmp(buf.mytext,"end1",5)){
            memset(&buf,0,sizeof(buf));
            strcpy(buf.mytext,"over1");
            buf.mtype=2;
            error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);
            if(error==-1){
                printf("receiver send message error\n");
                sem_post(&mutex_que);
                exit(1);
            }
            sem_post(&over1);
            sem_post(&mutex_que);
            sem_post(&s_server);
            flag1=0;
        }else{
            if(flag2&&!strncmp(buf.mytext,"end2",5)){
                memset(&buf,0,sizeof(buf));
                strcpy(buf.mytext,"over2");
                buf.mtype=2;
                error=msgsnd(msgid,&buf,sizeof(buf.mytext),IPC_NOWAIT);
                if(error==-1){
                    printf("receiver send message error\n");
                    sem_post(&mutex_que);
                    exit(1);
                }
                sem_post(&over2);
                flag2=0;
                sem_post(&mutex_que);
                sem_post(&s_server);
            }
            else{
                if(strlen(buf.mytext)!=0){
                    printf("receive: %s \n",buf.mytext);
                    sem_post(&mutex_que);
                    sem_post(&s_server);
                }
            }
        }
    }
    printf("all end\n");
}

int main(){
    sem_init(&msgid_mutex,0,1);
    sem_init(&mutex_que,0,1);
    sem_init(&over1,0,0);
    sem_init(&over2,0,0);
    sem_init(&s_server,0,1);
    sem_init(&r_server,0,0);

    pthread_t s1,s2,r;
    int error;
    error=pthread_create(&s1,NULL,sender1,NULL);
    if(error!=0){
        printf("sender1 create error\n");
        exit(1);
    }
    error=pthread_create(&s2,NULL,sender2,NULL);
    if(error!=0){
        printf("sender2 create error\n");
        exit(1);
    }
    error=pthread_create(&r,NULL,receiver,NULL);
    if(error!=0){
        printf("receiver create error\n");
        exit(1);
    }

    //block wait threads end
    pthread_join(s1,NULL);
    pthread_join(s2,NULL);
    pthread_join(r,NULL);

    //delete message queue
    msgctl(msgid,IPC_RMID,0);
    //delete sem
    return 0;
}

实现效果

在这里插入图片描述

参考

1.参考实现
https://blog.csdn.net/CPromise/article/details/127929525
2.API手册
https://www.bookstack.cn/read/linuxapi/SUMMARY.md
3.sem信号量
https://blog.csdn.net/qq_19923217/article/details/82902442

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1422113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React、React Router、JSX 简单入门快速上手

React、React Router、JSX 简单入门快速上手 介绍特点 JSX使用js表达式渲染列表样式控制注意事项 入门脚手架创建react项目安装目录介绍入口文件解析 组件解析介绍函数式组件类组件 事件绑定注意点定义使用事件对象事件处理函数接收额外参数 组件状态状态的定义使用 组件通信父…

金蝶云星空RCE漏洞合集(多接口批量检测)

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

IntelliJ Idea实用插件推荐

目录 一、插件安装 二、常用插件 A、代码规范 Alibaba Java Coding Guidelines SonarLint B、快捷开发 aiXcoder-AI代码生成 AWS Toolkit-AI代码生成 CodeGeeX-AI代码生成 CodeGlance-代码缩略图 camelCase-格式转换 GsonFormatPlus-json代码生成 Sequence Giagram…

从搜索引擎到答案引擎:LLM驱动的变革

在过去的几周里&#xff0c;我一直在思考和起草这篇文章&#xff0c;认为谷歌搜索正处于被颠覆的边缘&#xff0c;它实际上可能会影响 SEO 作为业务牵引渠道的可行性。 考虑到谷歌二十多年来的完全统治地位&#xff0c;以及任何竞争对手都完全无力削弱它&#xff0c;坦率地说&…

微信活动投票小程序源码系统:自主创建活动小程序带完整的安装代码包以及搭建教程

微信小程序的日益普及&#xff0c;越来越多的企业和个人开始关注如何利用小程序进行活动推广和用户互动。在这个背景下&#xff0c;微信活动投票小程序源码系统应运而生。这款源码系统旨在帮助用户快速创建自己的活动投票小程序&#xff0c;降低技术门槛&#xff0c;提高开发效…

代理模式(静态代理、JDK 动态代理、CGLIB 动态代理)

代理模式(静态代理、JDK 动态代理、CGLIB 动态代理) 一、代理模式概述1. 生活中的代理案例2. 为什么要使用代理3. 代理模式在 Java 中的应用4. 概述5. 生活中代理图示二、代理的实现方式1. Java 中代理图示2. 静态代理2.1 案例2.2 实现案例2.3 静态代理存在的问题三、动态代理…

centOS+nodejs+mysql阿里云部署前后端个人网站

centOSnodejsmysql阿里云部署前后端个人网站 参考&#xff1a; 部署NodeExpressMySQL项目到阿里云轻量应用服务器 阿里云轻量应用服务器部署Node.jsReactMongoDB前后端分离项目 参考&#xff1a;在阿里云上部署nodejs服务 https 部署的原理就是你在本地测试的时候在地址栏&am…

FileViewer纯前端预览项目Vue2 demo

FileViewer 项目Vue2 demo 本demo基于vue-clijsvue2.x构建&#xff0c;如果您需要vue3版本的demo&#xff0c;请前往main分支。 适用于Vue2 Webpack&#xff0c;本集成方法要求最低Webpack版本为5&#xff0c;也就是Vue Cli Service 5.0.0以上&#xff0c;当然&#xff0c;if…

万户 ezOFFICE wpsservlet SQL注入漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

Word莫名其妙开启兼容模式将其永久取消的方法

这是因为Word模板文件被意外更改了 找到Word模板文件&#xff0c;目录在C:\Users\15976\AppData\Roaming\Microsoft\Templates 15976替换成你自己的用户名&#xff0c;不确定的就先点进C/Users看一看&#xff0c; AppData是隐藏文件夹&#xff0c;显示隐藏文件夹才能看见&am…

腾讯云SSL证书在阿里云添加域名DNS解析

场景说明 在阿里云申请并备案了域名&#xff0c;这个域名理论上可以在任何服务器上进行绑定。应用服务器部署到腾讯云&#xff0c;并在腾讯云申请了SSL证书&#xff0c;从而完成HTTPS转化。那么问题来了&#xff0c;腾讯提供的免费版SSL证书是一年有效期&#xff0c;到期后就需…

EVAP-COND蒸发器和冷凝器设计软件

EVAP-COND蒸发器和冷凝器设计软件 是一个软件包&#xff0c;其中包含NIST的翅片管蒸发器和冷凝器仿真模型。“逐管”建模方案允许指定复杂的制冷剂回路&#xff0c;对这些回路之间的制冷剂分配进行建模&#xff0c;并考虑到不均匀的空气分配。模拟结果包括每个管的局部参数&…

MyBatis常见面试题汇总

说一下MyBatis执行流程&#xff1f; MyBatis是一款优秀的基于Java的持久层框架&#xff0c;它内部封装了JDBC&#xff0c;使开发者只需要关注SQL语句本身&#xff0c;而不需要花费精力去处理加载驱动、创建连接等的过程&#xff0c;MyBatis的执行流程如下&#xff1a; 加载配…

单片机开发通用功能组件

mcu_reuse_development_module 单片机可复用、可通用开发组件&#xff0c;是以中间件思想开发的一套功能模块&#xff0c;将具有代表性或使用次数较多的功能和协议栈封装为独立的组件供开发者使用&#xff0c;开发者仅需通过组件提供的接口对接驱动层和应用层即可使用组件功能…

科微/金航标kinghelm一直在技术上不断创新

宋仕强说&#xff0c;萨科微slkor&#xff08;www.slkoric.com&#xff09;/金航标kinghelm&#xff08;www.kinghelm.net&#xff09;一直在技术上不断创新&#xff0c;并将这些新技术应用于公司的产品中&#xff0c;推出的新产品&#xff0c;这让我们比同行发展快一些&#x…

【论文阅读|小目标分割算法ASF-YOLO】

论文阅读|小目标分割算法ASF-YOLO 摘要&#xff08;Abstract&#xff09;1 引言&#xff08;Introduction&#xff09;2 相关工作&#xff08;Related work&#xff09;2.1 细胞实例分割&#xff08;Cell instance segmentation&#xff09;2.2 改进的YOLO用于实例分割&#xf…

[机器学习]TF-IDF算法

一.TF-IDF算法概述 什么是TF-IDF&#xff1f; 词频-逆文档频率&#xff08;Term Frequency-Inverse Document Frequency&#xff0c;TF-IDF&#xff09;是一种常用于文本处理的统计方法&#xff0c;可以评估一个单词在一份文档中的重要程度。简单来说就是可以用于文档关键词的提…

postgresql 查询缓慢原因分析

pg_stat_activity 最近发现系统运行缓慢&#xff0c;查询数据老是超时&#xff0c;于是排查下pg_stat_activity 系统表&#xff0c;看看有没有耗时的查询sql SELECT pid, state, query, query_start, backend_type FROM pg_stat_activity WHERE state active AND query LIK…

C#用正则表达式验证格式:电话号码、密码、邮编、手机号码、身份证、指定的小数点后位数、有效月、有效日

正则表达式在程序设计中有着重要的位置&#xff0c;经常被用于处理字符串信息。 用Regex类的IsMatch方法&#xff0c;使用正则表达式可以验证电话号码是否合法。 一、涉及到的知识点 Regex类的IsMatch方法用于指示正则表达式使用pattern参数中指定的正则表达式是否在输入字符串…

springBoot+Vue汽车销售源码

源码描述: 汽车销售管理系统源码基于spring boot以及Vue开发。 针对汽车销售提供客户信息、车辆信息、订单信息、销售人员管理、 财务报表等功能&#xff0c;提供经理和销售两种角色进行管理。 技术架构&#xff1a; idea(推荐)、jdk1.8、mysql5.X(不能为8驱动不匹配)、ma…