- 消息队列
链式队列
Msqid_ds 维护消息队列的结构体,队列的第一个消息指针msg_first,最后一个消息指针msg_last
消息中有一个成员指针next
每一个消息中包含有哪些内容:
Data 数据
Length 数据的长度
Type 数据的类型。
例如:
1----voltage data
2----电流数据
3----有功功率
消息的接收端可以根据消息的类型来接收。
(1) msgget
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int msgid;
msgid =msgget(IPC_PRIVATE, 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
创建了消息队列
(2) msgsnd
msgctl(要删除的id号,要做说明操作,返回值);
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int msgid;
msgid =msgget(IPC_PRIVATE, 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
删除队列消息
(2) msgsnd发送消息
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
long type;
char voltage[124];
char ID[14];
};
int main()
{
int msgid;
//定义消息的对象
struct msgbuf sendbuf;
msgid =msgget(IPC_PRIVATE, 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
//初始话消息
sendbuf.type = 100;
printf("please input message:\n");
fgets(sendbuf.voltage,124,stdin);
//开始写消息到消息队列
msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
system("ipcs -q");
while(1);
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
(3) msgrcv接收函数
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
long type;
char voltage[124];
char ID[14];
};
int main()
{
int msgid;
int readret;
//定义消息的对象
struct msgbuf sendbuf,recvbuf;
msgid =msgget(IPC_PRIVATE, 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
//初始话消息
sendbuf.type = 100;
printf("please input message:\n");
fgets(sendbuf.voltage,124,stdin);
//开始写消息到消息队列
msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
//开始读消息到消息队列里
memset(recvbuf.voltage,0,124);
readret = msgrcv(msgid,(void *)&recvbuf,124,100,0);
printf("recv =%s",recvbuf.voltage);
printf("readret = %d\n",readret);
system("ipcs -q");
while(1);
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
消息队列中数据读后,数据也不存在了,再次读取的时候数据没有了
msgsnd和msgrcv都可以设置为阻塞方式和非阻塞方式,阻塞方式设置为0
例子:通过消息队列,设置A和B之间的无亲缘之间的通信,可以相互通信,不单只是单向通信
写的程序(单向)
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
long type;
char voltage[124];
char ID[14];
};
int main()
{
int msgid;
int readret;
int key;
//定义消息的对象
struct msgbuf sendbuf,recvbuf;
key =ftok("./a.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -2;
}
printf("creat key sucess\n");
msgid =msgget(key,IPC_CREAT | 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
sendbuf.type = 100;
//写消息队列
while(1)
{
//初始化缓存
memset(sendbuf.voltage,0,124);
//初始话消息
//sendbuf.type = 100;
printf("please input message:\n");
fgets(sendbuf.voltage,124,stdin);
//开始写消息到消息队列
msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
//开始读消息到消息队列里
memset(recvbuf.voltage,0,124);
}
system("ipcs -q");
while(1);
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
读的函数(单向)
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//消息队列的数据类型
struct msgbuf
{
long type;
char voltage[124];
char ID[14];
};
int main()
{
int msgid;
int readret;
int key;
//定义消息的对象
struct msgbuf sendbuf,recvbuf;
key =ftok("./a.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -2;
}
printf("creat key sucess\n");
msgid =msgget(key,IPC_CREAT | 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
//开始读消息队列
while(1)
{
//初始化读缓存
memset(recvbuf.voltage,0,124);
//开始读消息队列内容
msgrcv(msgid,(void *)&recvbuf,124,100,0);
printf("receive data from message queue:%s",recvbuf.voltage);
}
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
证明可以单向通信
通过父子进程实现双向通信
服务器端的实现
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
//消息队列的数据类型
struct msgbuf
{
long type;
char voltage[124];
char ID[14];
};
int main()
{
int msgid;
int readret;
int key;
//定义消息的对象
struct msgbuf sendbuf,recvbuf;
int pid;
key =ftok("./b.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -2;
}
printf("creat key sucess\n");
msgid =msgget(key,IPC_CREAT | 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
pid = fork();
if(pid > 0)//父进程写
{
sendbuf.type = 100;
//写消息队列
while(1)
{
//初始化缓存
memset(sendbuf.voltage,0,124);
//初始话消息
//sendbuf.type = 100;
printf("please input message:\n");
fgets(sendbuf.voltage,124,stdin);
//开始写消息到消息队列
msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
//开始读消息到消息队列里
memset(recvbuf.voltage,0,124);
}
}
if(pid == 0)//子进程读
{
while(1)
{
memset(recvbuf.voltage,0,124);
msgrcv(msgid,(void *)&recvbuf,124,200,0);//从哪里读,读到哪里去,读多少个,读什么样的数据类型,以什么方式读(0为阻塞)
printf("receive message from message queue:%s\n",recvbuf.voltage);
}
}
system("ipcs -q");
while(1);
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
客户端的实现
#include<sys/types.h>
#include<sys/msg.h>
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
//消息队列的数据类型
struct msgbuf
{
long type;
char voltage[124];
char ID[14];
};
int main()
{
int msgid;
int readret;
int key;
//定义消息的对象
struct msgbuf sendbuf,recvbuf;
int pid;
key =ftok("./b.c",'a');
if(key < 0)
{
printf("creat key failure\n");
return -2;
}
printf("creat key sucess\n");
msgid =msgget(key,IPC_CREAT | 0777);
if(msgid <0)
{
printf("creat message queue failure\n");
return -1;
}
printf("creat message queue sucess mid = %d\n",msgid);
system("ipcs -q");
pid = fork();
if(pid == 0)//子进程写
{
sendbuf.type = 200;
//写消息队列
while(1)
{
//初始化缓存
memset(sendbuf.voltage,0,124);
//初始话消息
//sendbuf.type = 100;
printf("please input message:\n");
fgets(sendbuf.voltage,124,stdin);
//开始写消息到消息队列
msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.voltage),0);
//开始读消息到消息队列里
memset(recvbuf.voltage,0,124);
}
}
if(pid > 0)//父进程读
{
while(1)
{
memset(recvbuf.voltage,0,124);
msgrcv(msgid,(void *)&recvbuf,124,100,0);//从哪里读,读到哪里去,读多少个,读什么样的数据类型,以什么方式读(0为阻塞)
printf("receive message from message queue:%s\n",recvbuf.voltage);
}
}
system("ipcs -q");
while(1);
msgctl(msgid,IPC_RMID,NULL);
system("ipcs -q");
//system("ipcrm -m shmid");
return 0;
}
通过对队列消息的操作,对同一个文件b.c的读写利用fork产生的key属性,客户端和服务端都对key操作,父子进程交叉进程读写