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 ...
随机推荐
- 开启VMSS Autoscale的报警功能
VMSS可以自动的实现Scale Out和Scale in.在VMSS做自动操作的时候,可以通过配置通知服务,通知VMSS的状态. 具体实现方式: 1, 在portal中选择"监视器&quo ...
- 在Azure上搭建L2TP服务器
L2TP是常用的一种point-site的VPN.而目前在Azure上的VPN Gateway只支持IPsec和SSTP两种.如果客户需要L2TP服务器,需要自己在VM中搭建.本文将介绍如何在Azur ...
- Linux测试程序 - 多线程
#include <sched.h> #include <pthread.h> main(){ pthread_t id0, id1, id2; ret=pthread_cre ...
- 学习vue
一,声明模板的时候需要新建示例 如下代码 <div id="app"> <my></my> </div> Vue.component ...
- 任意输入3个数,判断能否组成三角形(python)
任意输入3个数,判断能否组成三角形. 三角形:两边之和大于第三边 直角三角形:勾股定理 代码如下: # 输入合法性检查,必须输入正数,不支持科学计数法'''try: <语句>except ...
- linux 学习2 常用命令
1.显示日期的指令: date 2. [Tab]按键---具有『命令补全』不『档案补齐』的功能 3: su和 sudo su用于用户之间的切换. su在不加任何参数,默认为切换到root用户 ...
- ruby中nil?, empty? and blank?
In Ruby, you check with nil? if an object is nil: article = nil article.nil? # => true empty? che ...
- 设置mysql表名大小写不敏感
在跨平台的程序设计中要注意到mysql的一些系统变量在windows和linux上的缺省值是不同的, 比如mysql表名称的大小写变量. 在windows上lower_case_table_names ...
- 问题:oracle 计算年龄;结果:oracle中根据生日计算年龄的问题
SELECT FLOOR(MONTHS_BETWEEN(SYSDATE,birthday)/12,1) FROM ltteacherinfo where name='朱雪东111'这个报错ORA 00 ...
- leetcode633
用开方的思想来解题. bool judgeSquareSum(int c) { int h = pow(c, 0.5); ; i <= h; i++) { ), 0.5); if (left - ...