前言:天下武功为快不破!在信息爆炸、快速发展的新时代...,扯远了...。进程间通信方式有很多,但最快的方式你知道么?由我娓娓道来...

  一、共享内存方式

  主角闪亮登场了,噔噔瞪...,最快的方式就是共享内存了。实现共享内存的方式主要有两种:

  1. 存储映射I/O mmap函数实现
  2. shmget函数

   感觉学两个以上相同的知识时,就会学他们的区别,我也会避免不了进入俗套,也要简单来说它们的区别:

  

 注:此图引自《unix环境高级编程》 

  看到图片中“主要区别”四个大字了么?别告诉我:你近视看不到,打死你个龟孙!开玩笑啦,哈哈哈!只希望在学习知识时,不要感觉太乏味哦。在下文介绍完两种方式之后,你就会不明白它们的区别了。

  二、mmap函数实现共享内存

  1、存储映射I/O

   先来画个见图来介绍一下实现原理,如下图:  PS:依旧是全博客园最丑图,不接受反驳!!!

  

  mmap函数主要作用就是将磁盘文件映射到内存中,并返回这段内存的首地址,并可以将这块内存来当做“数组”来处理。要对这个图有一个模型(虽然是全博客园最丑图),对接下来的讲解有一定帮助。

  2、mmap函数及相关函数

  原型:void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

  返回:成功:返回创建的映射区首地址;失败:MAP_FAILED宏,注意错误跟普通的不一样!

  参数说明:

addr:       建立映射区的首地址,由Linux内核指定。使用时,直接传递NULL

length: 欲创建映射区的大小

prot:      映射区权限PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE

flags:     标志位参数(常用于设定更新物理区域、设置共享、创建匿名映射区)

MAP_SHARED:  会将映射区所做的操作反映到物理设备(磁盘)上。

MAP_PRIVATE: 映射区所做的修改不会反映到物理设备。

fd:         用来建立映射区的文件描述符

offset: 映射文件的偏移(4k的整数倍)

  3、munmap函数

  原型:int munmap(void *addr, size_t length); 成功:0; 失败:-1

  功能:同malloc函数申请内存空间类似的,mmap建立的映射区在使用结束后也应调用类似free的函数来释放。

  4、父子进程用mmap示例程序

  程序主要用共享内存进行通信,如下:

  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h> int var = ; int main(void)
{
int *p;
pid_t pid; int fd;
fd = open("temp", O_RDWR|O_CREAT|O_TRUNC, );
if(fd < ){
perror("open error");
exit();
}
unlink("temp"); //删除临时文件目录项,使之具备被释放条件.
ftruncate(fd, ); //p = (int *)mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
p = (int *)mmap(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, );
if(p == MAP_FAILED){ //注意:不是p == NULL
perror("mmap error");
exit();
}
close(fd); //映射区建立完毕,即可关闭文件 pid = fork(); //创建子进程
if(pid == ){
*p = ;
var = ;
printf("child, *p = %d, var = %d\n", *p, var);
} else {
sleep();
printf("parent, *p = %d, var = %d\n", *p, var);
wait(NULL); int ret = munmap(p, ); //释放映射区
if (ret == -) {
perror("munmap error");
exit();
}
} return ;
}

  三、匿名映射

  1、说明

通过使用我们发现,使用映射区来完成文件读写操作十分方便,父子进程间通信也较容易。但缺陷是,每次创建映射区一定要依赖一个文件才能实现。通常为了建立映射区要open一个temp文件,创建好了再unlink、close掉,比较麻烦。 可以直接使用匿名映射来代替。其实Linux系统给我们提供了创建匿名映射区的方法,无需依赖一个文件即可创建映射区。同样需要借助标志位参数flags来指定。

  使用MAP_ANONYMOUS (或MAP_ANON), 如:

  int *p = mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  "4"随意举例,该位置表大小,可依实际需要填写。

  需注意的是,MAP_ANONYMOUS和MAP_ANON这两个宏是Linux操作系统特有的宏。在类Unix系统中如无该宏定义,可使用如下两步来完成匿名映射区的建立。

  ① fd = open("/dev/zero", O_RDWR);

  ② p = mmap(NULL, size, PROT_READ|PROT_WRITE, MMAP_SHARED, fd, 0);

  2、用"/dev/sero"示例匿名映射

  程序如下:

  

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h> int main(void)
{
int *p;
pid_t pid; int fd;
fd = open("/dev/zero", O_RDWR); p = mmap(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, ); if(p == MAP_FAILED){ //注意:不是p == NULL
perror("mmap error");
exit();
} pid = fork(); //创建子进程
if(pid == ){
*p = ;
printf("child, *p = %d\n", *p);
} else {
sleep();
printf("parent, *p = %d\n", *p);
} munmap(p, ); //释放映射区 return ;
}

  

  总结:shmget函数会在另一篇博客介绍,欢迎评论交流

  

