消息队列 多线程 linux

这些天自己在学习消息队列的使用,经过几天的琢磨,总算了解了怎么使用了,趁现在思路清晰把自己的过程记录下来供自己以后查阅。

工作原理:

首先通过唯一标识创建消息队列,之后所有的线程都监听消息队列中相对应的消息类型,当有消息产生的时候就出发接收函数,主线程只需要通过发送函数发送到消息队列就可以。这样,就实现了多线程之间的通信。

需要使用的头文件:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

 

需要使用到的函数是

 

Key_t ftok(const char *pathname, intproj_id);

该函数用于产生key值,之后msgget使用该值创建唯一标识的消息队列

 

Int msgget( key_t key, int msgflg );

该函数通过key值创建消息队列

 

Int msgsnd( int sqid, const void *msgp,size_t msgsz, int msgflg );

该函数主要是将消息发送出去,flg目前还没有使用,置0

 

Sseze_t msgrcv( int msqid, void *msgp,size_t msgsz, long msgtyp, int msgflg );

该函数通过消息队列接收 msgtyp 类型的消息,

该函数注意的地方是:进过几次的验证,发现每次msgid都会改变,不管你接收成功还是接收失败,所以在使用msgqid之前,必须先保存一下,之后每次调用都赋值一下,不然就是出现invaild segment错误,这个还真心不知道什么原因,有待探究....


自己的代码如下所示:写的很粗糙,但是基本功能实现,自己创建了两个线程然后主线程轮流向各个线程发送消息,各个线程能够接收

/** @file      mq_thread1.c 
 *  @brief     练习使用消息消息队列,多线程之间的通信
 *  @note      
 *  @note      
 *  @author   
 *  @date     
 *  @version   v1.0
 */


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


#define MSG_FILE "."
#define MAXBUF 255
#define PERM S_IRUSR|S_IWUSR


struct myMsg
{
    long msgType;
    char msgText[MAXBUF+1];
};


struct msqid_ds msgbuf;      // 获取消息属性的结构体


void *thr_fun1(void *arg)
{
    //printf("here is thread 1!\n");
    struct myMsg msg;
    //const int qid=*((int *)arg);
    int qid, tmpqid, err;
    tmpqid = *((int *)arg);
    qid = tmpqid;
    while (1)
    {
        qid = tmpqid;   
        /* msgrcv竟然会在出错返回时改掉 qid 的值,加const修饰都会被改为 1 
         * 太扯淡了,所以必须使用qidtmp保存第一次传进来的 qid值,
         * 以便后面消息的接收
         */
        if (-1 == (err = msgrcv(qid, &msg, sizeof(struct myMsg), 1, IPC_NOWAIT)) )
        {
            //printf("qid = %d  ", qid);
            //perror("thr1: recv msg error!");
            //printf("strerror = %s\n", strerror(errno));
            //sleep(2);
            continue;
            //pthread_exit((void *)-1);
            
            


        }
        printf("thread1:received msg \"%s\"  MsgType = %d\n", msg.msgText, msg.msgType);
        
       /*
        msg.msgType = 2;
        
        sleep(2);
        if ( -1 == (err = msgsnd(qid, &msg, sizeof(struct myMsg), 0)) )
        {
            perror("thr1: send msg error!\n");


        }
        */
        //sleep(2);
        
    }
    
    //fprintf(stdout, "thread1 receive: %s\n", msg.msgText);
    //


    


    //pthread_exit((void *)2);
}


void *thr_fun2(void *arg)
{
    //printf("here is thread 2!\n");
    struct myMsg msg;
    int qid, qidtmp;
    int err;
    qidtmp = *((int *)arg);
    while (1)
    {
        qid = qidtmp;
        if (-1 == (err = msgrcv(qid, &msg, sizeof(struct myMsg), 2, IPC_NOWAIT)) )
        {
            //perror("thr2: recv msg error!");
            //sleep(2);
            continue;
            //pthread_exit((void *)-1);
        }
        
        
        else
        {
            printf("thread2:received msg \"%s\" MsgType = %d\n", msg.msgText, msg.msgType);
        }
        /* 
        msg.msgType = 1;


        sleep(2);
        if ( -1 == (err = msgsnd(qid, &msg, sizeof(struct myMsg), 0)) )
        {
            perror("thr2: send msg error!\n");


        }
        */
        //sleep(2);
        
    }
    


    
    
    //fprintf(stdout, "thread1 receive: %s\n", msg.msgText);
    //msg.msgType = 2;


    //msgsnd(qid, &msg, sizeof(struct myMsg), 0);


    //pthread_exit((void *)2);


}


