Ubuntu下Linux进程间通信——消息队列
Linux提供了多种进程间通信的方法,常见有管道(匿名)、FIFO(有名管道)、消息队列、信号量、共享内存,socket通信。
3.消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
//创建消息队列
int msgget(key_t key, int msgflg);
//发送消息到队列
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
//消息结构体
struct my_message{
long int message_type;
/* The data you wish to transfer*/
};
//从队列接收消息
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
//控制消息队列
int msgctl(int msgid, int command, struct msgid_ds *buf);
struct msgid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
msgget函数中的key相当于消息队列标签,msgflg为权限标志,创建成功则返回以key命名的消息队列的标识符,失败返回-1;
msgsend函数中msgid是由msgget函数返回的消息队列标识符,msg_ptr指向消息结构体,msg_sz是消息内容长度,msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情,成功返回0,失败返回-1。
msgrcv函数中msgid, msg_ptr, msg_st的作用也函数msgsnd函数的一样,msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。msgflg用于控制当队列中没有相应类型的消息可以接收时将发生的事情。调用成功时,该函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息。失败时返回-1.
msgctl函数中command是将要采取的动作,它可以取3个值:
IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
IPC_RMID:删除消息队列
成功时返回0,失败时返回-1.
实例
msglistread.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
//消息的数据结构
struct msg_st{
long int msg_type;
char text[1024];
};
int main()
{
int msgid=-1;
struct msg_st data;
long int msgtype = 0; //接收为0,发送为1
int ret=-1;
//建立消息队列
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid==-1)
{
perror("msgget create fail!");
return -1;
}
while(1)
{
//从队列中获取消息,直到遇到quit为止
ret=msgrcv(msgid,(void*)&data,1024,msgtype,0);
if(ret==-1)
{
perror("msgrcv fail");
break;
}
printf("msg receive:%s\n",data.text);
if(strncmp(data.text,"quit",4)==0)
{
printf("msg receive end!\n");
break;
}
}
//删除消息队列
ret=msgctl(msgid,IPC_RMID,0);
if(ret==-1)
{
perror("msgctl delete fail!");
return -1;
}
return 0;
}
msglistwrite.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
//消息的数据结构
struct msg_st{
long int msg_type;
char text[1024];
};
int main()
{
int msgid=-1;
struct msg_st data;
long int msgtype = 0; //接收为0,发送为1
char buf[1024];
int ret=-1;
//建立消息队列
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid==-1)
{
perror("msgget create fail!");
return -1;
}
while(1)
{
//输入要发送的消息
printf("please send msg:");
fgets(buf, 1024, stdin);
data.msg_type=1;
strcpy(data.text,buf);
//向队列发送数据
ret=msgsnd(msgid,(void*)&data, 1024, 0);
if(ret==-1)
{
perror("msgsnd fail!");
break;
}
//输入end结束输入
if(strncmp(buf, "quit", 4) == 0)
{
printf("send msg end!\n");
break;
}
}
return 0;
}
每天一个知识点,全局变量存放在BSS区,局部变量放在堆区。