3,消息队列
进程间传递数据,如果数据量比较小的话,使用消息队列。消息结构有两个限制:消息大小不能操作系统规定最大值。必须以一个long整数开始。
消息队列相关函数。
int msgget(key_tkey,int msgflg);
key_t key键值可以随意选择,特殊键值IPC_PRIVATE,创建只能有本进程使用的消息。
msgflg访问权限。类似信号量和共享内存。
int msgsnd(intmsgid,const void *msg_ptr,size_t msg_size,int msgflg);
msgid消息队列标示符。
msg_ptr消息指针,指向将要发送的消息,这个消息必须以一个长整数开始。
msg_size消息大小,不包括消息开头的长整数。
msgflg控制着消息队列满或者到达系统上限时采取的动作。如果设置为IPC_NOWAIT,消息队列满后,此调用立马返回-1,不阻塞。
如果IPC_NOWAIT标识被清除,次调用将被挂起,直到队列腾出空间后,操作完后返回。
int msgrcv(intmsgid,void *msg_ptr,size_t msg_sz,long int msg_type,int msgflg);
msgid消息队列标示符。
msg_ptr消息接受缓冲区,该结构和msgsnd中定义的结构相同。
msg_szmsg_ptr所指向的消息的长度,不包括开头长整数。
msg_type消息类型,如果想按照发送顺序接受消息,该值赋值为0。如果想检索某一特定的消息,只需要设定为特定的类型即可。
msgflg控制着消息队列满或者到达系统上限时采取的动作。如果设置为IPC_NOWAIT,消息队列为空时,此调用立马返回-1,不阻塞。
如果IPC_NOWAIT标识被清除,此调用将被挂起,直到队列中有消息位置,操作完后返回。
int msgctl(intmsgid,int command,struct msgid_ds *buf);
struct msgid_ds
{
uid_t msg_perm.uid;
uid_t msg_perm.gid;
mode_tmsg_perm.mode;
};
IPC_STAT获取当前共享内存的状态信息,放到msgid_ds结构中。
IPC_SET把msgid_ds结构中的数据设置为共享内存的当前关联值。
IPC_RMID 删除消息队列。
message_queue2
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#define MAX_TEXT 512
struct my_msg_st {
long intmy_msg_type;
charsome_text[MAX_TEXT];
};
int main()
{
int running = 1;
struct my_msg_stsome_data;
int msgid;
charbuffer[BUFSIZ];
msgid =msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1){
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
while(running) {
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
some_data.my_msg_type = 1;
strcpy(some_data.some_text, buffer);
if(msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) {
fprintf(stderr, "msgsnd failed\n");
exit(EXIT_FAILURE);
}
if(strncmp(buffer, "end", 3) == 0) {
running= 0;
}
}
exit(EXIT_SUCCESS);
}
message queue1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
struct my_msg_st {
long intmy_msg_type;
charsome_text[BUFSIZ];
};
int main()
{
int running = 1;
int msgid;
struct my_msg_stsome_data;
long intmsg_to_receive = 0;
msgid =msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1){
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
while(running) {
if(msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, 0) == -1) {
fprintf(stderr, "msgrcv failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("Youwrote: %s", some_data.some_text);
if(strncmp(some_data.some_text, "end", 3) == 0) {
running= 0;
}
}
if(msgctl(msgid, IPC_RMID, 0) == -1) {
fprintf(stderr, "msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}