linux 进程间通信机制(IPC机制)一消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
一.头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
二.函数
1.ftok
(1)原型:
key_t ftok( char * fname, int id )
(2)参数:
fname:指定的文件名
id:子序号(虽然为int,但是只有8个比特被使用(0-255))
(3)返回值:
成功 --- key_t值,失败 --- -1
(4)作用:
系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
2.msgget
(1)原型:
int msgget(key_t key, int msgflg)
(2)参数:
key:来源于ftok返回的IPC键值(0(IPC_PRIVATE):会建立新的消息队列)
msgflg:
0666|IPC_CREAT --- 如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列,返回此消息队列的标识符
0666|IPC_CREAT|IPC_EXCL --- 如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列则报错
(3)返回值:
成功 ---返回消息队列的标识符,失败 --- -1,错误原因存于error中
(4)作用:
得到消息队列标识符或创建一个消息队列对象
(5)错误码:
EACCES:指定的消息队列已存在,但调用进程没有权限访问它
EEXIST:key指定的消息队列已存在,而msgflg中同时指定IPC_CREAT和IPC_EXCL标志
ENOENT:key指定的消息队列不存在同时msgflg中没有指定IPC_CREAT标志
ENOMEM:需要建立消息队列,但内存不足
ENOSPC:需要建立消息队列,但已达到系统的限制
3.msgctl
(1)原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
(2)参数:
msqid:消息队列标识符
cmd:
IPC_STAT:获得msgid的消息队列头数据到buf中
IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes
IPC_RMID:删除消息队列,将队列从系统内核中删除
buf:消息队列管理结构体
(3)返回值:
成功 --- 0,失败 --- -1,错误原因存于error中
(4)作用:
获取和设置消息队列的属性
(5)错误码:
EACCESS:参数cmd为IPC_STAT,确无权限读取该消息队列
EFAULT:参数buf指向无效的内存地址
EIDRM:标识符为msqid的消息队列已被删除
EINVAL:无效的参数cmd或msqid
EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行
3.msgsnd
(1)原型:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
(2)参数:
msqid:消息队列标识符
msgp:发送给队列的消息。msgp可以是任何类型的结构体,但第一个字段必须为long类型
参照格式如下:
struct s_msg{ /*msgp定义的参照格式*/
long type; /* 必须大于0,消息类型 */
char mtext[256]; /*消息正文,可以是其他任何类型*/
} msgp;
msgsz:要发送消息的大小,不含消息类型占用的4个字节,即mtext的长度
msgflg:
0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列
IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回
IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。
(3)返回值:
成功 --- 0,失败 --- -1,错误原因存于error中
(4)作用:
将msgp消息写入到标识符为msqid的消息队列
(5)错误码:
EAGAIN:参数msgflg设为IPC_NOWAIT,而消息队列已满
EIDRM:标识符为msqid的消息队列已被删除
EACCESS:无权限写入消息队列
EFAULT:参数msgp指向无效的内存地址
EINTR:队列已满而处于等待情况下被信号中断
EINVAL:无效的参数msqid、msgsz或参数消息类型type小于0
4.msgrcv
(1)原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
(2)参数:
msqid:消息队列标识符
msgp:存放消息的结构体,结构体类型要与msgsnd函数发送的类型相同
msgsz:要发送消息的大小,不含消息类型占用的4个字节,即mtext的长度
msgtyp:
0:接收第一个消息
>0:接收类型等于msgtyp的第一个消息
<0:接收类型等于或者小于msgtyp绝对值的第一个消息
msgflg:
0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待
IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG
IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息
IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃
(3)返回值:
成功 --- 0,失败 --- -1,错误原因存于error中
(4)作用:
从标识符为msqid的消息队列读取消息并存于msgp中,读取后把此消息从消息队列中删除
(5)错误码:
E2BIG:消息数据长度大于msgsz而msgflag没有设置IPC_NOERROR
EIDRM:标识符为msqid的消息队列已被删除
EACCESS:无权限读取该消息队列
EFAULT:参数msgp指向无效的内存地址
ENOMSG:参数msgflg设为IPC_NOWAIT,而消息队列中无消息可读
EINTR:等待读取队列内的消息情况下被信号中断
三.书上看到的例子:
1.msgrcv.c
#include <unistd.h>//ftok头函数
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>//msg头函数#define PATH "./msg"//指定文件路径
#define TEXT_SIZE 1024struct msg_st
{long int msg_type;char text[TEXT_SIZE];
};int main()
{int running = 1;int msgid = -1;struct msg_st data;long int msgtype = 2;//msgtype>0时,要和发送端的一致key_t key = ftok(PATH,4);msgid = msgget(key, 0666 | IPC_CREAT);if(msgid == -1){fprintf(stderr, "msgget failed with error: %d\n", errno);exit(EXIT_FAILURE);}while(running){if(msgrcv(msgid, (void*)&data, TEXT_SIZE+sizeof(long int), msgtype, 0) == -1){fprintf(stderr, "msgrcv failed with errno: %d\n", errno);exit(-1);}printf("You wrote: %s\n",data.text);if(strncmp(data.text, "end", 3) == 0)running = 0;}//删除消息队列 if(msgctl(msgid, IPC_RMID, 0) == -1){fprintf(stderr, "msgctl(IPC_RMID) failed\n");exit(-1);}exit(0);
}
2.msgsnd
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>#define PATH "./msg"
#define TEXT_LEN 1024
struct msg_st
{long int msg_type;char text[TEXT_LEN];
};int main()
{int running = 1;struct msg_st data;char buffer[TEXT_LEN];int msgid = -1;key_t key = ftok(PATH,4);msgid = msgget(key, 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, TEXT_LEN, stdin);data.msg_type = 2;//如果service端 msgtype>0, client端的msgtype要和service端一致strcpy(data.text, buffer);if(msgsnd(msgid, (void*)&data, TEXT_LEN+sizeof(long int), 0) == -1){fprintf(stderr, "msgsnd failed\n");exit(-1);}if(strncmp(buffer, "end", 3) == 0)running = 0;sleep(1);}exit(0);
}
转载于:https://www.cnblogs.com/yaosj/p/6738006.html
linux 进程间通信机制(IPC机制)一消息队列相关推荐
- 20155301 滕树晨linux基础——linux进程间通信(IPC)机制总结
20155301 滕树晨linux基础--linux进程间通信(IPC)机制总结 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在 ...
- linux基础——linux进程间通信(IPC)机制总结
原 linux基础--linux进程间通信(IPC)机制总结 2016年07月23日 21:33:12 yexz 阅读数:18224更多 <div class="tags-box sp ...
- 2017-2018-1 20155222 《信息安全系统设计基础》第10周 Linux下的IPC机制
2017-2018-1 20155222 <信息安全系统设计基础>第10周 Linux下的IPC机制 IPC机制 在linux下的多个进程间的通信机制叫做IPC(Inter-Process ...
- Linux 环境进程间通信(三):消息队列
本系列文章中的前两部分,我们探讨管道及信号两种通信机制,本文将深入第三部分,介绍系统 V 消息队列及其相应 API. 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix ...
- Linux C 进程间的IPC通信 之 消息队列(2)
Linux C 进程间的IPC通信 之 消息队列 双向通信 代码:(进程1) 1 #include <stdio.h>2 #include <sys/msg.h>3 #incl ...
- System V IPC POSIX IPC(一):消息队列
System V IPC & POSIX IPC(一):消息队列 消息队列允许进程之间以消息的形式交换数据,是一种常见的进程之间的通信机制. 1. 消息队列的创建 System V IPC: ...
- linux进程间通信-XSI IPC
一 什么是XSI IPC 有三种 IPC我们称作XSI IPC,即消息队列.信号量以及共享存储器(共享内存),它们之间有很多相似之处. 二 标识符和键 每个内核中的 IPC结构(消息队列.信号 ...
- Linux系统编程(七)消息队列
Linux系统编程(七)消息队列 一.什么是消息队列 二.消息队列内部原理 三.实现消息队列的收发 1.发送消息队列 2.接收消息队列 四.消息队列与命名管道的比较 一.什么是消息队列 消息队列提供了 ...
- IPC通信:Posix消息队列的属性设置
IPC通信:Posix消息队列的属性设置 Posix消息队列的属性使用如下结构存放: struct mq_attr { long mq_flags; /*阻塞标志位,0为非阻塞(O_NONBLOCK) ...
- Linux的常见IPC机制简介
IPC机制:Inter-Process Communication,进程间通信机制 本文简述的IPC机制有:管道pipe.命名管道FIFO.信号.信号量.消息队列.共享内存.内存映射 1.管道pipe ...
最新文章
- python官方书籍-有哪些Python入门的书籍值得推荐?
- redis和kafka读取代码
- python股票历史最低点_Python统计某一只股票每天的开盘,收盘,最高,最低价格!...
- 服务器无法在发送 http 标头之后设置内容类型。_python socket编程预知内容
- dubbo + zookeeper 简介和部署
- linux内存手动释放
- spring mvc mvc:default-servlet-handler / 。
- oracle导出大数据
- AsyncTask与Thread+Handler的区别、AsyncTask的使用
- jxta java_JXTA-JavaP2P JXT
- Microsoft Excel 教程「3」:如何在 Excel 中打印工作表?
- CAD二次开发 对象
- 【ceph】分布式存储ceph
- Java教程:如何对接自定义钉钉机器人并实现群聊消息发送
- linux输入法搜狗 修复,搜狗输入法自带修复功能,可以解决无法打字的问题
- WIFI性能测试二 --- wifi的ANI功能
- 《缠中说禅108课》52:炒股票就是真正的学佛
- 那个给三千人算命的大师,正在给自己水滴筹
- 计算机视觉之目标检测与轨迹追踪
- JobManager 内存简介
热门文章
- 话费充值 php,话费充值示例代码
- 初一计算机课学什么,初一有哪几门课程 各科满分是多少
- python:画图调整图例位置
- 历年蓝桥杯日期类问题总结
- python用matplotlib画皮卡丘_python使用matplotlib绘图 -- barChart
- php soapenv:server.userexception,SoapFault - faultcode: 'soap:Server' faultstring
- android 布局图片缩放,Android中进行图片缩放显示
- 微宝球型机器人功能_腾讯智能球型机器人专属app(微宝)
- python做服务器需要什么模块_用Python自带的包建立简单的web服务器
- PostgreSQL 10.1 手册_部分 II. SQL 语言_第 10 章 类型转换_10.5. UNION、CASE和相关结构...