(三)Android架构拆解——进程/线程间通信(Binder IPC)

好文推荐:
Android 操作系统架构开篇 - Gityuan博客 | 袁辉辉的技术博客
Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? - sheldon_blogs - 博客园
        (一)在安卓系统中,各组件和模块间必然涉及进程间或者线程间的通信。专业术语称为IPC(Inter-Process Communication,进程间通信),常见Linux的IPC机制有:Pipe管道,Message报文队列,Share Memory共享内存,Socket字节套,Semaphore信号量,Signal信号。Android系统中,上层架构最常用的IPC机制:Binder粘合剂,Socket字节套,Handler处理者。在内核层和系统运行层之间的Binder IPC机制
        (二)基础概念:
        ●进程隔离,进程间不可直接相互访问资源,简单来说就是操作系统中,进程间内存不共享,彼此之间要通信就要采用特殊的通信机制——>IPC
        ●进程空间划分用户空间(user space)内核空间(kernel sapce),操作系统都采用虚拟存储器,对于32位系统而言,虚拟存储空间就是2的32次方,也就是4GB,内核是操作系统的核心,它独立于普通的应用程序,可以访问受保护的内存空间,也可以访问底层硬件设备的权限。为了保护用户进程不能直接操作内核,保证其安全,操作系统从逻辑上将虚拟空间划分为用户空间和内核空间。针对Linux系统来说,将最高的1GB字节给内核使用,即为内核空间,3GB字节给各进程使用,成为用户空间,他们在各自空间运行,相互独立。
        ●系统调用,用户态&内核态,虽然从逻辑上进行了用户空间和内核空间的划分,但不可避免的用户空间需要访问内核资源,比如文件操作,访问网络等等。为了突破隔离限制,就需要借助系统调用来实现。系统调用是用户空间访问内核空间的唯一方式,保证了所有的资源访问都是在内核的控制下进行的,避免了用户程序对系统资源的越权访问,提升了系统安全性和稳定性。当一个进程执行系统调用而陷入内核代码中执行时,称进程处于内核运行态(内核态),执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈。当进程在执行用户自己的代码的时候,则称其处于用户运行态(用户态)
        系统调用主要通过两个函数来实现
        copy_from_user() //将数据从用户空间拷贝到内核空间
        copy_to_user() //将数据从内核空间拷贝到用户空间
       
(三)Linux下的传统IPC通信原理
        方式:消息发送方将要发送的数据存放在内存缓存区中,通过系统调用进入内核态,然后内核程序在内核空间分配内存,开辟一块内核缓存区,调用copy_from_user()函数将数据从用户空间的内存缓存区拷贝到内核空间的内核缓存区中。同样的,接收方进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用copy_to_user()函数将数据从内核缓存区拷贝到接收进程的内存缓存区。
        这种传统的IPC通信方式有两个显著缺点:
(1)一次数据传递需要经历:内存缓存区——>内核缓存区——>内存缓存区,需要2次数据拷贝,效率低,可能此时会想到共享内存的方式,但是其难于控制不稳定;
(2)接收数据的缓存区由数据接收进程提供,但是接收进程并不知道需要多大空间来存放将要传递过来的数据,因此只能开辟尽可能大的内存空间或者先调用API接收消息头来获取消息体的大小,对于手机这种资源紧张的嵌入式移动设备来说无疑是巨大的负担。
       可见传统IPC效率低,占资源,除此之外还有安全、稳定性等缺点不足以胜任Android的核心进程间通信方式。        
        Binder IPC高效性:共享内存的数据拷贝次数0次,Binder的数据拷贝次数1次,Socket/管道/消息队列的数据拷贝次数2次。
        Binder IPC稳定性:该机制属于C/S架构,客户端(Client)有什么需求就丢给服务端(server)去完成,架构清晰、职责明确又相互独立,稳定性好,相比于内存共享的复杂控制的缺点,Binder IPC机制更加稳定。
        Binder IPC安全性:为每个APP分配UID,进程的UID是鉴别进程身份的重要标志。
        (四)Binder IPC通信原理
        传统IPC机制都是内核的一部分,因此通过内核支持来实现进程间通信就没有问题,但Binder不是Linux系统内核的一部分,这时需要添加动态内核可加载模块(具有独立功能的程序,可以单独编译,但不能独立运行,运行时被链接到内核作为内核的一部分运行)运行在内核空间,用户之间通过这个内核模块来实现通信,这各模块就叫Binder驱动(Binder Driver)。接着,通过内存映射(mmap)功能,将用户空间的一块内存区域映射到内核空间,这样这块内存区域的修改可以直接反映到内核空间,反之内核空间对这段区域的修改也能直接反映到用户空间,从而减少数据拷贝次数。
        一次完整的Binder IPC通信过程:
①Binder驱动在内核空间创建一个数据接收缓存区
②在内核空间开辟一块内核缓存区,建立内核缓存区数据接收缓存区之间的映射关系,以及数据接收缓存区接收进程用户空间地址的映射关系;
③发送方进程通过系统调用copy_from_user()将数据copy到内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间。

 Binder IPC原理图2:图片来源——彻底理解Android Binder通信架构 - Gityuan博客 | 袁辉辉的技术博客

ams_ipc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少卿不在大理寺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值