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

调用原型

POSIX信号量--无名信号量

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

python 复制代码
#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消息队列通信机制

python 复制代码
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
消息缓冲区struct msgbuf

需重新定义

python 复制代码
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线程库

python 复制代码
#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

相关推荐
vvw&27 分钟前
如何在 Ubuntu 上安装 Jupyter Notebook
linux·人工智能·python·opencv·ubuntu·机器学习·jupyter
钰爱&3 小时前
【操作系统】Linux之线程同步二(头歌作业)
linux·运维·算法
DC_BLOG6 小时前
Mysql-DDL语句
服务器·数据库·mysql
Yz98766 小时前
Hive基础
大数据·linux·数据仓库·hive·hadoop·bigdata
raysync8887 小时前
镭速大文件传输软件向金融银行的文档管理提供高效的解决方案
服务器·网络·金融
Stara05117 小时前
Linux系统常用操作与命令指南
linux·vim
AI狂热爱好者8 小时前
A3超级计算机虚拟机,为大型语言模型LLM和AIGC提供强大算力支持
服务器·人工智能·ai·gpu算力
white.tie8 小时前
linux配置nginx
linux·运维·nginx
TN_stark9328 小时前
多进程/线程并发服务器
服务器·算法·php
Komorebi.py8 小时前
【Linux】-学习笔记03
linux·笔记·学习