消息队列相关的函数
// 创建和获取 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