linux进程间消息队列通信
一,通信原理
1)消息队列是内核地址空间中的内部链表。消息可以顺序地发送到队列中,并以几种不同的方式从队列中获取。每个消息队列都是由 IPC 标识符所唯一标识的。
2)消息队列是随内核存在的,即使进程退出它仍然存在 。只有在内核重起或者人工删除时,该消息队列才会被删除。所以,一定要确保不再使用的消息队列被删除。(使用ipcs -q命令来查看当前系统中的消息队列信息)。
3)消息队列用于运行于同一台机器上的进程间通信,和管道很相似,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
2)消息队列是随内核存在的,即使进程退出它仍然存在 。只有在内核重起或者人工删除时,该消息队列才会被删除。所以,一定要确保不再使用的消息队列被删除。(使用ipcs -q命令来查看当前系统中的消息队列信息)。
3)消息队列用于运行于同一台机器上的进程间通信,和管道很相似,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
二,通信实现
建立一个写消息进程和一个读消息进程,写进程不断向消息队列写入消息,读进程则不断从消息队列读取消息。
一个简单的实现如下:
写进程:
/*************************************************************************
> File Name: msgwrite.c
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2014年11月27日 星期四 20时19分01秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#define BUFFER_SIZE 1024 // 1K
struct msg_buf {
int type; // 消息类型
char buf[BUFFER_SIZE]; // 消息内容
};
int main(int argc, char *argv[])
{
int key = ftok("/etc/profile", 1234);
int qid = msgget(key, IPC_CREAT | 0666);
struct msg_buf msg;
msg.type = 1;
if (qid == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
printf("key = %d\n", key);
printf("qid = %d\n", qid);
system("ipcs -q"); // 查看系统的IPC状态
printf("请输入一些消息,每条消息以回车键结束。如果输入quit,则程序"
"结束。\n");
while (1) {
fgets(msg.buf, BUFFER_SIZE, stdin);
if (strncmp(msg.buf, "quit", 4) == 0) {
// 删除消息队列
if (msgctl(qid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(EXIT_FAILURE);
} else {
system("ipcs -q");
printf("成功删除消息队列%d\n", qid);
exit(EXIT_SUCCESS);
}
}
if (msgsnd(qid, (void *)&msg, BUFFER_SIZE, 0) == -1) {
perror("msgsnd");
exit(EXIT_FAILURE);
}
}
return 0;
}
读进程:
/*************************************************************************
> File Name: msgread.c
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2014年11月27日 星期四 20时42分00秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#define BUFFER_SIZE 1024 // 1K
struct msg_buf {
int type; // 消息类型
char buf[BUFFER_SIZE]; // 消息内容
};
/*
* 读入消息时的长度一定要大于或等于写入的
* 否则就会出现msgrcv: Argument list too long的错误。
*/
int main(int argc, char *argv[])
{
key_t key = ftok("/etc/profile", 1234);
int qid = msgget(key, IPC_CREAT | 0666);
struct msg_buf msg;
if (qid == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
printf("key = %d\n", key);
printf("qid = %d\n", qid);
while (1) {
memset(msg.buf, 0, BUFFER_SIZE);
if (msgrcv(qid, (void *)&msg, BUFFER_SIZE, 0, 0) == -1) {
perror("msgrcv");
exit(EXIT_FAILURE);
}
printf("消息类型:%d\n", msg.type);
printf("消息内容:%s\n", msg.buf);
}
return 0;
}
有关消息队列操作函数msgget,msgctl,msgsnd,msgrcv的用法可以参考这个博客: linux常用系统调用简介