linux线程间通信—消息队列

消息队列相关的函数

// 创建和获取 ipc 内核对象
int msgget(key_t key, int flags);
// 将消息发送到消息队列
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// 从消息队列获取消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
// 查看、设置、删除 ipc 内核对象(用法和 shmctl 一样)
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

消息数据格式(无论你是发送数据还是接收数据,消息的格式都得按照规范来)

struct Msg{
   long type; // 消息类型。这个是必须的,而且值必须 > 0,这个值被系统使用
   // 消息正文,多少字节随你而定
   // ...
};
//保证首4字节(32位linux下的long)是一个整数就行了,举例:
struct Msg {
    long type;
    char name[20];
    int age;
} msg;
    
struct Msg {
    long type;
    int start;
    int end;
} msg;
//正文部分是什么数据类型都没关系,因为消息队列传递的是 2 进制数据,不一定非得是文本

msgsnd函数

msgrcv函数

msgctl函数

例程1

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
 
pthread_t pid_1,pid_2;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int msgid;
typedef struct{
    long mtype;
    int date;
}msg;
void *func2(void *arg)
{
    int i = 1,j =1;
    msg sendData;
    pthread_detach(pthread_self());
    while(1)
    {
        sleep(2);
        sendData.mtype = i++;
        sendData.date= j++;
        if(( msgsnd(msgid,&sendData,sizeof(msg)-sizeof(sendData.mtype),0))<0)
        {
            perror("msgsnd:");
            pthread_exit(NULL);
        }else
        {
            pthread_mutex_lock(&mutex);
            printf("send:mtype= %ld,data = %d\n",sendData.mtype,sendData.date);
            pthread_mutex_unlock(&mutex);
        }
 
    }
}
void *func1(void *arg)
{
    pthread_create(&pid_2,NULL,func2,NULL);
 
    msg reData;
    while(1)
    {
        if((msgrcv(msgid,&reData,sizeof(reData)-sizeof(reData.mtype),0,0))<0)
        {
            perror("msgrcv:");
            pthread_exit(NULL);
        }else{
            pthread_mutex_lock(&mutex);
            printf("recv:mtype= %ld,data = %d\n",reData.mtype,reData.date);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_join(pid_2,NULL);
    printf("func1--son exit \n");
 
}
 
int main(int argc, char *argv[])
{
    if((msgid =  msgget(3123,IPC_CREAT|0666))<0)
    {
        perror("msgget:");
        return 0;
    }
    pthread_create(&pid_1,NULL,func1,NULL);
 
    pthread_join(pid_1,NULL);
    printf("main--son exit \n");
 
    printf("father exit\n");
    return 0;
}

例程2

MSGQUEUE1.c


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

#define MSGKEY  1234
pthread_t tid[2]={0}; //定义一个数组,作为线程id

struct msgbuf 
{
    long mtype;     //消息类型
    char mtext[100];  //消息内容
};

void *receive(void *arg)
{
    struct msgbuf buf;  //定义结构体用作消息缓冲区
    int ret;

    while(1)
    {
        memset(&buf,0,sizeof(buf));  //初始化

        ret = msgrcv(*(int *)arg,&buf,sizeof(buf.mtext),2,0);
        if(-1 == ret)
        {
            perror("msgrcv");
            exit(1);
        }
        if(!strncmp(buf.mtext,"bye",3))
        {
            pthread_cancel(tid[1]); //注意:要取消另一个进程哦
            break;
        }
        printf("receive :%s\n",buf.mtext);
    }
}

void *send(void *arg)
{
    struct msgbuf buf;
    int ret,oldtype;

    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);//收到信号后立即执行取消动作(退出);oldtype用来存入取消动作的类型值。
    while(1)
    {
        memset(&buf,0,sizeof(buf));
        scanf("%s",buf.mtext);
        buf.mtype = 1;

        ret = msgsnd(*(int *)arg,&buf,sizeof(buf.mtext),0);
        if(-1 == ret)
        {
            perror("msgsnd");
            exit(1);
        }
        if(!strncmp(buf.mtext,"bye",3))
        {
            pthread_cancel(tid[0]);
            break;
        }
    }
}

int main()
{
    int msgid,ret;

    msgid = msgget(MSGKEY,IPC_CREAT |IPC_EXCL); //创建消息队列,返回标识符
    if(-1 == msgid)
    {
        perror("msgid");
        exit(1);
    }

    ret = pthread_create(&tid[0],NULL,receive,(void *)&msgid); //参数一:线程id;参数二:线程属性(通常为空);参数三:线程要执行的函数;参数四:作为传递给参数三的参数
    if(0 != ret)
    {
        perror("pthread_create1");
        exit(1);
    }

    ret = pthread_create(&tid[1],NULL,send,(void *)&msgid);
    if(0 != ret)
    {
        perror("msgid");
        exit(1);
    }

    pthread_join(tid[0],NULL);//阻塞调用线程,直到指定的线程终止
    pthread_join(tid[1],NULL);

    msgctl(msgid,IPC_RMID,NULL);//移除消息队列
    return 0;
}

例程3


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

#define MSGKEY  1234
pthread_t tid[2]={0}; //定义一个数组,作为线程id

struct msgbuf 
{
    long mtype;     //消息类型
    char mtext[100];  //消息内容
};

void *receive(void *arg)
{
    struct msgbuf buf;  //定义结构体用作消息缓冲区
    int ret;

    while(1)
    {
        memset(&buf,0,sizeof(buf));  //初始化

        ret = msgrcv(*(int *)arg,&buf,sizeof(buf.mtext),1,0);
        if(-1 == ret)
        {
            perror("msgrcv");
            exit(1);
        }
        if(!strncmp(buf.mtext,"bye",3))
        {
            pthread_cancel(tid[1]); //注意:要取消另一个进程哦
            break;
        }
        printf("receive another:%s\n",buf.mtext);
    }
}

void *send(void *arg)
{
    struct msgbuf buf;
    int ret,oldtype;

    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);//收到信号后立即执行取消动作(退出);oldtype用来存入取消动作的类型值。
    while(1)
    {
        memset(&buf,0,sizeof(buf));
        scanf("%s",buf.mtext);
        buf.mtype = 2;

        ret = msgsnd(*(int *)arg,&buf,sizeof(buf.mtext),0);
        if(-1 == ret)
        {
            perror("msgsnd");
            exit(1);
        }
        if(!strncmp(buf.mtext,"bye",3))
        {
            pthread_cancel(tid[0]);
            break;
        }
    }
}

int main()
{
    int msgid,ret;

    msgid = msgget(MSGKEY,0); //创建消息队列,返回标识符
    if(-1 == msgid)
    {
        perror("msgid");
        exit(1);
    }

    ret = pthread_create(&tid[0],NULL,receive,(void *)&msgid); //参数一:线程id;参数二:线程属性(通常为空);参数三:线程要执行的函数;参数四:作为传递给参数三的参数
    if(0 != ret)
    {
        perror("pthread_create1");
        exit(1);
    }

    ret = pthread_create(&tid[1],NULL,send,(void *)&msgid);
    if(0 != ret)
    {
        perror("msgid");
        exit(1);
    }

    pthread_join(tid[0],NULL);//阻塞调用线程,直到指定的线程终止
    pthread_join(tid[1],NULL);

    return 0;
}




执行结果:
    receive :hi         hi
    receive :i          i am your father
    receive :am         receive another:fuck
    receive :your       receive another:what
    receive :father     receive another:you
    fuck                receive another:say
    what you say
    bye
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值