消息队列用于线程间通信

109 篇文章 12 订阅
72 篇文章 19 订阅

我们知道,消息队列是进程间通信的方法之一,

当然,消息队列也可以用于线程间通信。

进程间通信的时候,我们需要使用ftok()函数创建同一个key值,(当然,进程间通信,key值我们可以自定义同一个值,而不必非要调用ftok函数,这步可以省掉。)线程间通信时,我们就是采用直接自定义key值的方法,这样比较简便。

示例:

#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;
}

运行结果: 

总结:

1) 消息队列可以用于线程间通信;

2)在同一进程中的话,只需要msgget一次获得一个全局的消息id即可。

3)

msgrcv的使用,当没有消息过来时,msgrcv是阻塞在这里的,

此时的现象是,不会perror报错,也不会打印else中的内容,just阻塞在这里,

只有当msgsnd过来消息后,才会printf打印输出。 

4)消息类型中的mtype必须是大于0的,测试改成0后,结果:

 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用 POSIX 消息队列实现线程间通信的例子: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <mqueue.h> #define MSG_SIZE 256 #define MAX_MSG 10 mqd_t mqd; pthread_t tid[2]; pthread_attr_t attr; // 线程1:发送消息 void *send_func(void *arg) { char msg[MSG_SIZE]; int i; for (i = 0; i < MAX_MSG; i++) { memset(msg, 0, MSG_SIZE); sprintf(msg, "Message %d from thread 1", i); if (mq_send(mqd, msg, strlen(msg) + 1, 0) == -1) { perror("mq_send"); exit(1); } printf("Thread 1 sent: %s\n", msg); sleep(1); } } // 线程2:接收消息 void *recv_func(void *arg) { char msg[MSG_SIZE]; unsigned int prio; int i; for (i = 0; i < MAX_MSG; i++) { memset(msg, 0, MSG_SIZE); if (mq_receive(mqd, msg, MSG_SIZE, &prio) == -1) { perror("mq_receive"); exit(1); } printf("Thread 2 received: %s\n", msg); sleep(1); } } int main() { struct mq_attr attr; attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = MSG_SIZE; attr.mq_curmsgs = 0; if ((mqd = mq_open("/test_mq", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr)) == -1) { perror("mq_open"); exit(1); } if (pthread_attr_init(&attr) != 0) { perror("pthread_attr_init"); exit(1); } if (pthread_create(&tid[0], &attr, send_func, NULL) != 0) { perror("pthread_create"); exit(1); } if (pthread_create(&tid[1], &attr, recv_func, NULL) != 0) { perror("pthread_create"); exit(1); } if (pthread_join(tid[0], NULL) != 0) { perror("pthread_join"); exit(1); } if (pthread_join(tid[1], NULL) != 0) { perror("pthread_join"); exit(1); } if (mq_close(mqd) == -1) { perror("mq_close"); exit(1); } if (mq_unlink("/test_mq") == -1) { perror("mq_unlink"); exit(1); } return 0; } ``` 该程序创建了一个 POSIX 消息队列 `/test_mq`,其中维护了最大消息数为 10,每条消息为 256 字节。程序启动两个线程,一个用于发送消息,一个用于接收消息,它们都可以同时操作消息队列。发送线程每秒钟向队列中发送一条消息,接收线程每秒钟从队列中接收一条消息并打印出来。程序使用 `pthread_create()` 创建线程,使用 `pthread_join()` 以等待线程完成,使用 `mq_send()` 发送消息,使用 `mq_receive()` 接收消息。最后程序清理了 POSIX 消息队列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值