void *thr_fun3(void *arg)
{
    struct myMsg msg;
    int qid, qidtmp;
    int err;
    qidtmp = *((int *)arg);  
    while (1)
    {
        qid = qidtmp;
        //printf("thread3111111: qid = %d  ", qid);
        if (-1 == (err = msgrcv(qid, &msg, sizeof(struct myMsg), 3, IPC_NOWAIT)) )
        {
            //perror("thr3: recv msg error!");
            //sleep(2);
            continue;
            //pthread_exit((void *)-1);
        }
        else
        {
            qid = qidtmp;
            printf("thread3222222: qid = %d  ");
            err = msgctl(qid, IPC_RMID, 0);    // 删除消息队列
            if ( 0 == err )
            {
                printf("msg queue removed successfully!\n");
                printf("thread3:received msg \"%s\" MsgType = %d\n", msg.msgText, msg.msgType);
                printf("Now going to shutdown the system!\n");
                pthread_exit((void *)0);
            }
            else
            {
                perror("thread3: delete msg queue error!\n");
                exit (-1);
            }
            
        }
        /* 
        msg.msgType = 1;


        sleep(2);
        if ( -1 == (err = msgsnd(qid, &msg, sizeof(struct myMsg), 0)) )
        {
            perror("thr2: send msg error!\n");


        }
        */
        //sleep(2);
        
    
    }
}








int main(int argc, char *argv[])
{
    pthread_t td1, td2, td3;
    int err1, err2, err3, err;
    int qid;
    key_t key;


    char buf[MAXBUF+1];
    int tmpMsgType;
    
    struct myMsg msg;


    fflush(stdin);
    fflush(stdout);


    if ( -1 == (key = ftok(".", 'a')) )   // 创建key
    {
         perror("Create key error!\n");
         exit (-1);
    }
    /* 创建消息队列,若存在直接报错 */
    if ( -1 == (qid = msgget(key, IPC_CREAT | 0777)) )  // | IPC_EXCL 
    {
        perror("message queue already exitsted!\n");
        exit (-1);
    }
    printf("create . open queue qid is %d!\n", qid);
    
    err1 = pthread_create(&td1, NULL, thr_fun1, &qid);
    if ( 0 != err1 )
    {
        fprintf(stderr, "sync thread create error!\n");
        exit(1);
    }


    err2 = pthread_create(&td2, NULL, thr_fun2, &qid);
    if ( 0 != err2 )
    {
        fprintf(stderr, "fdatasync thread create error!\n");
        exit(1);
    }


    err3 = pthread_create(&td3, NULL, thr_fun3, &qid);
    if ( 0 != err3 )
    {
        fprintf(stderr, "sync thread create error!\n");
        exit(1);
    }
    
    while (1)
    {
        printf("Input the string: ");
        scanf("%s", buf);
        printf("buf = %s\n");
        fflush(stdin);
        fflush(stdout);


        strncpy(msg.msgText, buf, MAXBUF);


        printf("Input the msgType:");
        scanf("%d", &tmpMsgType);
        printf("msgType = %d\n", tmpMsgType);
        fflush(stdin);
        fflush(stdout);
        msg.msgType = tmpMsgType;
        
        if ( -1 == (msgsnd(qid, &msg, sizeof(struct myMsg), 0)) )
        {
            perror("msg closed! quit the system!\n");
            break;
            //exit (-1);
        }
        printf("Write msg success!\n");


        /*
        printf("\n---------------------------\n");
        err = msgctl(qid, IPC_STAT, &msgbuf);
        if ( err != -1 )
        {
            printf("current number of bytes on queue: %ld\n", msgbuf.msg_cbytes);
            printf("number of msg in queue is: %ld\n", msgbuf.msg_qnum);
            printf("Max number of bytes on queue is: %ld\n", msgbuf.msg_qbytes);
        }
        else
        {
            printf("msg queue msgctl error!\n");
        }
        printf("---------------------------\n"); 
        */
        sleep(2);
    }
    


    /*
    err1 = pthread_join(td1, NULL);
    if ( 0 != err1 )
    {
        printf("join thread1 failed!\n");
        exit(1);
    }


    err2 = pthread_join(td2, NULL);
    if ( 0 != err2 )
    {
        printf("join thread2 failed!\n");
        exit(1);
    }
    */
    
    err3 = pthread_join(td3, NULL);
    if ( 0 != err3 )
    {
        printf("join thread3 failed!\n");
        exit(1);
    }


    
    
    return 0;
}


程序的运行结果如下:


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值