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 1024 struct 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);
}
linux 进程间通信机制(IPC机制)一消息队列的更多相关文章
- c/c++ linux 进程间通信系列6,使用消息队列(message queue)
linux 进程间通信系列6,使用消息队列(message queue) 概念:消息排队,先进先出(FIFO),消息一旦出队,就从队列里消失了. 1,创建消息队列(message queue) 2,写 ...
- Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()
下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提 ...
- 20155301 滕树晨linux基础——linux进程间通信(IPC)机制总结
20155301 滕树晨linux基础--linux进程间通信(IPC)机制总结 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在 ...
- 20155332 linux进程间通信(IPC)机制(未完成,待续)
linux进程间通信(IPC)机制 1.共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在该进程的地址空间(这里的地址空间具体是哪个 ...
- 2017-2018-1 20155222 《信息安全系统设计基础》第10周 Linux下的IPC机制
2017-2018-1 20155222 <信息安全系统设计基础>第10周 Linux下的IPC机制 IPC机制 在linux下的多个进程间的通信机制叫做IPC(Inter-Process ...
- Linux下的IPC机制
Linux下的IPC机制 IPC(Inter-Process Communication)是多个进程之间相互沟通的一种方法.在linux下有多种进程间通信的方法. 共享内存 Linux内存共享有多种, ...
- linux进程间通信-XSI IPC
一 什么是XSI IPC 有三种 IPC我们称作XSI IPC,即消息队列.信号量以及共享存储器(共享内存),它们之间有很多相似之处. 二 标识符和键 每个内核中的 IPC结构(消息队 ...
- IPC通信:Posix消息队列
IPC通信:Posix消息队列 消息队列可以认为是一个链表.进程(线程)可以往里写消息,也可以从里面取出消息.一个进程可以往某个消息队列里写消息,然后终止,另一个进程随时可以从消息队列里取走这些消息. ...
- linux下六大IPC机制【转】
转自http://blog.sina.com.cn/s/blog_587c016a0100nfeq.html linux下进程间通信IPC的几种主要手段简介: 管道(Pipe)及有名管道(named ...
- Linux IPC System V 消息队列
模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ftok() //获取key ...
随机推荐
- source In sight 中修改自动补全快捷键方式
点击 “options”中的“key Assi...”,找到如下 点击“Assign New Key...”之后按键盘上的指定按键就能重新设定.
- Operating System-进程间互斥的问题-生产者&&消费者引入
之前介绍的几种解决进程间互斥的方案,不管是Peterson方案还是TSL指令的方式,都有一个特点:当一个进程被Block到临界区外面时,被Block的进程会一直处于忙等待的状态,这个不但浪费了CPU资 ...
- java编程思想第八章多态
前言: 封装:通过合并特征和行为创建新的数据类型. 实现隐藏:通过将细节“私有化”,把接口和实现分离. 多态:消除类型间的耦合关系.也称作动态绑定,后期绑定或运行时绑定. 8.1再论向上转型: 对象既 ...
- webrtc自带client的音频引擎创建代码走读
src\webrtc\examples\peerconnection\client\conductor.cc1.bool Conductor::InitializePeerConnection()1. ...
- Azure VM Disk的设计与部署
Azure的VM的设计中,Disk相关的设计是非常重要的一个内容,本文将介绍Azure上的VM的Disk相关的一些最佳实践和一些小的技巧. 一.Azure VM中Disk的存储账户设计 1. Stor ...
- Ext.window.Window
var win = Ext.create("Ext.window.Window", { id: "myWin", title: "示例窗口" ...
- KVO键值监听
KVO 键值监听:当我想知道一个对象的属性是否发生改变的时候 做出响应,就需要添加监听keypath 和 key的区别keypath会自动寻找子类的属性key只会寻找当前类的属性添加键值监听[pers ...
- 隔行变色---bai
<!DOCTYPE html> <html> <style> .mousein { background-color:blue; cursor: pointer; ...
- Celery-4.1 用户指南: Workers Guide (Workers 指南)
启动工作单元 你可以通过执行以下命令在前台启动工作单元: $ celery -A proj worker -l info 查看启动工作单元的可用命令行选项,可以执行: $ celery worker ...
- scrapy xpath 节点关系
父节点 子节点 兄弟节点 先辈节点 后代节点