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 ...
随机推荐
- php 服务器的安全笔记
php 服务器的安全笔记 操作系统安全 默认端口修改 MySQL 端口禁止外网访问 用户权限 父进程 子进程 目录权限 TODO Web Server 版本信息 服务器版本信息 PHP 版本 open ...
- 分区工具parted的详解及常用分区使用方法
一. parted的用途及说明 概括使用说明: parted用于对磁盘(或RAID磁盘)进行分区及管理,与fdisk分区工具相比,支持2TB以上的磁盘分区,并且允许调整分区的大小. ...
- centos7 安装 mysql-python时 报错 EnvironmentError: mysql_config not found
pip install mysql-python 然后报错 EnvironmentError: mysql_config not found 网上搜解决方法,需要安装 mysql-devel 然后 ...
- svn更新报错:出现skipped:目标路径
skipped 意为:跳过此目标文件: 一般出现在目标文件被删除后,重新更新情况下: 解决办法及结果: 1,回到此目标文件的上一层文件夹,team-clean up,结果不成功 2,回到此目标文件的上 ...
- 第十四届华中科技大学程序设计竞赛决赛同步赛 A - Beauty of Trees
A - Beauty of Trees 题意: 链接:https://www.nowcoder.com/acm/contest/119/A来源:牛客网 Beauty of Trees 时间限制:C/C ...
- DCloud-HBulder:杂项
ylbtech-DCloud-HBulder:杂项 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 ...
- #define和const的区别
下面使用#define和const定义常量: #define n_define 10 int main(int argc, char* argv[],int _version) { ; int *p= ...
- c语言-顺序表
在数据结构中包含两种,一种线性结构(包括顺序表,链表,栈,队列),一种非线性结构(树,图), 顺序表,其实就是在内存动态数组,Java中的ArrayList就是一个典型的顺序表,它在顺序表的基础上增加 ...
- linux yum 脚本实现
yum 位于linux /usr/bin/yum yum命令是python脚本进行编写的(python 2.6) #!/usr/bin/python2.6 import sys try: import ...
- “百度杯”CTF比赛 2017 二月场(Misc Web)
爆破-1: 打开链接,是502 我直接在后面加个变量传参数:?a=1 出了一段代码 var_dump()函数中,用了$$a,可能用了超全局变量GLOBALS 给hello参数传个GLOBALS 得到f ...