Linux 进程通信内存拷贝次数图解

原创
03/09 20:00
阅读数 1.4K

一、进程通信中“拷贝”的概念

拷贝:

  • 广义上讲就是任何数据复制,但是在Linux系统中比较特殊,这里的概念比较狭义,物理内存之间的数据复制才叫拷贝
  • IO设备、Input 、DMA(Direct Memory Access)与其他设备之间的数据复制不能称为拷贝

为什么要着重强调这个概念呢?

因为很多博客中讲sendfile、mmap,多次拷贝的时候出现了描述矛盾的问题。

 

1、两次拷贝 (这张图上有3个物理内存)

  • Copy From User   用户态->内核态
  • Copy To User        内核态->用户态

因此传统IO上,进程间的通信经过两次拷贝,而且这只是单向传输数据,如果B进程要返回结果给A进程,只需要把这张图中的A进程和B进程角色关系调换一下。也是就是说,如果是带返回值的IPC,至少需要4次拷贝。

细品Copy这个单词

我们发现,Copy From  User和Copy To User ? 作为主谓宾结构,到底是Who在Copy?

答案:是内核驱动程序,说明了一件事,进程通信需要内核允许

 

2、一次拷贝(这张图上有2个物理内存)

 

Binder 通信的实质,Binder 服务端和Binder用户端,进程A和B分别和内核态建立映射关系,这个映射关系依靠mmap完成,一次拷贝。

IPC通信,最多只需要2次拷贝,比传统方式少一倍。

 

3、0拷贝(这张图上1个物理内存)

A,B两用户态进程和内核态建立了同一虚拟内存地址的内存,因此,实现了内存共享,同样也是通过mmap实现

 

问题来了,共享内存这么高校为什么Android 通信不用?

实际上,Android并没有不用,只是在用户进程之间通信不推荐试用,Android使用共享内存的。Android使用共享内存的地方是SurfaceFlinger,Android App中可以使用共享内存的是工具是MemoryFile。

 

Google为什么不推荐呢?

共享内存无法实现高并发的复杂控制,可能出现用户进程A修改用户进程B数据的问题,对于一对一的通信缺陷并不大,但是多对一,多对多就是致命伤?

 

为什么SurfaceFlinger会使用共享内存?

  • SurfaceFlinger数据控制使用Binder,View绘制使用GraphicBuffer 共享内存
  • 共享内存传输数据非常高校,SurfaceFlinger直接和显示设备关联,需要尽可能避免图像数据延迟导致丢帧问题
  • 数据类型单一,无需安全校验
  • 进程之间是一对一,通过优先级合成图像

 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部