实验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

相关推荐
杰哥在此13 分钟前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
枫叶丹42 小时前
【在Linux世界中追寻伟大的One Piece】进程信号
linux·运维·服务器
刻词梨木2 小时前
ubuntu中挂载点内存不足,分配不合理后使用软链接的注意事项
linux·运维·ubuntu
灯火不休ᝰ3 小时前
[win7] win7系统的下载及在虚拟机中详细安装过程(附有下载文件)
linux·运维·服务器
数云界6 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
powerfulzyh7 小时前
Ubuntu24.04远程开机
linux·ubuntu·远程工作
ulimpid7 小时前
Command | Ubuntu 个别实用命令记录(新建用户、查看网速等)
linux·ubuntu·command
HHoao7 小时前
Ubuntu启动后第一次需要很久才能启动GTK应用问题
linux·运维·ubuntu
小灰兔的小白兔7 小时前
【Ubuntu】Ubuntu常用命令
linux·运维·ubuntu
GFCGUO7 小时前
ubuntu18.04运行OpenPCDet出现的问题
linux·python·学习·ubuntu·conda·pip