最快的进程间通信方式你get了么的更多相关文章

  1. Linux下进程间通信--共享内存:最快的进程间通信方式

    共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...

  2. 进程间的八种通信方式----共享内存是最快的 IPC 方式

    1.无名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. 2.高级管道(popen):将另一个程序当做一个新 ...

  3. unix进程间通信方式(IPC)

    unix进程间通信方式(IPC) 管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信. 命名管道(named pipe):命名管道克服了管道没有 ...

  4. 【转】进程间通信方式总结(windows 和linux)

    平时看的书很多,了解的也很多,但不喜欢总结,这不昨天面试的时候被问到了进程间通信的方式,因为没有认真总结过,所以昨天答得不是特别好.现在将linux和windows的进程间通信方式好好总结一下.    ...

  5. Android六大进程间通信方式总结之一:基本知识

    因为不同进程都是享有独立资源的,所以全局变量这些都是无效的,必须有其他的进程间通信方式. 一.基本知识 1:怎样使用多进程 Android正常使用的多进程的办法只有一种,就是在Service或Acti ...

  6. C# 简单的进程间通信方式

    只想实现一个简单的进程建通信,有什么快速实现方式? 1 进程单例需求 / Windows 消息与 IMessageFilter 如果需求是实现一个进程单例,在启动第二个进程时,期望能自动唤起第一个进程 ...

  7. IPC 进程间通信方式——管道

    进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...

  8. python学习笔记——进程间通信方式对比

     通信方式对比   管道 消息队列 共享内存 信号 开辟空间 内存 内存 内存 不开辟额外空间 读写方式 双向/单向(信息流) 先进先出(消息体) 操作内存(数值数组) 发送处理信号 效率 一般 一般 ...

  9. linux 进程间通信方式

    管道: 它包括无名管道和有名管道两种,前者用于父进程和子进程间的通信,后者用于运行于同一台机器上的任意两个进程间的通信消息队列: 用于运行于同一台机器上的进程间通信,它和管道很相似,是一个在系统内核中 ...

随机推荐

  1. Love Live!-01字典树启发式合并

    链接:https://ac.nowcoder.com/acm/contest/201/D?&headNav=www 思路:题目要求的是每个等级下的最大 简单路径中的最大异或值,那么我们为了保证 ...

  2. iOS开发之图片压缩实现

    使用下面两个方法,先按尺寸重绘图片,然后再降低品质上传图片data #pragma mark 裁剪照片 -(UIImage *)scaleToSize:(UIImage *)image size:(C ...

  3. JS实现快速排序,冒泡排序

    JS-排序详解-冒泡排序   说明 时间复杂度指的是一个算法执行所耗费的时间 空间复杂度指运行完一个程序所需内存的大小 稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面 不稳定指,如果a=b, ...

  4. That girl

    音标 词汇 Purple Glasses Black Hat Brown Bag Clothes Blue Jacket Pink Handbag Sock White Skirt Shoe 1, s ...

  5. OI中常犯的傻逼错误总结

    OI中常犯的傻逼错误总结 问题 解决方案 文件名出错,包括文件夹,程序文件名,输入输出文件名  复制pdf的名字  没有去掉调试信息  调试时在后面加个显眼的标记  数组开小,超过定义大小,maxn/ ...

  6. 洛谷p3801:红色的幻想乡

    初见完全没有思路.....感觉像是线段树 但二维感觉完全不可做嘛 于是只能去看了看题解 然而还是疯狂爆零+WA.. 和yycc神犇调了两三个小时才调出来... ——————以下个人理解 考虑到每次的修 ...

  7. 新建一个express项目的流程

    1.先创建一个文件夹,然后创建一个项目,默认有一个:package.json 文件 #初始化项目 npm init 2.初始化项目会出现一个默认的提醒 #这个实用程序将指导您创建一个包,json文件. ...

  8. python函数用法

    一.定义函数 形参:函数完成一项工作所需要的信息,在函数定义时完成 实参:调用函数时传递给函数的信息 二.传递实参 1.位置实参:每个实参都关联到函数定义中的一个形参 示例: def describe ...

  9. 使用gulp打包普通项目

    前言: 在使用gulp打包工具之前,我做的H5项目在浏览器中的缓存是很严重的,若改了一点css,加了一句js代码,不手动清除浏览器缓存是看不到效果的.老总也在项目演示当中遇到这些问题,一查找原因却是缓 ...

  10. kodexplorer免费网盘安装教程

    KodExplorer是什么? KodExplorer可道云,原名芒果云,是基于Web技术的私有云和在线文件管理系统. 用户只需通过简单环境搭建,即可使用KodExplorer快速完成私有云/私有网盘 ...