Linux进程入门学习(八)-消息队列通信
2017-08-26 22:39
190 查看
1.什么是消息队列
消息队列(也叫做报文队列)是一个消息的链式队列。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息
2.消息队列特性
1)消息队列是IPC 对象中的一种,消息队列中可以通过唯一的ID 来识别2)消息队列就是一个消息列表,用户可以在消息队列中添加消息、读消息
3)消息队列可以按照类型来发送/接收信息
消息队列查看:ipcs -q
删除消息队列:ipcrm -q msqid
ipcrm -Q key
3.消息队列的结构
与消息队列相关的数据结构主要有两个:1)msqid_ds 消息队列数据结构,用来标识整个消息队列的情况
2)msg 消息队列数据结构,是整个消息队列的主体
kernel 中描述消息链表每个节点结构的结构体是
struct msg { struct msg *msg_next; 指向消息链表中下一个节点的指针 long msg_type; 和msgbuf 中mtype 成员的意义是一样的。 char *msg_spot; /* message text address */ time_t msg_stime; /* msgsnd time */ short msg_ts; /* message text size */ };
kernel 中描述消息的结构体
事实上,在我们自定义的结构中,和它对应的部分可以是任意的数据类型,甚至是多个数据类型的集合。
比如我们可以定义这样的一个消息类型:
struct my_msgbuf { long mtype; /* Message type */ long request_id; /* Request identifier */ struct client info; /* Client information structure */ };
由此可见消息队列在传送消息上的灵活性。
4.消息队列使用步骤
创建并打开消息队列—— msgget写消息队列操作—— msgsnd
读消息队列操作—— msgrcv
销毁消息队列—— msgctl
msgget 函数
功能:用于获取消息队列ID头文件
#include <sys/msg.h>
函数原型
int msgget(key_t key, int msgflg);
返回值
成功:消息队列ID; 失败:-1
参数列表
key_t key:消息队列的key 值 (可以自己写一个正整数,如IPC_PRIVATE也可以调用函数ftok 来获取) int msgflg:消息队列的访问权限 可以通过IPC_CREAT 创建:IPC_CREAT | 0666(可读可写)
示例:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int main(int argc, char *argv[]) { int msqid; msqid = msgget(IPC_PRIVATE, 0666); if(msqid < 0) { printf("fail to get message \n"); return -1; } printf("success to get message, id = %d \n",msqid); /* 查看消息队列的创建情况*/ system("ipcs -q"); return 0; }
ftok 函数
功能:用于获取一个key 值头文件
#include <sys/types.h> #include <sys/ipc.h>
函数原型
key_t ftok(const char *pathname, int proj_id);
返回值
成功:key 值; 失败:-1
参数列表
const char *pathname:路径:"." int proj_id:给定的一个正整数
示例:利用ftok 函数生成key 值
#include <stdio.h>
#include <sys/types.h> #include <sys/ipc.h>#include <sys/msg.h>int main(int argc, char *argv[])
{
int msqid;
key_t key;
key = ftok("/key", 'a');
if(key < 0)
{
printf("fait to creat key value \n");
return -1;
}
msqid = msgget(key, IPC_CREAT|0666);
if(msqid < 0)
{
printf("fail to get message \n");
return -1;
}
printf("success to get message, id = %d \n",msqid);
/* 查看消息队列的创建情况*/
system("ipcs -q");
return 0;
}
msgctl 函数
功能:用于消息队列控制头文件
#include <sys/msg.h>
函数原型
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
返回值
成功:0;失败:-1
参数列表
int msqid:消息队列ID int cmd :IPC_RMID 删除消息队列 struct msqid_ds *buf 4000 :消息队列缓冲区如果有IPC_RMID,就设置NULL
示例:
#include <stdio.h>
#include <sys/types.h> #include <sys/ipc.h>#include <sys/msg.h>int main(int argc, char *argv[])
{
int msqid;
int ret;
key_t key;
key = ftok("/key", 'a');
if(key < 0)
{
printf("fait to creat key value \n");
return -1;
}
msqid = msgget(key, IPC_CREAT|0666);
if(msqid < 0)
{
printf("fail to get message \n");
return -1;
}
printf("success to get message, id = %d \n",msqid);
/* 查看消息队列的创建情况*/
system("ipcs -q");
//新添加内容: 删除消息队列
ret = msgctl(msqid, IPC_RMID, NULL);
if(ret < 0)
{
printf("fail to delete message queue \n");
return -1;
}
system("ipcs -q");
return 0;
}
msgsnd 函数
功能:用于消息发送头文件
#include <sys/msg.h>
函数原型
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
返回值
成功:0;失败:-1
参数列表
int msqid :消息队列ID const void *msgp:指向发送消息的指针 struct mymsg { long mtype; /* Message type.消息类型*/ char mtext[1]; /* Message text.消息数据*/ } size_t msgsz:发送消息大小 int msgflg:消息标志 IPC_NOWAIT:消息没有发送完成也会立即返回 0 :直到消息发送完成再返回
msgrcv 函数
功能:用于消息接收头文件
#include <sys/msg.h>
函数原型
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
返回值
成功:读取到的消息的大小;失败:-1
参数列表
int msqid:消息队列ID void *msgp:指向接收消息的指针 struct mymsg { long mtype; /* Message type.消息类型*/ char mtext[1]; /* Message text.消息数据*/ } size_t msgsz:接收消息大小 long msgtyp:接受消息的类型 0:接收消息队列中的第一个消息 >0: 接受消息队列中的对应的消息类型 <0: 接收消息队列类型中不小于msgtyp 绝对值消息 int msgflg:消息标志 0:直到消息接收完成再返回 IPC_NOWAIT:消息没有接收完成也会立即返回
示例:
xie@ubuntu:/mnt/hgfs/share/ISP/pratice8.9$ cat msgsnd.c
/**************************************************************************
* File Name: msgsnd.c
* Author: Po Xie
* E-mail: 2446603068@qq.com
* Create Time: Wed 09 Aug 2017 04:33:40 AM PDT
***************************************************************************/
#include <stdio.h>
#include <sys/types.h> #include <sys/ipc.h>#include <sys/msg.h>#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_MSG 128
struct msgbuf
{
long type;
char buf[MAX_MSG];
};
int main(int argc, char **argv)
{
int msgid;
int err;
int cnt;
key_t key;
key = ftok("./key",'b');
if(key < 0)
{
printf("fail to create key value\n");
return -1;
}
msgid = msgget(key, IPC_CREAT|0666);
if(key < 0)
{
printf("fail to get message \n");
return -1;
}
printf("success to get message \n");
system("ipcs -q");
//添加写操作
struct msgbuf sendbuf,recvbuf;
sendbuf.type = 100;
printf("please enter you message: \n");
fgets(sendbuf.buf, MAX_MSG, stdin);
err = msgsnd(msgid, (void *)&sendbuf, strlen(sendbuf.buf), 0);
if(err < 0)
{
printf("write message fail \n");
return -1;
}
printf("success to write message \n");
printf("err = %d\n",err);
system("ipcs -q");
//添加读操作
memset(recvbuf.buf, 0, MAX_MSG);
cnt = msgrcv(msgid, (void *)&recvbuf, MAX_MSG, 100, 0);
if(cnt < 0)
{
printf("fail to receive message ");
return -1;
}
printf("success to receive message, cnt=%d \n",cnt);
printf("read data = %s\n",recvbuf.buf);
//测试第二次是否还可以读(不可以,会阻塞)
msgrcv(msgid, (void *)&recvbuf, MAX_MSG, 100, 0);
printf("second read data =%s\n",recvbuf.buf);
//删除消息队列
err = msgctl(msgid, IPC_RMID, NULL);
if(err < 0)
{
printf("fail to delete message queue \n");
return -1;
}
system("ipcs -q");
return 0;
}
运行结果:
xie@ubuntu:/mnt/hgfs/share/ISP/pratice8.9$ ./msgsnd success to get message ------ Message Queues -------- key msqid owner perms used-bytes messages 0x62270166 0 xie 666 0 0 please enter you message: hello world, hello linux! success to write message err = 0 ------ Message Queues -------- key msqid owner perms used-bytes messages 0x62270166 0 xie 666 26 1 success to receive message, cnt=26 read data = hello world, hello linux!
相关文章推荐
- Linux快速入门教程-进程管理ipcs命令学习
- Linux进程入门学习(一)-认识进程
- Linux进程入门学习(六)-管道通信
- linux学习入门 基础部分(7)【1.进程定义2.ps命令3.进程优先级4.环境中进程的前后台调用5.进程信号6.用户登陆审记7.top命令】
- Linux进程入门学习(四)-进程启动退出
- Linux进程入门学习(三)-进程创建等待
- Linux进程入门学习(二)-基础知识
- Linux进程入门学习(五)-IPC介绍
- Linux入门学习——进程
- Linux进程入门学习(七)-信号通信
- Linux操作系统下C语言编程入门学习笔记(...20090601(第一遍学完待整理)...)
- Linux学习笔记---进程
- 嵌入式Linux开发学习如何入门、如何深入?
- 入门篇-学习点滴之最简单的Linux关机命令程序
- linux 进程学习(二)
- 通过一个Linux漏洞学习Linux入门知识
- linux 进程通信-信号学习总结(1)
- 关于Linux的Cron进程的学习总结
- 入门学习linux的建议red hat linux或者ubuntu