这些天自己在学习消息队列的使用,经过几天的琢磨,总算了解了怎么使用了,趁现在思路清晰把自己的过程记录下来供自己以后查阅。
工作原理:
首先通过唯一标识创建消息队列,之后所有的线程都监听消息队列中相对应的消息类型,当有消息产生的时候就出发接收函数,主线程只需要通过发送函数发送到消息队列就可以。这样,就实现了多线程之间的通信。
需要使用的头文件:
#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;
}
程序的运行结果如下: