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

调用原型

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自定义vue通用左侧菜单组件(未完善版本)

使用到的技术&#xff1a; vue3、pinia、view-ui-plus 实现的功能&#xff1a; 传入一个菜单数组数据&#xff0c;自动生成一个左侧菜单栏。菜单栏可以添加、删除、展开、重命名&#xff0c;拖动插入位置等。 效果预览&#xff1a; 代码&#xff1a; c-menu-wrap.vue <t…

模拟电路之运放

滞回比较器&#xff1a; 小幅度波动时候不受影响&#xff0c;除非超过一点范围 当输入信号慢慢增加到UT&#xff0c;就变成负电压 当输入信号慢慢减压到—UT&#xff0c;就变成正电压 电路反向接信号 正反馈&#xff0c;串联电阻接地 调整回差的方法 1.调整电阻的分压 2.…

学习在微信小程序使用富文本修改图片大小的代码,超简单

学习在微信小程序使用富文本修改图片大小的代码&#xff0c;超简单 前言代码 前言 自带img图片或大或小&#xff0c;不适应小程序页面 代码 1、replace方法全局添加图片img标签的style样式 let txt www.qipa250.com //富文本内容 txt txt.replace(/<img/gi,<img s…

c++ 字符串切分split

c 字符串切分split 的举例实现 一共给出了四种方式 1、 strtok 2、 stringstream 3、 字符串查找 4、 基于封装的方式&#xff0c;提供了 c11 foreach 接口 代码 vector<string> split(string s) {vector<string> res;const char *p strtok((char *) s.c_str(),…

linux平台 LED情报板网关项目总结

LED情报板目前已经基本稳定 主要存在两个版本LED1.5 和LED2 两个版本的主要差别是 &#xff1a; 1.1.5的配置文件存在本地 2.0的存在平台 需要通过接口从平台获取 2.1.5的下发消息的时候需要同步返回 2.0的是异步返回&#xff0c;所以1.5的要尽可能完成 不然会导致发 布平台…

C++指针比较

内存中各个数据的存放方式。 数组str1、str2、str3、str4都是在栈中分配的&#xff0c;内存中的内容都为“abc”加一个“\0”&#xff0c;但是他们的位置是不同的&#xff0c;因此代码第15行和第16行输出的都是0. 指针str5、str6、str7、str8也是在栈中分配的&#xff0c;他们…

oj赛(双周赛第二十次)

目录 碰碰车 小码哥与机器人 小码哥的跳棋游戏 竖直打印机 排队 邮箱地址 碰碰车 难度:钻石 占用内存:128 M时间限制:1秒 游乐园玩碰碰车&#xff0c;其中有一种碰碰车是在一条直线上行驶。该碰碰车有一个初始朝向和初始位置&#xff0c;并且以每秒一个单位的速度向初始方…

网络原理-TCP_IP(2)

TCP协议 TCP全称为"传输控制协议(Transmission Control Protocol)".协议如其名,要对数据的传输进行一个详细的控制. TCP协议段格式 源/目的端口号:表示数据从哪个进程来,到哪个进程去. 32位序号/32位确认序号:后面详细讲. 4位TCP报头长度:表示该TCP头部有多少个32位…

【JS逆向实战-入门篇】某gov网站加密参数分析与Python算法还原

文章目录 1. 写在前面2. 请求分析3. 断点分析4. 算法还原 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋…

一分钟在SpringBoot项目中使用EMQ

先展示最终的结果: 生产者端: RestController RequiredArgsConstructor public class TestController {private final MqttProducer mqttProducer;GetMapping("/test")public String test() {User build User.builder().age(100).sex(1).address("世界潍坊渤…

【C项目】顺序表

简介&#xff1a;本系列博客为C项目系列内容&#xff0c;通过代码来具体实现某个经典简单项目 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

spark-cannot resolve overloaded method

使用split方法&#xff0c;出现错误&#xff1a;cannot resolve overloaded method 解决方法:那个regex应该是自动生成&#xff0c;所以split括号中输入空引号即可。 入门学习人的愚笨&#xff0c;也要继续坚持&#xff0c;加油&#xff01;

R语言基础学习-02 (此语言用途小众 用于数学 生物领域 基因分析)

变量 R 语言的有效的变量名称由字母&#xff0c;数字以及点号 . 或下划线 _ 组成。 变量名称以字母或点开头。 变量名是否正确原因var_name2.正确字符开头&#xff0c;并由字母、数字、下划线和点号组成var_name%错误% 是非法字符2var_name错误不能数字开头 .var_name, var.…

CISAW和CISP-PTE证书选择指南

&#x1f4e3;在信息安全领域&#xff0c;选择合适的证书可以为你的职业生涯增添光彩。很多从事信息渗透行业的朋友经常讨论CISP-PTE和CISAW之间的选择问题。今天就从4个方面带你详细了解这两张证书&#xff0c;帮你做出明智的选择&#xff01; 1️⃣证书的行业前景 &#x1f4…

八斗学习笔记

1 初始环境安装 Anaconda安装(一款可以同时创建跟管理多个python环境的软件) https://blog.csdn.net/run_success/article/details/134656460 Anaconda创建一个新python环境(安装人工智能常用的第三方python包&#xff0c;如&#xff1a;tensorflow、keras、pytorch) https://…

k8s的operator基石:controller-runtime源码解析

写在之前 今天开始开更controller-runtime的源码阅读&#xff0c;笔者建议大家在阅读前了解以下知识&#xff0c;可能会帮助大家更好的理解源码逻辑。 1.client-go的基础使用 2. 使用kubebuilder搭建一个简单的controller-runtime环境 3.informer的基本思想 1.源码环境搭建 参…

热仿真中稳态与瞬态的区别

对于热仿真&#xff0c;根据是否随时间变化&#xff0c;可分为稳态&#xff08;steady&#xff09;仿真和瞬态&#xff08;transient&#xff09;仿真两类。 从数学计算的角度&#xff0c;所谓稳态是指物理量不随时间变化的定常过程&#xff0c;即计算域中所有物理量均满足关系…

鸿蒙会取代Android吗?听风就是雨

现在说取代还谈不上&#xff0c;毕竟这需要时间。安卓作为全球第一的手机操作系统&#xff0c;短时间内还无法取代。持平iOS甚至超过iOS有很大可能&#xff0c;最终会呈现“三足鼎立”有望超过安卓基数。 作为全新的鸿蒙操作系统&#xff0c;其现在已经是全栈自研底座。按照鸿…

讯飞星火V3.5发布,一场大模型的奇幻之旅(深度体验讯飞星火V3.5)

在去年的人工智能领域&#xff0c;大模型无疑是最炙手可热的技术话题。其强大的数据处理和深度学习能力&#xff0c;为众多领域带来了革命性的变革。而其中&#xff0c;讯飞星火表现尤为出色&#xff0c;成为了行业的翘楚&#xff0c;得到了大量的用户认可&#xff0c;其中&…

负载均衡下的webshell上传+nginx解析漏洞

负载均衡下的webshell上传 一&#xff0c;负载均衡下webshell上传的四大难点 难点一&#xff1a;需要在每一台节点的相同位置上传相同内容的webshell 我们需要在每一台节点的相同位置都上传相同内容的 WebShell一旦有一台机器上没有&#xff0c;那么在请求轮到这台机器上的时…