前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux和Android的IPC通信简介

Linux和Android的IPC通信简介

作者头像
提莫队长
发布2020-06-02 15:31:27
1.6K0
发布2020-06-02 15:31:27
举报
文章被收录于专栏:刘晓杰刘晓杰

1.Linux和Android的IPC机制种类

IPC全名为inter-Process Communication,含义为进程间通信,是指两个进程之间进行数据交换的过程。在Android和Linux中都有各自的IPC机制,这里分别来介绍下。

1.1 Linux中的IPC机制种类

Linux中提供了很多进程间通信机制,主要有管道(pipe)、信号(sinal)、信号量(semophore)、消息队列(Message)、共享内存(Share Memory)、套接字(Socket)等。

1.2 Android中的IPC机制

Android系统是基于Linux内核的,在Linux内核基础上,又拓展出了一些IPC机制。Android系统除了支持套接字,还支持序列化、Messenger、AIDL、Bundle、文件共享、ContentProvider、Binder等。

2.Linux和Binder的IPC通信原理

在讲到Linux的进程通信原理之前,我们需要先了解Liunx中的几个概念。

概念

  • 内核空间和用户空间 User space(用户空间)和 Kernel space(内核空间)。内核空间是Linux内核的运行空间,用户空间是用户程序的运行空间。为了保护用户进程不能直接操作内核,保证内核的安全,操作系统从逻辑上将虚拟空间划分为用户空间和内核空间。Linux 操作系统将最高的1GB字节供内核使用,称为内核空间,较低的3GB 字节供各进程使用,称为用户空间。
  • 系统调用 用户空间需要访问内核空间,就需要借助系统调用来实现。系统调用是用户空间访问内核空间的唯一方式,保证了所有的资源访问都是在内核的控制下进行的,避免了用户程序对系统资源的越权访问,提升了系统安全性和稳定性。 进程A和进程B的用户空间可以通过如下系统函数和内核空间进行交互。 copy_from_user:将用户空间的数据拷贝到内核空间。 copy_to_user:将内核空间的数据拷贝到用户空间。
  • 内存映射 由于应用程序不能直接操作设备硬件地址,所以操作系统提供了一种机制:内存映射,把设备地址映射到进程虚拟内存区。 举个例子,如果用户空间需要读取磁盘的文件,如果不采用内存映射,那么就需要在内核空间建立一个页缓存,页缓存去拷贝磁盘上的文件,然后用户空间拷贝页缓存的文件,这就需要两次拷贝。由于新建了虚拟内存区域,那么磁盘文件和虚拟内存区域就可以直接映射,少了一次拷贝。 内存映射全名为Memory Map,在Linux中通过系统调用函数mmap来实现内存映射。将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间,反之亦然。内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。
2.1 Linux的IPC通信原理

Linux的IPC通信原理

内核程序在内核空间分配内存并开辟一块内核缓存区,发送进程通过copy_from_user函数将数据拷贝到到内核空间的缓冲区中。同样的,接收进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用 copy_to_user() 函数将数据从内核缓存区拷贝到接收进程。这样数据发送进程和数据接收进程完成了一次数据传输,也就是一次进程间通信。 Linux的IPC通信原理有两个问题:

  • 一次数据传递需要经历:用户空间 --> 内核缓存区 --> 用户空间,需要2次数据拷贝,这样效率不高。
  • 接收数据的缓存区由数据接收进程提供,但是接收进程并不知道需要多大的空间来存放将要传递过来的数据,因此只能开辟尽可能大的内存空间或者先调用API接收消息头来获取消息体的大小,浪费了空间或者时间。
2.2 Binder的通信原理

Binder是基于内存映射来实现的,大致原理如下图:

Binder的通信原理

Binder通信的步骤如下

  • Binder驱动在内核空间创建一个数据接收缓存区。
  • 在内核空间开辟一块内核缓存区,建立内核缓存区和数据接收缓存区之间的映射关系,以及数据接收缓存区和接收进程用户空间地址的映射关系。
  • 发送方进程通过copy_from_user()函数将数据拷贝 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。 整个过程只使用了1次拷贝,不会因为不知道数据的大小而浪费空间或者时间,效率更高。

(PS:为啥需要两次映射?感觉一次就可以了)

3.Binder优势

  • 性能方面 性能方面主要影响的因素是拷贝次数,管道、消息队列、Socket的拷贝次书都是两次,性能不是很好,共享内存不需要拷贝,性能最好,Binder的拷贝次书为1次,性能仅次于内存拷贝。
  • 稳定性方面 Binder是基于C/S架构的,这个架构通常采用两层结构,在技术上已经很成熟了,稳定性是没有问题的。共享内存没有分层,难以控制,并发同步访问临界资源时,可能还会产生死锁。从稳定性的角度讲,Binder是优于共享内存的。
  • 安全方面 Android是一个开源的系统,并且拥有开放性的平台,市场上应用来源很广,因此安全性对于Android 平台而言极其重要。 传统的IPC接收方无法获得对方可靠的进程用户ID/进程ID(UID/PID),无法鉴别对方身份。Android 为每个安装好的APP分配了自己的UID,通过进程的UID来鉴别进程身份。另外,Android系统中的Server端会判断UID/PID是否满足访问权限,而对外只暴露Client端,加强了系统的安全性。
  • 语言方面 Linux是基于C语言,C语言是面向过程的,Android应用层和Java Framework是基于Java语言,Java语言是面向对象的。Binder本身符合面向对象的思想,因此作为Android的通信机制更合适不过。

从这四方面来看,Linux提供的大部分IPC机制根本无法和Binder相比较,而共享内存只在性能方面优于Binder,其他方面都劣于Binder,这些就是为什么Android要使用Binder来进行进程间通信,当然系统中并不是所有的进程通信都是采用了Binder,而是根据场景选择最合适的,比如Zygote进程与AMS通信使用的是Socket,Kill Process采用的是信号。

参考文章:https://www.jianshu.com/p/52e15875c81d

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Linux和Android的IPC机制种类
  • 2.Linux和Binder的IPC通信原理
  • 3.Binder优势
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档