- 瑞瑞爱吃桃
-
从android Q开始,binder添加了ndk使用的接口,相关使用接口示例如下:
iface.h
iface.cpp
使用
为什么要引入binder ndk的接口呢? 答案很简单就是使用简单。像iface.h和iface.cpp 这两个文件完全可以通过aidl文件自动生成,接口使用简单,ABI稳定。谷歌相关的commit log
binder是什么意思
binder意思是粘合剂;结合剂;黏合剂;活页夹;装订工;装订机;(谷物)割捆机。双语例句:1、The final operation in propellant manufacture is the curing of the binder. 制造推进剂的最后操作是粘合剂的固化。2、Maggie: well your sister has her books, notebooks, paper, pencils, binders, course dividers. 麦琪:你妹妹拿好了书本笔记本纸张铅笔讲义夹绘图仪器。3、You should collect all your awards, transcripts, resumes, and even teaching ideas and compile them in a large binder. 你应该收集所有的奖状、成绩单、简历、甚至是教学思想,然后装订在一起。4、The and inferior binders fabrication process has become much more important. 黏合剂制作工艺优劣显得更加重要。5、Research progress of phosphate inorganic binder for high temperature esistance .磷酸盐基耐高温无机胶黏剂的研究进展。6、Durability of High Volume Fly Ash Concrete with Low Water Binder .低用水大掺量粉煤灰高性能砼的耐久性研究。7、The Adhesion Theory of Binder in the Pigment Coating System .通过理论计算分析了所用粘结剂组元的热力学相容性.颜料涂布系统中的胶粘剂的胶接理论。8、Relationship between penetration grade and performance high temperature grade of conventional asphalt binder .常规沥青的针入度等级和PG高温等级间的关系。9、Fractal Study on Granularity Distribution of α-Starch Composite Binder Powder .铸造用α淀粉复合粘结剂粉体粒度分布的分形研究。10、The Experimental Investigation on Morphological Effect of Lithium Slag under High and Low Water binder Ratio .锂渣在高低水胶比中形态效应的试验研。2023-06-17 14:52:141
BINDER是什么意思
binder 英[u02c8bau026andu0259(r)] 美[u02c8bau026andu025a] n. 粘合剂; 包扎物,包扎工具; [法] 临时契约; 装订工; [例句]The final operation in propellant manufacture is the curing of the binder.制造推进剂的最后操作是粘合剂的固化。[其他] 复数:binders2023-06-17 14:52:501
Binder 总结
binder是Android 中的一种进程间通信机制(IPC机制) android 是一种基于linux 的系统,linux 系统已经提供了 诸如管道、消息队列、共享内存和socket 等IPC 方式。既然已经存在了如此之多的IPC 机制,为什么binder还会出现?主要是因为上述IPC机制无法对android 而言存在着诸多的不便,主要体现在性能,稳定性和安全性三个方面。 综上,android中使用Binder作为其IPC 机制。 binder 主要是通过内存映射来实现的,一次完整的ipc通讯的过程如下: 1.binder 驱动在内核中创建一块数据接收缓冲区 2.建立一块内核缓冲区 3.建立内核缓冲区和数据接收缓冲区的映射 4.建立内核数据缓冲区和接收进城用户空间的映射 5.发送方将数据发送到内核缓冲区 6.由于映射的存在,就相当于直接将数据发送到了 接收进城中 binder 主要有四部分组成 其中binder client 、 binder service 和 servicemanager 运行在用户空间,而binder 驱动则是运行在内核空间(binder驱动是通过模块挂载的方式,运行在内核空间中的)。 binder 的工作流程其实可以类比为 上网的过程。客户端(binder client) 服务器(binder service) dns(servicemanager) 和 路由器(binder 驱动) 客户端输入网址请求服务器会在路由器的帮助下请求 dns 服务器获取服务器的ip地址,然后利用ip地址和服务器进行通讯。 binder基本的运行如下: 1.首先一个进城通过binder驱动将自己注册为servicemanager 2.service 通过binder 驱动将自己的binder 注册到servicemanager中,以对外使用。在这个过程中,binder驱动会生成该binder 的内核节点,以及该节点的引用,并将这些内容发送给servicemanager,servicemanager会把引用存入表中 3.client 通过binder名称,在binder驱动的帮助下在servicemanager中获取到service 中binder 的引用,从而跨进程通信 1.通过上述的工作流程可知,servicemanager 其实是一个特殊的进程,service 和 client 和 servicemanager 之间的通讯其实也是进程间的通讯,而这里的进程间通信其实也是使用的binder通信。这里的设计十分巧妙,servicemanager 是service 端,其他所有进程都是它的client 端,servicemanager提供了一个非常特殊的binder,他不需要注册也没有名字,其他进程可以直接获取到该binder 和servicemanager 进行通讯。 2.binder中还使用了代理模式,client 端所获取的service 的binder引用并不是一个真的binder对象,而是一个service端binder 的代理,调用binder中方法的时候通过对service进行请求然后获取返回结果。 android binder通信机制其实可以看作是一次简单的上网过程 1.客户端输入网址(发送端请求跨进程通信) 2.通过路由器查询dns 服务器 根据域名获取ip地址(通过binder驱动,获取servicemanager 中实名binder的引用) 3.根据返回的ip地址,通过路由器连接服务器(根据获取到service端的binder 代理 client端和service端进行通信 )2023-06-17 14:52:591
Binder机制概述
Android进程间通讯是通过Binder机制来实现的,Android是基于linux系统因此有必要了解Linux系统进程相关知识. Linux系统中(其他系统也是这样)不同进程之间不允许直接操作或访问另一进程.也就是进程隔离. 为了保证用户进程不能直接访问内核,操作系统从逻辑上将虚拟空间划分为用户空间和内核空间.内核程序运行在内核空间(kernel space),应用程序运行在用户空间(user space).为了安全,他们之间是隔离的,即使用户程序奔溃了,也不会影响内核.内核空间数据是可以共享的,用户空间不可以. 用户空间访问内核空间只能通过系统调用,系统调用是用户空间访问内核空间的唯一方式,保证所有资源访问在内核控制下,避免了用户对系统资源的越权访问,提高了系统安全性和稳定性. copy_from_user:将用户空间数据拷贝到内核空间 copy_to_user:将内核空间数据拷贝到用户空间 由于用户进程不能直接访问硬件地址,所以系统提供了一种机制:内存映射(Memory Map).在Linux中通过调用函数mmap实现内存映射,将用户空间一块内存地址映射到内核空间.映射关系建立后,对用户空间内存的修改可以反应到内核空间.内存映射可减少拷贝次数. 如果没有内存映射,用户进程需要访问硬盘文件时,需要在内核空间创建一片页缓存,将硬盘文件数据拷贝到页缓存然后用户进程在拷贝页缓存数据,需要两次拷贝.通过内存映射后硬盘文件可以和内核的虚拟内存直接映射,减少一次拷贝. 如图 inter-process-communication进程间通信,指进程间交换数据的过程. Linux提供了很多进程间通讯的机制,主要有管道(pipe)、消息队列(Message)、信号(sinal)、信号量(semophore)、套接字(socket)等 内核程序在内核空间分配并开辟一块内核缓冲区,发送进程将数据通过copy_from_user拷贝到内核空间的数据缓冲区,内核空间通过copy_to_user将数据拷贝到接收进程,这样就实现了一次进程间通信.如图 Linux的IPC机制有两个问题: 1.数据通过用户空间->内核空间->用户空间,经过两次拷贝,效率不高 2.接收进程无法预先知道数据大小,只能尽可能大创建数据缓冲区,或通过api消息头获取消息体的大小,浪费了空间或时间. Android进程间通信通过Binder实现,下面介绍Binder机制通信原理,为什么是Binder 内核程序创建一个数据接收缓存区,同时创建一个内核缓冲区.并建立内核缓冲区和数据接收缓冲区内存映射,以及数据内核缓冲区和接收进程用户空间的映射关系.发送进程通过copy_from_user将数据拷贝到内核数据接收缓冲区,因为内核数据接收缓冲区和内核缓冲区以及接收进程用户空间存在映射关系,相当于将数据发送到了接收进程.完成了一次进程间通信.如图 Binder机制是c/s架构的,由Client、server、ServiceManager和Binder组成.client、server和serviceManager都是独立的进程,由于Linux进程隔离的原因,所以需要借助Binder进行通信. Binder通信主要有三个步骤:注册服务、获取服务、使用服务.如下图 从上一条Binder实现原理示例图中可以看到,Binder可分为Java Binder、Native Binder和Kernal Binder.应用开发需要了解Java Binder和Navive Binder.这里只介绍Binder基本原理.具体可查看文章结尾的链接. 感谢 https://blog.csdn.net/itachi85/article/details/102713845 https://www.jianshu.com/p/429a1ff3560c https://blog.csdn.net/carson_ho/article/details/73560642?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159651217319195188353096%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=159651217319195188353096&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2 all first_rank_ecpm_v3~rank_business_v1-1-73560642.ecpm_v3_rank_business_v1&utm_term=Binder&spm=1018.2118.3001.41872023-06-17 14:53:091
深入理解Binder
之前一直对 Binder 理解不够透彻,仅仅知道一些皮毛,所以最近抽空深入理解一下,并在这里做个小结。 Binder 是 Android 系统中实现 IPC (进程间通信)的一种机制。Binder 原意是“胶水、粘合剂”,所以可以想象它的用途就是像胶水一样把两个进程紧紧“粘”在一起,从而可以方便地实现 IPC 。 那么为什么会有进程通信呢?这是因为在 Linux 中进程之间是隔离的,也就是说 A 进程不知道有 B 进程的存在,相应的 B 进程也不知道 A 进程的存在。A 、B 两进程的内存是不共享的,所以 A 进程的数据想要传给 B 进程就需要用到 IPC 。 在这里再科普一下进程空间的知识点:进程空间可以分为用户空间和内核空间。简单的说,用户空间是用户程序运行的空间,而内核空间就是内核运行的空间了。因为像内核这么底层、至关重要的东西肯定是不会简单地让用户程序随便调用的,所以需要把内核保护起来,就创造了内核空间,让内核运行在内核空间中,这样就不会被用户空间随便干扰到了。两个进程之间的用户空间是不共享的,但是内核空间是共享的。 所以到这里,有些同学会有个大胆的想法,两个进程间的通信可以利用内核空间来实现啊,因为它们的内核空间是共享的,这样数据不就传过去了嘛。但是接着又来了一个问题:为了保证安全性,用户空间和内核空间也是隔离的。那么如何把数据从发送方的用户空间传到内核空间呢? 针对这个问题提供了 系统调用 来解决,可以让用户程序调用内核资源。系统调用是用户空间访问内核空间的唯一方式,保证了所有的资源访问都是在内核的控制下进行的,避免了用户程序对系统资源的越权访问,提升了系统安全性和稳定性(这段话来自 《写给 Android 应用工程师的 Binder 原理剖析》 )。我们平时的网络、I/O操作其实都是通过系统调用在内核空间中运行的(也就是 内核态 )。 至此,关于 IPC 我们有了一个大概的实现方案:A 进程的数据通过系统调用把数据传输到内核空间(即copy_from_user),内核空间再利用系统调用把数据传输到 B 进程(即 copy_to_user)。这也正是目前 Linux 中传统 IPC 通信的实现原理,可以看到这其中会有两次数据拷贝。 (图片来自于 《写给 Android 应用工程师的 Binder 原理剖析》 ) Linux 中的一些 IPC 方式: 通过上面的讲解我们可以知道,IPC 是需要内核空间来支持的。Linux 中的管道、socket 等都是在内核中的。但是在 Linux 系统里面是没有 Binder 的。那么 Android 中是如何利用 Binder 来实现 IPC 的呢? 这就要讲到 Linux 中的 动态内核可加载模块 。动态内核可加载模块是具有独立功能的程序,它可以被单独编译,但是不能独立运行。它在运行时被链接到内核作为内核的一部分运行。这样,Android 系统就可以通过动态添加一个内核模块运行在内核空间,用户进程之间通过这个内核模块作为桥梁来实现通信。(这段话来自 《写给 Android 应用工程师的 Binder 原理剖析》 )在 Android 中,这个内核模块也就是 Binder 驱动。 另外,Binder IPC 原理相比较上面传统的 Linux IPC 而言,只需要一次数据拷贝就可以完成了。那么究竟是怎么做到的呢? 其实 Binder 是借助于 mmap (内存映射)来实现的。mmap 用于文件或者其它对象映射进内存,通常是用在有物理介质的文件系统上的。mmap 简单的来说就是可以把用户空间的内存区域和内核空间的内存区域之间建立映射关系,这样就减少了数据拷贝的次数,任何一方的对内存区域的改动都将被反应给另一方。 所以,Binder 的做法就是建立一个虚拟设备(设备驱动是/dev/binder),然后在内核空间创建一块数据接收的缓存区,这个缓存区会和内存缓存区以及接收数据进程的用户空间建立映射,这样发送数据进程把数据发送到内存缓存区,该数据就会被间接映射到接收进程的用户空间中,减少了一次数据拷贝。具体可以看下图理解 (图片来自于 《写给 Android 应用工程师的 Binder 原理剖析》 ) Binder 的优点 在整个 Binder 通信过程中,可以分为四个部分: 其中 Client 和 Server 是应用层实现的,而 Binder 驱动和 ServiceManager 是 Android 系统底层实现的。 具体流程如下: (Binder通信过程示意图来自于 《写给 Android 应用工程师的 Binder 原理剖析》 )2023-06-17 14:53:211
Binder机制的原理
u2003 因为Binder机制是涉及到进程的通信,所以需要对操作系统的进程通信需要有所了解。 u2003 进程的相关知识: Linux进程的学习的笔记 u2003Binder机制相比于其他的进程通信方法更加高效,是因为使用了内存映射的机制,数据只需要复制一次。 u2003内存映射的具体内容: 操作系统——内存映射 u2003在介绍Binder跨进程通信之前,需要去了解一个动态内核可加载模块。 u2003根据进程空间划分,进程之间的通信需要依赖到内核空间,例如在传统的IPC机制中,管道,Socket都时内核的一部分,因此通过内核支持来实现进程间通信时没有问题的,但是Binder并不是内核的一部分,那么怎么办呢 ?这就得益于Linux的动态内核可载模块的机制。模块时具有独立功能的程序,它可以被单独编译,但是不能独立运行,它在运行时被链接到内核作为内核的一部分运行。这样,Android系统就可以通过动态添加一个模块运行在内核空间,用户进程之间通过这个内核模块做为桥梁来实现通信。在Android系统中,这个运行在内核空间,负责各个用户进程通过Binder实现通信的内核模块就叫Binder驱动。 u2003有了上面的所说的运行在内核空间的模块,在Android系统中是通过 内存映射 的方式来实现通信,数据的拷贝只需要一次,相比于传统的IPC机制需要两次的数据拷贝,是更加高效的。 Binder IPC是基于内存映射来实现的,但是mmap()通常是用在有物理介质的文件系统上的。比如进程中的用户区域是不能直接核物理设备打交道的,如果想要把磁盘上的数据读取到进程的用户区域,需要两次拷贝(磁盘 >> 内核空间 >> 用户空间)。通常在这种场景下mmap()就能发挥作用,通过在物理介质核用户空间之间建立映射,减少数据的拷贝次数,用内存读写代替I/O读写,提高文件读取效率。而Binder并不存在物理介质,因此Binder驱动使mmap()并不是为了在物理介质和用户空间之间建立映射,而是用来在内核空间创建数据接收的缓存空间。 u2003Binder IPC通信过程: 示意图: u2003Binder是一套基于C/S架构的。由一系列的组件组成,主要包括:Client,Server,Service Manager和Binder驱动。其中Client,Service和Service Manager是在用户空间的,Binder驱动是在内核空间的。Client和Service是由用户是用户实现的,Binder驱动和Service Manager是系统实现的。Client,Server和Service Manager都可以通过系统调用open,mmap和ioctl来访问设备文件/dev/binder。从而实现与Binder驱动的交互间接实现进程间的通信。 u2003其中 Android Bander设计与实现 - 设计篇 对上述的角色中有详细的讲解。 步骤1:使用 BINDERSETCONTEXT_MGR 命令通过Binder驱动将自己注册成为ServiceMannager。 步骤2:注册服务 步骤2:获取服务 关于Binder的原理学习,可参考 Android Binder 原理解析 和 Android跨进程通信:图文详解 Binder机制 原理 ,个人认为这两篇描述的比较详细。2023-06-17 14:53:291
Binder机制通信原理
Binder机制可以说是Android系统中最难理解的一个部分了,这次结合Linux的内存管理来彻底理解它的通信原理。 在看介绍Binder的一些文章中,经常会提到用户空间地址和内核空间地址,这里需要先了解下它的概念。内存,是一块N字节大小的单元组成的数组,每个单元都有唯一的一个物理地址。在早些的系统中,由于当时的程序体积较小,内存一般够用,所以我们可以直接通过物理地址进行访问。但随着程序体积的增大,内存不够用了,所以在程序运行时,我们只需要将当下需要的数据加载进内存,其它数据可以放在磁盘上。因此,我们为每个进程分配虚拟地址,虚拟地址通过mmu映射成真实的物理地址。 未使用MMU时,CPU执行单元发出的是物理地址,使用MMU时,发出的是虚拟地址,通过映射转换成物理地址。 在32位的操作系统,每个进程一开始被分配到2^32,4G大小的虚拟地址。其中0-3G是用户空间,3-4g是内核空间。用户空间没有权限直接访问内核空间,但内核空间有权限直接访问用户空间。且内核空间是所有进程共享的。 Binder机制的核心就是利用内核空间和用户空间的共享数据的原理来实现进程间通信。Linux系统中的mmap,借助的是硬盘文件与内存地址之间形成一个映射关系,操作这块内存并可以直接操作该文件。但是android中,并不存在这么一个文件。Android借助是/dev/binder驱动,在内核空间中开辟了一块接收缓存区,并将之与用户空间地址进行了映射。所以通过这个映射关系,接收方在用户空间中就可以访问到接收缓存区中的数据,不需要再次进行拷贝。同时,接收缓存区与内核缓存区同样建立了映射关系,当内核空间copy data from 用户空间时,将数据拷贝到内核缓存区。至此 接收方便可以访问到这些数据了。整个过程,只用了一次拷贝。 参考: https://blog.csdn.net/weixin_34174132/article/details/88839603?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link https://blog.csdn.net/appdsn/article/details/793114552023-06-17 14:53:461
如何在Android下使用Binder
实现一个binder通信实例,需要经过以下步骤:(1)获得ServiceManager的对象引用(2)向ServiceManager注册新的Service(3)在Client中通过ServiceManager获得Service对象引用(3)在Client中发送请求,由Service返回结果。下面看具体的代码如何实现。3.1 libmyservice代码实现(1)新建目录frameworks/base/myservice/libservice,进入该目录view plain$ cd frameworks/base$ mkdir myservice$ cd myservice$ mkdir libmyservice$ cd libmyservice(2)编写libmyservice/myservic.h文件view plain#include <utils/threads.h>#include <utils/RefBase.h>#include <binder/IInterface.h>#include <binder/BpBinder.h>#include <binder/Parcel.h>namespace android {class MyService : public BBinder{mutable Mutex mLock;int32_t mNextConnId;public:static int instantiate();MyService();virtual ~MyService();virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);};}; //namespace(2)编写libservice/myservice.cpp文件view plain#include "myservice.h"#include <binder/IServiceManager.h>#include <binder/IPCThreadState.h>namespace android {static struct sigaction oldact;static pthread_key_t sigbuskey;int MyService::instantiate(){LOGE("MyService instantiate");// defaultServiceManager ()获得ServiceManager的对象引用,addService()可向ServiceManager注册新的服务int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService());LOGE("MyService r = %d/n", r);return r;}MyService::MyService(){LOGV("MyService created");mNextConnId = 1;pthread_key_create(&sigbuskey, NULL);}MyService::~MyService(){pthread_key_delete(sigbuskey);LOGV("MyService destroyed");}// 每个系统服务都继承自BBinder类,都应重写BBinder的onTransact虚函数。当用户发送请求到达Service时,系统框架会调用Service的onTransact函数,该函数分析接收到的数据包,调用相应的接口函数处理请求status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){switch(code){case 0: {pid_t pid = data.readInt32();int num = data.readInt32();num = num + 100;reply->writeInt32(num);return NO_ERROR;}break;default:return BBinder::onTransact(code, data, reply, flags);}}}; //namespace(3)编写libservice/Android.mk文件view plain# File: Android.mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := myservice.cppLOCAL_C_INCLUDES := $(JNI_H_INCLUDE)LOCAL_SHARED_LIBRARIES := libutils libbinderLOCAL_MODULE_TAGS := optionalLOCAL_PRELINK_MODULE := falseLOCAL_MODULE := libmyserviceinclude $(BUILD_SHARED_LIBRARY)(4)编译libmyservice.so动态库在android源码主目录下view plain$ source build/envsetup.shincluding device/htc/passion/vendorsetup.shincluding device/samsung/crespo4g/vendorsetup.shincluding device/samsung/crespo/vendorsetup.sh$ mmm frameworks/base/myservice/libmyservice/编译成功后生成文件:out/target/product/generic/system/lib/libmyservice.so2023-06-17 14:53:551
面试必备:Binder进程通信原理
先简单概括性地说说Linux现有的所有进程间IPC方式: 管道(Pipe): 在创建时分配一个page大小的内存,缓存区大小比较有限; 消息队列(Message): 信息复制两次,额外的CPU消耗;不适合频繁或信息量大的通信; 共享内存(Share Memory): 无须复制,共享缓冲区直接附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决。 套接字(Socket): 作为更通用的接口,传输效率低,主要用于不同机器或跨网络的通信。 信号量(Semaphore): 常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此主要作为进程间以及同一进程内不同线程之间的同步手段。 信号(Signal): 不适用于信息交换,更适用于进程中断控制,比如非法内存访问、杀死某个进程等。 从4个角度来展开对Binder的分析 (1)从性能的角度 数据拷贝次数: Binder数据拷贝只需要一次,而管道、消息队列、套接字都需要2次,但共享内存方式一次内存拷贝都不需要;从性能角度看,Binder性能仅次于共享内存。 (2)从稳定性的角度 u2002u2002u2002u2002Binder是基于C/S架构的,架构清晰明朗,Server端和Client端相对独立,稳定性较好;而共享内存实现方式复杂,没有Client端与Server端之别,需要充分考虑到访问临界资源的并发同步问题,否则可能会出现死锁等问题;从稳定性角度看,Binder架构优越于共享内存。 (3)从安全的角度 u2002u2002u2002u2002传统Linux IPC的接收方无法获得对方进程可靠的UID/PID,从而无法鉴别对方身份;而Android作为一个开放的开源体系,手机安全显得额外重要,传统Linux IPC五任何保护措施,完全由上层协议来确保。 u2002u2002u2002u2002Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。前面提到C/S架构, Android系统中对外只暴露Client端,Client端将任务发送给Server端,Server端会根据权限控制策略,判断UID/PID是否满足访问权限,目前权限控制很多时候是通过弹出权限询问对话框,让用户选择是否运行。 u2002u2002u2002u2002传统IPC只能由用户在数据包里填入UID/PID;另外,可靠的身份标记只有由IPC机制本身在内核中添加。其次传统IPC访问接入点是开发的,无法建立私有通道。从安全角度,Binder的安全性更高。 (4)从语言层面的角度 u2002u2002u2002u2002大家都知道Linux是基于C语言(面向过程的语言),而Android是基于Java语言(面向对象的语句)。Binder恰恰符合面向对象思想,将进程间通信转化为对某个Binder对象的引用,调用该对象的方法。而其独特之处在于Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程,而它的引用却遍布于系统的各个进程之中。Binder模糊了进程边界,淡化了进程间通信过程,让整个系统仿佛运行于同一个面向对象的程序之中。 u2002u2002u2002u2002Binder框架定义了四个角色:Server,Client,ServiceManager(以后简称SM)以及Binder驱动。其中Server,Client,SM运行于用户空间,驱动运行于内核空间。 ServiceManager与实名Binder Client获得实名Binder的引用 u2002u2002u2002u2002Server向SM注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用了。 匿名Binder u2002u2002u2002u2002并不是所有Binder都需要注册给SM广而告之的。Server端可以通过已经建立的Binder连接将创建的Binder实体传给Client,当然这条已经建立的Binder连接必须是通过实名Binder实现。由于这个Binder没有向SM注册名字,所以是个匿名Binder。Client将会收到这个匿名Binder的引用,通过这个引用向位于Server中的实体发送请求。匿名Binder为通信双方建立一条私密通道,只要Server没有把匿名Binder发给别的进程,别的进程就无法通过穷举或猜测等任何方式获得该Binder的引用,向该Binder发送请求。 u2002u2002u2002u2002 传统IPC方式中,数据是怎样从发送端到达接收端的呢? 通常的做法是: 发送方 将准备好的数据存放在缓存区中,通过系统API调用进入 内核 中。 内核服务程序 在内核空间分配内存,将数据从 发送方 缓存区复制到内核缓存区中。 接收方 读数据是也要提供一块缓存区, 内核 将数据从内核缓存区拷贝到 接收方 提供的缓存区中并唤醒接收线程,完成一次数据发送。这种存储-转发机制有两个缺陷:首先是效率低下,需要做两次拷贝(用户空间->内核空间->用户空间)。Linux使用copy_from_user()和copy_to_user()实现这两个跨空间拷贝。其次是接收数据的缓存要由接收方提供,可接收方不知道到底要多大的缓存才够用。只能开辟尽量打的空间或先调用API接收消息头获得消息体大小,再开辟适当的空间接收消息体。两种做法都有不足,不是浪费空间就是浪费时间。 u2002u2002u2002u2002 Binder采用一种全新策略:由Binder驱动负责管理数据接收缓存。 Binder驱动通过实现mmap()来创建数据接收的缓存空间。 u2002u2002u2002u2002这样Binder的接收方就有了一片大小为MAP_SIZE的接收缓存区。mmap()的返回值是内存映射在用户空间的地址,不过这段空间是由驱动管理,用户不必直接访问(映射类型为PROT_READ,只读映射)。 参考文献 Android Binder机制原理(史上最强理解,没有之一)2023-06-17 14:54:221
Binder(七)系统服务注册流程总结
本文基于Android_9.0、kernel_3.18源码 通过Binder(三)到Binder(六)的相关文章,我们详细介绍了Binder服务启动、服务注册的流程;其中服务注册相当于servicemanager提供的一个方法,AMS在system_server进程中,AMS完成注册即通过binder完成了一次跨进程通信,我们再梳理一下整体流程。 1、service_manager进程创建之后,会进行binder的初始化: (1)通过binder_open打开 dev/binder ,创建 binder_proc 来记录进程信息,并通过mmap进行 内存映射 ; (2)通过binder_become_context_manager注册为binder的管理者,即将自己赋值给全局变量全局变量 binder_context_mgr_node ; (3)通过binder_loop循环,等待消息,由于刚刚创建,没有进行中待处理任务,阻塞进程, 等待唤醒 。 2、system_server进程创建后,也会进行binder初始化: (1)通过ProcessState打开 dev/binder ,创建 binder_proc 来记录进程信息,并通过mmap进行 内存映射 ; (2)通过 开启新的线程 ,并调用IPCThreadState的joinThreadPool开启循环,等待接收消息,由于没有待处理的任务,该线程阻塞,等待唤醒。 1、BpBinder的获取 binder通信,需要知道通信的目标是谁,在binder中定义binder_context_mgr_node的handle = 0,因此就 通过handle = 0找到servicemanager ,在BpBinder创建时持有了handle。 2、以AMS注册为例,数据发送 (1)通过 Parcel将AMS数据包装 ,在此设置type为BINDER_TYPE_BINDER,并将AMS数据写入对应结构,再通过 BpBinder 的transact调用 IPCThreadState 的transact进行通信; (2)在IPCThreadState的waitForResponse中,会调用binder驱动进行如下操作: 在第5步创建事务时,事物的数据地址直接通过地址偏移量计算出来,省去一次拷贝。 (3)如上操作会唤醒servicemanager进程,servicemanager进程会对任务进行处理,同时发送回执 (4)第(3)步操作会唤醒system_server线程,system_server处理回执消息,退出waitForResponse,数据交互流程完毕。 在binder驱动中,用来描述进程的上下文信息;每当进程打开文件节点/dev/binder时,binder驱动都会为这个进程创建一个binder_proc。 描述线程相关的数据。 在binder驱动中,会为每一个服务创建一个binder_node,通过它可以找到真正提供服务的对象。 binder驱动中,需要通过binder_ref找到binder_node(服务对应的实体),每个与binder_node对应的客户端都会创建一个binder_ref;2023-06-17 14:54:291
如何在Android下使用Binder
1概述Binder是基于OpenBinder,在Android系统上使用的进程间通信机制。Binder基于Client-Server通信模式,本质上可以理解为它实现了Client对Server对象的远程调用。比如,有某个binder对象A位于Server中,该对象提供了一套函数用以实现对服务的请求,而在一个或多个Client中包含对象A的引用,Client通过该引用可以调用远端Server中对象A的接口函数,这种远端调用对Client而言,与调用本地对象并无区别。2 通信模型Binder机制定义了四个组件,分别是Client,Server,ServiceManager和binder驱动,其中Client,Server,ServiceManager运行于用户空间,binder驱动运行于内核空间。binder驱动binder驱动是内核中的一个字符设备驱动/dev/binder,它是整个Binder通信机制的核心。Client,Server,ServiceManager通过open()和ioctl()文件操作函数与binder驱动进行通信,从而实现了Client向Server发送请求,Server处理请求并返回结果到Client。具体来说,它负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。ServiceManagerServiceManager是一个守护进程,负责管理服务,即所有的Server需要向ServiceManager注册服务。同时,ServiceManager向Client提供查询和获取Server的接口。3 binder通信实例实现一个binder通信实例,需要经过以下步骤:(1)获得ServiceManager的对象引用(2)向ServiceManager注册新的Service(3)在Client中通过ServiceManager获得Service对象引用(3)在Client中发送请求,由Service返回结果。下面看具体的代码如何实现。3.1 libmyservice代码实现(1)新建目录frameworks/base/myservice/libservice,进入该目录view plain$ cd frameworks/base $ mkdir myservice $ cd myservice $ mkdir libmyservice $ cd libmyservice (2)编写libmyservice/myservic.h文件view plain#include <utils/threads.h> #include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/BpBinder.h> #include <binder/Parcel.h> namespace android { class MyService : public BBinder { mutable Mutex mLock; int32_t mNextConnId; public: static int instantiate(); MyService(); virtual ~MyService(); virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); }; }; //namespace (2)编写libservice/myservice.cpp文件view plain#include "myservice.h" #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> namespace android { static struct sigaction oldact; static pthread_key_t sigbuskey; int MyService::instantiate() { LOGE("MyService instantiate"); // defaultServiceManager ()获得ServiceManager的对象引用,addService()可向ServiceManager注册新的服务 int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService()); LOGE("MyService r = %d/n", r); return r; } MyService::MyService() { LOGV("MyService created"); mNextConnId = 1; pthread_key_create(&sigbuskey, NULL); } MyService::~MyService() { pthread_key_delete(sigbuskey); LOGV("MyService destroyed"); } // 每个系统服务都继承自BBinder类,都应重写BBinder的onTransact虚函数。当用户发送请求到达Service时,系统框架会调用Service的onTransact函数,该函数分析接收到的数据包,调用相应的接口函数处理请求 status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case 0: { pid_t pid = data.readInt32(); int num = data.readInt32(); num = num + 100; reply->writeInt32(num); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } }; //namespace (3)编写libservice/Android.mk文件view plain# File: Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := myservice.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := libutils libbinder LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libmyservice include $(BUILD_SHARED_LIBRARY) (4)编译libmyservice.so动态库在android源码主目录下view plain$ source build/envsetup.sh including device/htc/passion/vendorsetup.sh including device/samsung/crespo4g/vendorsetup.sh including device/samsung/crespo/vendorsetup.sh $ mmm frameworks/base/myservice/libmyservice/ 编译成功后生成文件:out/target/product/generic/system/lib/libmyservice.so3.2 myserver代码实现(1)新建目录myservice/myserver,并进入该目录(2)编写myserver/myserver.cpp文件view plain#include <sys/types.h> #include <unistd.h> #include <grp.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include <utils/Log.h> #include <private/android_filesystem_config.h> #include "../libmyservice/myservice.h" using namespace android; int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager();//获得ServiceManager接口 LOGI("ServiceManager: %p", sm.get()); MyService::instantiate(); //执行addService()函数,注册服务 ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); //进入循环,等待客户端的请求 return 0; } (3)编写myserver/Android.mk文件view plain# File: Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= myserver.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := libutils libbinder libmyservice LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := myserver include $(BUILD_EXECUTABLE) (4)编译myserver可执行程序在android源码主目录下执行:view plain$mmm frameworks/base/myservice/myserver/ 编译成功后生成文件:out/target/product/generic/symbols/system/bin/myserver3.3 MyClient客户端代码实现(1)新建目录myservice/myclient,进入该目录(2)编写myclient/myclient.h文件view plainnamespace android { class MyClient { public: void add100(int n); private: static const void getMyService(); //通过ServiceManager获取服务接口 }; }; //namespace (3)编写myclient/myclient.cpp文件view plain#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include "myclient.h" namespace android { sp<IBinder> binder; void MyClient::add100(int n) { getMyService(); Parcel data, reply; int answer; data.writeInt32(getpid()); data.writeInt32(n); LOGE("BpMyService::create remote()->transact()/n"); binder->transact(0, data, &reply); answer = reply.readInt32(); printf("answner=%d/n", answer); return; } const void MyClient::getMyService() { sp<IServiceManager> sm = defaultServiceManager(); binder = sm->getService(String16("android.myservice")); LOGE("MyClient::getMyService %p/n",sm.get()); if (binder == 0) { LOGW("MyService not published, waiting..."); return; } } }; //namespace using namespace android; int main(int argc, char** argv) { MyClient* p = new MyClient(); p->add100(1); return 0; } (4)编写myclient/Android.mk文件view plainLOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= myclient.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := libutils libbinder libmyservice LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := myclient include $(BUILD_EXECUTABLE) (5)编译myclient可执行程序在android源码主目录下,执行:view plain$ mmm frameworks/base/myservice/myclient/ 编译成功后生成可执行文件:out/target/product/generic/symbols/system/bin/myclient3.4在模拟器上运行(1)启动模拟器view plain$ cd ~/software/android/android-sdk-linux/tools $ ./emulator -avd gbread -partition-size 512 (2)拷贝libmyservice.so到模拟器的/system/lib目录view plain$cd out/target/product/generic/obj/lib $adb remount $ adb push libmyservice.so /system/lib 159 KB/s (10084 bytes in 0.061s) (3)拷贝myserver到模拟器的/system/bin目录view plain$cd out/target/product/generic/symbols/system/bin $ adb push myserver /system/bin 668 KB/s (27508 bytes in 0.040s) (4)拷贝myclient到/system/bin目录view plain$ adb push myclient /system/bin 1549 KB/s (46840 bytes in 0.029s) (5)在模拟器上启动服务,并执行客户端程序。view plain# adb shell # cd system/bin # ls my* myclient myserver # ./myserver # ./myclient answner=101/n# 由客户端程序的执行结果可知,由服务端返回的执行结果是正确的。2023-06-17 14:54:361
Linux的IPC机制(三):Binder
正如上一章所说, 跨进程通信是需要内核空间做支持的. 传统的 IPC 机制如 管道, Socket, 都是内核的一部分, 因此通过内核支持来实现进程间通信自然是没问题的. 但是 Binder 并不是 Linux 系统内核的一部分, 那怎么办呢, 这得益于 Linux 的动态内核可加载模块 (Loadable Kernel Module, LKM)的机制 这样 Android 系统就可以通过动态添加一个内核模块运行在内核空间, 用户进程进程之间通过这个内核模块作为桥梁来实现通信. 那么在 Android 系统中用户进程之间是如何通过这个内核模块 (Binder Driver)来实现通信的呢? 显然不是和上一章的传统 IPC 通信一样,进行两次 copy 了, 不然Binder 也不有在性能方面的优势了. Binder IPC 机制中设计到的内存映射通过 mmap() 来实现, mmap() 是操作系统中一种内存映射的方法. 内存映射能减少数据 copy 的次数, 实现用户空间和内核空间的高效互动. 两个空间各自的修改也能直接反应在映射的内存区域, 从而被对方空间及时感知. 也正因为如此, 内存映射能够提供对进程间通信的支持. Binder IPC 正是基于内存映射( mmap() ) 来实现的, 但是 mmap() 通常是用在有物理介质的文件系统上的. 比如进程中的用户区域是不能直接和物理设备打交道的, 如果想要把磁盘上的数据读取到进程的用户区域, 需要两次 copy (磁盘 -> 内核空间 -> 用户空间). 通常在这种场景下 mmap() 就能发挥作用, 通过在物理介质和用户空间之间建立映射, 减少数据的 copy 次数, 用内存读写代替 I/O 读写, 提高文件读取效率. 而 Binder 并不存在物理介质, 因此 Binder 驱动使用 mmap() 并不是为了在物理介质和用户空间之间映射, 而是用来在内核空间创建数据接收的缓存空间. 一次完整的 Binder IPC 通信过程通常是这样: 这样就完成了一次进程间通信 如下图: 介绍完 Binder IPC 的底层通信原理, 接下来我们看看实现层面是如何设计的 一次完成的进程间通信必然至少包含两个进程, 通常我们称通信的双方分别为客户端进程(Client) 和服务端进程(Server), 由于进程隔离机制的存在, 通信双方必然需要借助 Binder 来实现. BInder 是基于 C/S 架构. 是由一些列组件组成. 包括 Client, Server, ServiceManager, Binder 驱动. Binder 驱动就如如同路由器一样, 是整个通信的核心. 驱动负责进程之间 Binder 通信的建立 / 传递, Binder 引用计数管理, 数据包在进程之间的传递和交互等一系列底层支持. ServiceManager 作用是将字符形式的 Binder 名字转化成 Client 中对该 Binder 的引用, 使得 Client 能够通过 Binder 的名字获得对 Binder 实体的引用. 注册了名字的 Binder 叫实名 Binder, 就像网站一样除了 IP 地址以外还有自己的网址. Server 创建了 Binder, 并为它起一个字符形式, 可读易记的名字, 将这个 BInder 实体连同名字一起以数据包的形式通过 Binder 驱动 发送给 ServiceManager, 通知 ServiceManager 注册一个名字为 "张三"的 Binder, 它位于某个 Server 中, 驱动为这个穿越进程边界的 BInder 创建位于内核中的实体节点以及 ServiceManager 对实体的引用, 将名字以及新建的引用打包传给 ServiceManager, ServiceManager 收到数据后从中取出名字和引用填入查找表. ServiceManager 是一个进程, Server 又是一个另外的进程, Server 向 ServiceManager 中注册 BInder 必然涉及到进程间通信. 当实现进程间通信又要用到进程间通信, 这就好像蛋可以孵出鸡的前提确实要先找只鸡下蛋! Binder 的实现比较巧妙, 就是预先创造一只鸡来下蛋. ServiceManager 和其他进程同样采用 Binder 通信, ServiceManager 是 Server 端, 有自己的 Binder 实体, 其他进程都是 Client, 需要通过这个 Binder 的引用来实现 Binder 的注册, 查询和获取. ServiceManager 提供的 Binder 比较特殊, 它没有名字也不需要注册. 当一个进程使用 BINDERSETCONTEXT_MGR 命令将自己注册成 ServiceManager 时 Binder 驱动会自动为它创建 Binder 实体(这就是那只预先造好的那只鸡). 其实这个 Binder 实体的引用在所有 Client 中都固定为 0 , 而无需通过其他手段获得. 也就是说, 一个 Server 想要向 ServiceManager 注册自己的 Binder 就必须通过这个 0 号引用和 ServiceManager 的 Binder 通信. 这里说的 Client 是相对于 ServiceManager 而言的, 一个进程或者应用程序可能是提供服务的 Server, 但是对于 ServiceManager 来说它仍然是个 Client. Server 向 ServiceManager 中注册了 Binder 以后, Client 就能通过名字获得 Binder 的引用. Client 也利用保留的 0 号引用向 ServiceManager 请求访问某个 Binder. 比如,Client 申请访问名字叫"张三"的 Binder 引用. ServiceManager 收到这个请求后从请求数据包中取出 Binder 名称, 在查找表里找到对应的条目, 取出对应的 Binder 引用, 作为回复发送给发起请求的 Client. 从面相对象的角度看, Server 中的 Binder 实体现在有两个引用: 一个位于 ServiceManager 中, 一个位于发起请求的 Client 中. 如果后面会有更多的 Client 请求该 Binder, 系统中就会有更多的引用指向这个 Binder, 就像 Java 中一个对象有多个引用一样. 我们已经解释清楚 Client, Server 借助 Binder 驱动完成跨进程通信的实现机制了, 但是还有个问题需要弄清楚, 比如 A 进程想要 B 进程中的某个对象(object) 是如何实现的呢, 毕竟它们属于不同的进程, A 进程没办法直接使用 B 进程中的 object. 前面我们说过跨进程通信的过程都有 Binder 驱动的参与, 因此在数据流经 Binder 驱动的时候 Binder 驱动会对数据做一层转换. 我们在 Client端,向 ServiceManager 获取具体的 Server 端的 Binder 引用的时候,会首先进过 Binder 驱动,Binder 驱动它并不会把真正的 Server 的 Binder 引用返回给 Client 端,而是返回一个代理的 java 对象,该对象具有跟 Server 端的 Binder 引用相同的方法签名,这个对象为 ProxyObject,他具有跟 Server 的 Binder 实例一样的方法,只是这些方法并没有 Server 端的能力,这些方法只需要把请求参数交给 Binder 驱动即可. 对于 Client 端来说和直接调用 Server 中的方法是一样的. 了解了上面之后, 我们大致可以推算出 Binder 的通信过程 1. 注册 ServiceManager 2. 注册 Server 3. Client 获取 Server 的 Binder 引用 4. Client 与 Server 通信2023-06-17 14:54:441
Binder 之 oneway 机制
Binder 是 Android 中的 IPC(进程间通信)的最要一环,它的作用就是: 像一些系统服务调用应用进程的时候就会使用 oneway,比如 AMS 调用应用进程启动 Activity,这样就算应用进程中做了耗时的任务,也不会阻塞系统服务的运行。 本篇不展开它是如何通信的,只聊聊它的机制,分两种: 首先是非 oneway 的情况: 这里的挂起相当于 Thread 的 sleep,是真正的"休眠",底层调用的是 waitEventInterruptible(), Linux 系统函数。 oneway 的情况,客户端就不需要挂起线程等待: 写在最后,涉及到的 binder 命令也有规律:2023-06-17 14:54:511
Android通信方式篇(七)-Binder机制(Native层(下))
本篇文章针对向ServiceManager注册服务 和 获取服务两个流程来做总结。在这两个过程中,ServiceManager都扮演的是服务端,与客户端之间的通信也是通过Binder IPC。 在此之前先了解下Binder的进程与线程的关系: 用户空间 :ProcessState描述一个进程,IPCThreadState对应一个进程中的一个线程。 内核空间 :binder_proc描述一个进程,统一由binder_procs全局链表保存,binder_thread对应进程的一个线程。 ProcessState与binder_proc是一一对应的。 Binder线程池 :每个Server进程在启动时会创建一个binder线程池,并向其中注册一个Binder线程;之后Server进程也可以向binder线程池注册新的线程,或者Binder驱动在探测到没有空闲binder线程时会主动向Server进程注册新的的binder线程。对于一个Server进程有一个最大Binder线程数限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。对于所有Client端进程的binder请求都是交由Server端进程的binder线程来处理的。我的理解是:binder线程是进程进行binder ipc时的一条数据处理路径。 MediaPlayerService向ServiceManager注册过程如下: 相关类: 整个过程总结如下: 1 获取BpServiceManager 与 BpBinder 由defaultServiceManager()返回的是BpServiceManager,同时会创建ProcessState对象和BpBinder对象。然后通过BpBinder执行transact,把真正工作交给IPCThreadState来处理。 2 BpBinder transact Binder代理类调用transact()方法,真正工作还是交给IPCThreadState来进行transact工作。 3 通过IPCThreadState 包装并转换数据并进行transact事务处理 每个线程都有一个IPCThreadState,每个IPCThreadState中都有一对Parcel变量:mIn、mOut。相当于两根数据管道: 最后执行talkWithDriver。 writeTransactionData:将BC Protocol + binder_transaction_data结构体 写入mOut, 然后执行waitForResponse: 由talkWithDriver将数据进一步封装到binder_write_read结构体,通过ioctl(BINDER_WRITE_READ)与驱动通信。同时等待驱动返回的接收BR命令,从mIn取出返回的数据。 mIn包装的数据结构(注册服务handle = 0 ,code 为ADD_SERVICE_TRANSACTION): 4 Binder Driver 把binder_write_read结构体write_buffer里数据取出来,分别得到BC命令和封装好数据的事务binder_transaction_data, 然后根据handler,在当前binder_proc中,找到相应的binder_ref,由binder_ref再找到目标binder_node实体,由目标binder_node再找到目标进程binder_proc。然后就是插入数据:当binder驱动可以找到合适的线程,就会把binder_transaction节点插入到servciemanager的线程的todo队列中,如果找不到合适的线程,就把节点之间插入servciemanager的binder_proc的todo队列。 5 ServiceManager 经过Binder Driver的处理,数据已经到了ServiceManager进程,在BR_TRANSACTION的引导下,在binder_loop()中执行binder_parser()取出数据,执行do_add_service()操作,最终向 svcinfo 列表中添加已经注册的服务(没有数据的返回)。最后发送 BR_REPLY 命令唤醒等待的线程,通知注册成功。结束MediaPlayerService进程 waitForResponse()的状态,整个注册过程结束。 获取服务的过程与注册类似,首先 ServiceManager 向 Binder 驱动发送 BC_TRANSACTION 命令携带 CHECK_SERVICE_TRANSACTION 命令,同时获取服务的线程进入等待状态 waitForResponse()。Binder 驱动收到请求命令向 ServiceManager 的发送 BC_TRANSACTION 查询已注册的服务,会区分请求服务所属进程情况。 查询到直接响应 BR_REPLY 唤醒等待的线程。若查询不到将与 binder_procs 链表中的服务进行一次通讯再响应。 以startService为例来简单总结下执行流程: 3.1 从方法执行流程来看: Client : 1 AMP.startService 标记方法以及通过Parcel包装数据; 2 BinderProxy.transact 实际调用native的 android_os_BinderProxy_transact 传递数据; 3 获取BpServiceManager 与 BpBinder 同时会创建ProcessState。然后通过BpBinder执行transact,把真正工作交给IPCThreadState来处理; 4 IPC.transact 主要执行writeTransactionData,将上层传来的数据重新包装成binder_transaction_data,并将BC Protocol + binder_transaction_data结构体 写入mOut; 5 IPC waitForResponse talkWithDriver + 等待返回数据; 6 talkWithDriver 将数据进一步封装成binder_write_read,通过ioctl(BINDER_WRITE_READ)与驱动通信; Kernel : 7 binder ioctl 接收BINDER_WRITE_READ ioctl命令; 8 binder_ioctl_write_read 把用户空间数据ubuf拷贝到内核空间bwr; 9 binder_thread_write 当bwr写缓存有数据,则执行binder_thread_write;当写失败则将bwr数据写回用户空间并退出; 10 binder_transaction 找到目标进程binder_proc并插入数据到目标进程的线程todo队列,最终执行到它 时,将发起端数据拷贝到接收端进程的buffer结构体; 11 binder_thread_read 根据binder_transaction结构体和binder_buffer结构体数据生成新的binder_transaction_data结构体,写入bwr的read_buffer,当bwr读缓存有数据,则执行binder_thread_read;当读失败则再将bwr数据写回用户空间并退出;最后,把内核数据bwr拷贝到用户空间ubuf。 12 binder_thread_write + binder_ioctl BR命令和数据传递 Server: 13 IPC.executeCommand 解析kernel传过来的binder_transaction_data数据,找到目标BBinder并调用其transact()方法; 14 IPC.joinThreadPool 采用循环不断地执行getAndExecuteCommand()方法, 处理事务。当bwr的读写buffer都没有数据时,则阻塞在binder_thread_read的wait_event过程. 另外,正常情况下binder线程一旦创建则不会退出. 15 BBinder.transact 到Binder.exeTransact 调用 AMN.onTransact 16 AMN.onTransact 把数据传递到AMS.starService去执行 17 AMS.starService Server处理了Client的请求了 然后原路replay回去,talkWithDriver 到Kernel ,然后找到Client进程,把数据拷贝到read_buffer里,最终唤醒IPC,把反馈传递回AMP.startService。完成启动服务。 3.2 从通信协议流程来看: 非oneWay: oneway: oneway与非oneway区别: 都是需要等待Binder Driver的回应消息BR_TRANSACTION_COMPLETE. 主要区别在于oneway的通信收到BR_TRANSACTION_COMPLETE则返回,而不会再等待BR_REPLY消息的到来. 另外,oneway的binder IPC则接收端无法获取对方的pid. 3.3 从数据流来看 从用户空间开始: 进入驱动后: 回到用户空间: 参考: http://gityuan.com/2016/09/04/binder-start-service/ http://gityuan.com/2015/11/28/binder-summary/ http://gityuan.com/2015/11/14/binder-add-service/ http://gityuan.com/2015/11/15/binder-get-service/2023-06-17 14:54:581
深入浅出Binder进程间通信机制
Linux传统IPC机制主要有已下几种:管道、消息队列、共享内存Socket等。消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。共享内存虽然无需拷贝,但控制复杂,难以使用。socket作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。 同时从安全性角度考虑,Android作为一个开放式,拥有众多开发者的平台,应用程序的来源广泛,确保智能终端的安全是非常重要的。传统IPC没有任何安全措施,完全依赖上层协议来确保。首先传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份。Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加。其次传统IPC访问接入点是开放的,无法建立私有通道。比如命名管道的名称、system V的键值、socket的ip地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。 由于传统的IPC机制有这样那样不让人满意的原因。Android自己开发了一套进程间通信机制Binder通信。Binder机制起源于一个简单的想法:将申请服务的请求和对应的响应信息,写入一个所有进程均能够访问的地址空间中。当进程需要使用这些数据时,只需要访问对应的内存地址,以减小内容复制引入的开销。为此,Binder机制利用kernel空间作为共享区域,并由Binder driver来建立起每个进程的内存地址与kernel空间中存储地址的映射。从而使数据只要拷贝一次就可以。同时为发送方添加UID/PID身份,既支持实名Binder也支持匿名Binder,提高安全性。 Binder通信采用C/S架构,从组件视角来说,包含Client、Server、ServiceManager以及Binder驱动,其中ServiceManager用于管理系统中的各种服务。如上图所示Binder在Framework层和Native层分别有对应的客户端(Client)、服务(Server)的和服务管理器(Service Manager)。同时在Kernel层(内核空间)有Binder的驱动设备。 这四个角色的作用分别是: ① Client进程:使用服务的进程。 ② Server进程:提供服务的进程。 ③ ServiceManager进程:ServiceManager的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。 ④ Binder驱动:驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。 首先需要注册服务端,只有注册了服务端,客户端才有通讯的目标,服务端通过 ServiceManager 注册服务,注册的过程就是向 Binder 驱动的全局链表 binder_procs 中插入服务端的信息(binder_proc 结构体,每个 binder_proc 结构体中都有 todo 任务队列),然后向 ServiceManager 的 svcinfo 列表中缓存一下注册的服务。 注册完服务后客户端就能够查询并获取注册了的服务了。客户端向ServiceManager 发起获取服务的请求,传递要获取服务的名称。ServiceManager 从服务列表中查找到Client需要的对应服务信息,将该服务的代理Binder(BinderProxy)返回给客户端。其实查询服务相当于ServiceManager 作为服务端,客户端进行使用。所以这也是一次Binder使用服务的过程。 使用服务的过程如上图。 ① Binder驱动为跨进程通信做准备:通过调用mmap()系统函数实现内存映射。在Binder驱动中创建一块接收缓存区。同时将内核缓存区地址和Server端中用户空间一块地址同时都映射到该接收缓存区中。这时候就创建了虚拟区间和映射的关系。 ② Client进程将数据发送到Server进程。Client进程通过调用copy_from_user()发送数据拷贝到内核中(Binder驱动)的缓存区中,此时Client发起请求的线程会被挂起。由于在①中构建了映射关系,此时相当于也将数据发送到了Server端的用户空间中。之后Binder驱动通知Server端进程执行解包。 ③ Server进程根据Client进程发送来的数据,调用目标方法。收到Binder驱动通知后,Server进程对数据进行解包,并调用相关方法处理。 ④ Server进程将目标方法处理结果返回给Client进程。将处理结果放回自己的共享空间(即①中映射的Binder驱动缓存区中)。Binder驱动通知Client进程获取返回结果,此时②中被挂起的线程会被重新唤醒。Client进程通过系统调用copy_to_user(),从内核缓存区拷贝Server进程返回的结果。 从上面使用服务的过程可以看到,整个过程只拷贝了一次发送的数据和一次接收的数据。而正如开头所述,消息队列和管道这两种IPC拷贝次数为2次。 Binder模型的线程管理采用Binder驱动线程池,由Binder驱动进行管理,而不是由Server进程来管理。而一个进程的Binder线程默认线程数默认最大是16。也就是说Client的请求数一旦超过16个会被阻塞直到有空间的Binder线程。2023-06-17 14:55:051
Carson带你学Android:全面剖析Binder跨进程通信原理
从而全方位地介绍 Binder ,希望你们会喜欢。 在本文的讲解中,按照 大角度 -> 小角度 去分析 Binder ,即: 从而全方位地介绍 Binder ,希望你们会喜欢。 在讲解 Binder 前,我们先了解一些 Linux 的基础知识 具体请看文章: 操作系统:图文详解 内存映射 Binder 跨进程通信机制 模型 基于 Client - Server 模式 此处重点讲解 Binder 驱动作用中的跨进程通信的原理: 原因: 所以,原理图可表示为以下: 所以,在进行跨进程通信时,开发者只需自定义 Client & Server 进程 并 显式使用上述3个步骤,最终借助 Android 的基本架构功能就可完成进程间通信 注册服务后, Binder 驱动持有 Server 进程创建的 Binder 实体 此时, Client 进程与 Server 进程已经建立了连接 Client 进程 根据获取到的 Service 信息( Binder 代理对象),通过 Binder 驱动 建立与 该 Service 所在 Server 进程通信的链路,并开始使用服务 步骤1: Client 进程 将参数(整数a和b)发送到 Server 进程 步骤2: Server 进程根据 Client 进要求 调用 目标方法(即加法函数) 步骤3: Server 进程 将目标方法的结果(即加法后的结果)返回给 Client 进程 对比 Linux ( Android 基于 Linux )上的其他进程通信方式(管道、消息队列、共享内存、 信号量、 Socket ), Binder 机制的优点有: 特别地,对于从模型结构组成的Binder驱动来说: 不定期分享关于 安卓开发 的干货,追求 短、平、快 ,但 却不缺深度 。2023-06-17 14:55:121
Android源码解析RPC系列(一)---Binder原理
看了几天的Binder,决定有必要写一篇博客,记录一下学习成果,Binder是Android中比较综合的一块知识了,目前的理解只限于JAVA层。首先Binder是干嘛用的?不用说,跨进程通信全靠它,操作系统的不同进程之间,数据不共享,对于每个进程来说,它都天真地以为自己独享了整个系统,完全不知道其他进程的存在,进程之间需要通信需要某种系统机制才能完成,在Android整个系统架构中,采用了大量的C/S架构的思想,所以Binder的作用就显得非常重要了,但是这种机制为什么是Binder呢?在Linux中的RPC方式有管道,消息队列,共享内存等,消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,这样就有两次拷贝过程。共享内存不需要拷贝,但控制复杂,难以使用。Binder是个折中的方案,只需要拷贝一次就行了。其次Binder的安全性比较好,好在哪里,在下还不是很清楚,基于安全性和传输的效率考虑,选择了Binder。Binder的英文意思是粘结剂,Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程中,这个进程一般是Server端,该对象提供了一套方法用以实现对服务的请求,而它的引用却遍布于系统的各个进程(Client端)之中,这样Client通过Binder的引用访问Server,所以说,Binder就像胶水一样,把系统各个进程粘结在一起了,废话确实有点多。 为了从而保障了系统的安全和稳定,整个系统被划分成内核空间和用户空间 内核空间:独立于普通的应用程序,可以访问受保护的内存空间,有访问底层硬件设备的所有权限。 用户空间:相对与内核空间,上层运用程序所运行的空间就是用户空间,用户空间访问内核空间的唯一方式就是系统调用。一个4G的虚拟地址空间,其中3G是用户空间,剩余的1G是内核空间。如果一个用户空间想与另外一个用户空间进行通信,就需要内核模块支持,这个运行在内核空间的,负责各个用户进程通过Binder通信的内核模块叫做Binder驱动,虽然叫做Binder驱动,但是和硬件并没有什么关系,只是实现方式和设备驱动程序是一样的,提供了一些标准文件操作。 在写AIDL的时候,一般情况下,我们有两个进程,一个作为Server端提供某种服务,然后另外一个进程作为Client端,连接Server端之后,就 可以使用Server里面定义的服务。这种思想是一种典型的C/S的思想。值得注意的是Android系统中的Binder自身也是C/S的架构,也有Server端与Client端。一个大的C/S架构中,也有一个小的C/S架构。 先笼统的说一下,在整个Binder框架中,由系列组件组成,分别是Client、Server、ServiceManager和Binder驱动程序,其中Client、Server和ServiceManager运行在用户空间,Binder驱动程序运行内核空间。运行在用户空间中的Client、Server和ServiceManager,是在三个不同进程中的,Server进程中中定义了服务提供给Client进程使用,并且Server中有一个Binder实体,但是Server中定义的服务并不能直接被Client使用,它需要向ServiceManager注册,然后Client要用服务的时候,直接向ServiceManager要,ServiceManager返回一个Binder的替身(引用)给Client,这样Client就可以调用Server中的服务了。 场景 :进程A要调用进程B里面的一个draw方法处理图片。 分析 :在这种场景下,进程A作为Client端,进程B做为Server端,但是A/B不在同一个进程中,怎么来调用B进程的draw方法呢,首先进程B作为Server端创建了Binder实体,为其取一个字符形式,可读易记的名字,并将这个Binder连同名字以数据包的形式通过Binder驱动发送给ServiceManager,也就是向ServiceManager注册的过程,告诉ServiceManager,我是进程B,拥有图像处理的功能,ServiceManager从数据包中取出名字和引用以一个注册表的形式保留了Server进程的注册信息。为什么是以数据包的形式呢,因为这是两个进程,直接传递对象是不行滴,只能是一些描述信息。现在Client端进程A联系ServiceManager,说现在我需要进程B中图像处理的功能,ServiceManager从注册表中查到了这个Binder实体,但是呢,它并不是直接把这个Binder实体直接给Client,而是给了一个Binder实体的代理,或者说是引用,Client通过Binder的引用访问Server。分析到现在,有个关键的问题需要说一下,ServiceManager是一个进程,Server是另一个进程,Server向ServiceManager注册Binder必然会涉及进程间通信。当前实现的是进程间通信却又要用到进程间通信,这就好象蛋可以孵出鸡前提却是要找只鸡来孵蛋,确实是这样的,ServiceManager中预先有了一个自己的Binder对象(实体),就是那只鸡,然后Server有个Binder对象的引用,就是那个蛋,Server需要通过这个Binder的引用来实现Binder的注册。鸡就一只,蛋有很多,ServiceManager进程的Binder对象(实体)仅有一个,其他进程所拥有的全部都是它的代理。同样一个Server端Binder实体也应该只有一个,对应所有Client端全部都是它的代理。 我们再次理解一下Binder是什么?在Binder通信模型的四个角色里面;他们的代表都是“Binder”,一个Binder对象就代表了所有,包括了Server,Client,ServiceManager,这样,对于Binder通信的使用者而言,不用关心实现的细节。对Server来说,Binder指的是Binder实体,或者说是本地对象,对于Client来说,Binder指的是Binder代理对象,也就是Binder的引用。对于Binder驱动而言,在Binder对象进行跨进程传递的时候,Binder驱动会自动完成这两种类型的转换。 简单的总结一下,通过上面一大段的分析,一个Server在使用的时候需要经历三个阶段 1、定义一个AIDL文件 Game.aidl GameManager .aidl 2、定义远端服务Service 在远程服务中的onBind方法,实现AIDL接口的具体方法,并且返回Binder对象 3、本地创建连接对象 以上就是一个远端服务的一般套路,如果是在两个进程中,就可以进程通信了,现在我们分析一下,这个通信的流程。重点是GameManager这个编译生成的类。 从类的关系来看,首先接口GameManager 继承 IInterface ,IInterface是一个接口,在GameManager内部有一个内部类Stub,Stub继承了Binder,(Binder实现了IBinder),并且实现了GameManager接口,在Stub中还有一个内部类Proxy,Proxy也实现了GameManager接口,一个整体的结构是这样的 现在的问题是,Stub是什么?Proxy又是什么?在上面说了在Binder通信模型的四个角色里面;他们的代表都是“Binder”,一个Binder对象就代表了所有,包括了Server,Clinet,ServiceManager,为了两个进程的通信,系统给予的内核支持是Binder,在抽象一点的说,Binder是系统开辟的一块内存空间,两个进程往这块空间里面读写数据就行了,Stub从Binder中读数据,Proxy向Binder中写数据,达到进程间通信的目的。首先我们分析Stub。 Stub 类继承了Binder ,说明了Stub有了跨进程传输的能力,实现了GameManager接口,说明它有了根据游戏ID查询一个游戏的能力。我们在bind一个Service之后,在onServiceConnecttion的回调里面,就是通过asInterface方法拿到一个远程的service的。 asInterface调用queryLocalInterface。 mDescriptor,mOwner其实是Binder的成员变量,Stub继承了Binder,在构造函数的时候,对着两个变量赋的值。 如果客户端和服务端是在一个进程中,那么其实queryLocalInterface获取的就是Stub对象,如果不在一个进程queryLocalInterface查询的对象肯定为null,因为不同进程有不同虚拟机,肯定查不到mOwner对象的,所以这时候其实是返回的Proxy对象了。拿到Stub对象后,通常在onServiceConnected中,就把这个对象转换成我们多定义AIDL接口。 比如我们这里会转换成GameManager,有了GameManager对象,就可以调用后querryGameById方法了。如果是一个进程,那直接调用的是自己的querryGameById方法,如果不是一个进程,那调用了就是代理的querryGameById方法了。 看到其中关键的一行是 mRemote就是一个IBinder对象,相对于Stub,Proxy 是组合关系(HAS-A),内部有一个IBinder对象mRemote,Stub是继承关系(IS-A),直接实现了IBinder接口。 transact是个native方法,最终还会回掉JAVA层的onTransact方法。 onTransact根据调用号(每个AIDL函数都有一个编号,在跨进程的时候,不会传递函数,而是传递编号指明调用哪个函数)调用相关函数;在这个例子里面,调用了Binder本地对象的querryGameById方法;这个方法将结果返回给驱动,驱动唤醒挂起的Client进程里面的线程并将结果返回。于是一次跨进程调用就完成了。 ***Please accept mybest wishes for your happiness and success ! ***2023-06-17 14:55:191
Android为什么选择binder
Binder主要能提供以下一些功能: 用驱动程序来推进进程间的通信。 通过共享内存来提高性能。 为进程请求分配每个进程的线程池。 针对系统中的对象引入了引用计数和跨进程的对象引用映射。 进程间同步调用。Android Binder设计与实现 – 设计篇: 目前linux支持的IPC包括传统的管道、System V IPC、即消息队列/共享内存/信号量,以及socket中只有socket支持Client-Server的通信方式。当然也可以在这些底层机制上架设一套协议来实现Client-Server通信,但这样增加了系统的复杂性,在手机这种条件复杂,资源稀缺的环境下可靠性也难以保证。另一方面是传输性能: socket作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。共享内存虽然无需拷贝,但控制复杂,难以使用。还有一点是出于安全性考虑: Android作为一个开放式,拥有众多开发者的平台,应用程序的来源广泛,确保智能终端的安全是非常重要的。终端用户不希望从网上下载的程序在不知情的情况下偷窥隐私数据,连接无线网络,长期操作底层设备导致电池很快耗尽等等。传统IPC没有任何安全措施,完全依赖上层协议来确保。首先传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份。 Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加。其次传统IPC访问接入点是开放的,无法建立私有通道。比如命名管道的名称、system V的键值、socket的ip地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。 基于以上原因,Android需要建立一套新的IPC机制来满足系统对通信方式,传输性能和安全性的要求,这就是Binder。Binder基于 Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。面向对象的 Binder IPC: 面向对象思想的引入将进程间通信转化为通过对某个Binder对象的引用调用该对象的方法,而其独特之处在于Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程中,而它的引用却遍布于系统的各个进程之中。最诱人的是,这个引用和java里引用一样既可以是强类型,也可以是弱类型,而且可以从一个进程传给其它进程,让大家都能访问同一Server,就像将一个对象或引用赋值给另一个引用一样。Binder模糊了进程边界,淡化了进程间通信过程,整个系统仿佛运行于同一个面向对象的程序之中。 面向对象只是针对应用程序而言,对于Binder驱动和内核其它模块一样使用C语言实现,没有类和对象的概念。Binder驱动为面向对象的进程间通信提供底层支持。2023-06-17 14:55:401
华为手机binder是病毒吗
不是。那个是华为云为你提供binder的精选文章等,同时提供包含binder相关的软件资源、产品活动、最佳实践以及常见问题文档等信息。工作原理:手机中的软件,嵌入式操作系统(固化在芯片中的操作系统,一般由 JAVA、C++等语言编写),相当于一个小型的智能处理器,所以会遭受病毒攻击。而且,短信也不只是简单的文字,其中包括手机铃声、图片等信息,都需要手机中的操作系统进行解释,然后显示给手机用户,手机病毒就是靠软件系统的漏洞来入侵手机的。手机病毒要传播和运行,必要条件是移动服务商要提供数据传输功能,而且手机需要支持Java等高级程序写入功能。许多具备上网及下载等功能的手机都可能会被手机病毒入侵。传播方式:利用蓝牙方式传播:“卡波尔”病毒会修改智能手机的系统设置,通过蓝牙自动搜索相邻的手机是否存在漏洞,并进行攻击。感染PC上的手机可执行文件:“韦拉斯科”病毒感染电脑后,会搜索电脑硬盘上的SIS可执行文件并进行感染。利用MMS多媒体信息服务方式来传播:。利用手机的BUG攻击:这类病毒一般是在便携式信息设备的“ EPOC”上运行,如“EPOC-ALARM”、“EPOC-BANDINFO.A”、“EPOC-FAKE.A”、“EPOC-GHOST.A”、“EPOC-ALIGHT.A”等。2023-06-17 14:55:471
12 Binder原理-基础知识点
Binder原理是掌握系统底层原理的基石,也是进阶高级工程师的必备知识点,这篇文章不会过多介绍Binder原理,而是讲解学习Binder前需要的掌握的知识点。 IPC全名为inter-Process Communication,含义为进程间通信,是指两个进程之间进行数据交换的过程。在Android和Linux中都有各自的IPC机制,这里分别来介绍下。 Linux中提供了很多进程间通信机制,主要有管道(pipe)、信号(sinal)、信号量(semophore)、消息队列(Message)、共享内存(Share Memory)、套接字(Socket)等。 管道 管道是Linux由Unix那里继承过来的进程间的通信机制,它是Unix早期的一个重要通信机制。管道的主要思想是,在内存中创建一个共享文件,从而使通信双方利用这个共享文件来传递信息。这个共享文件比较特殊,它不属于文件系统并且只存在于内存中。另外还有一点,管道采用的是半双工通信方式的,数据只能在一个方向上流动。 简单的模型如下所示。 信号 信号是软件层次上对中断机制的一种模拟,是一种异步通信方式,进程不必通过任何操作来等待信号的到达。信号可以在用户空间进程和内核之间直接交互,内核可以利用信号来通知用户空间的进程发生了哪些系统事件。信号不适用于信息交换,比较适用于进程中断控制。 信号量 信号量是一个计数器,用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。主要作为进程间以及同一进程内不同线程之间的同步手段。 消息队列 消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识,并且允许一个或多个进程向它写入与读取消息。信息会复制两次,因此对于频繁或者信息量大的通信不宜使用消息队列。 共享内存 多个进程可以直接读写的一块内存空间,是针对其他通信机制运行效率较低而设计的。 为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大的提高效率。 套接字 套接字是更为基础的进程间通信机制,与其他方式不同的是,套接字可用于不同机器之间的进程间通信。 Android系统是基于Linux内核的,在Linux内核基础上,又拓展出了一些IPC机制。Android系统除了支持套接字,还支持序列化、Messenger、AIDL、Bundle、文件共享、ContentProvider、Binder等。Binder会在后面介绍,先来了解前面的IPC机制。 序列化 序列化指的是Serializable/Parcelable,Serializable是Java提供的一个序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作。Parcelable接口是Android中的序列化方式,更适合在Android平台上使用,用起来比较麻烦,效率很高。 Messenger Messenger在Android应用开发中的使用频率不高,可以在不同进程中传递Message对象,在Message中加入我们想要传的数据就可以在进程间的进行数据传递了。Messenger是一种轻量级的IPC方案并对AIDL进行了封装。 AIDL AIDL全名为Android interface definition Language,即Android接口定义语言。Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户端显然是不合适的。另外还有一点,Messenger用来进程间进行数据传递但是却不能满足跨进程的方法调用,这个时候就需要使用AIDL了。 Bundle Bundle实现了Parcelable接口,所以它可以方便的在不同的进程间传输。Acitivity、Service、Receiver都是在Intent中通过Bundle来进行数据传递。 文件共享 两个进程通过读写同一个文件来进行数据共享,共享的文件可以是文本、XML、JOSN。文件共享适用于对数据同步要求不高的进程间通信。 ContentProvider ContentProvider为存储和获取数据了提供统一的接口,它可以在不同的应用程序之间共享数据,本身就是适合进程间通信的。ContentProvider底层实现也是Binder,但是使用起来比AIDL要容易许多。系统中很多操作都采用了ContentProvider,例如通讯录,音视频等,这些操作本身就是跨进程进行通信。 在讲到Linux的进程通信原理之前,我们需要先了解Liunx中的几个概念。 内核空间和用户空间 当我们接触到Liunx时,免不了听到两个词,User space(用户空间)和 Kernel space(内核空间),那么它们的含义是什么呢? 为了保护用户进程不能直接操作内核,保证内核的安全,操作系统从逻辑上将虚拟空间划分为用户空间和内核空间。Linux 操作系统将最高的1GB字节供内核使用,称为内核空间,较低的3GB 字节供各进程使用,称为用户空间。 内核空间是Linux内核的运行空间,用户空间是用户程序的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不会受到影响。内核空间的数据是可以进程间共享的,而用户空间则不可以。比如在上图进程A的用户空间是不能和进程B的用户空间共享的。 进程隔离 进程隔离指的是,一个进程不能直接操作或者访问另一个进程。也就是进程A不可以直接访问进程B的数据。 系统调用 用户空间需要访问内核空间,就需要借助系统调用来实现。系统调用是用户空间访问内核空间的唯一方式,保证了所有的资源访问都是在内核的控制下进行的,避免了用户程序对系统资源的越权访问,提升了系统安全性和稳定性。 进程A和进程B的用户空间可以通过如下系统函数和内核空间进行交互。 内存映射 由于应用程序不能直接操作设备硬件地址,所以操作系统提供了一种机制:内存映射,把设备地址映射到进程虚拟内存区。 举个例子,如果用户空间需要读取磁盘的文件,如果不采用内存映射,那么就需要在内核空间建立一个页缓存,页缓存去拷贝磁盘上的文件,然后用户空间拷贝页缓存的文件,这就需要两次拷贝。 采用内存映射,如下图所示。 由于新建了虚拟内存区域,那么磁盘文件和虚拟内存区域就可以直接映射,少了一次拷贝。 内存映射全名为Memory Map,在Linux中通过系统调用函数mmap来实现内存映射。将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间,反之亦然。内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。 了解Liunx中的几个概念后,就可以学习Linux的IPC通信原理了,如下图所示。 内核程序在内核空间分配内存并开辟一块内核缓存区,发送进程通过copy_from_user函数将数据拷贝到到内核空间的缓冲区中。同样的,接收进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用 copy_to_user() 函数将数据从内核缓存区拷贝到接收进程。这样数据发送进程和数据接收进程完成了一次数据传输,也就是一次进程间通信。 Linux的IPC通信原理有两个问题: Binder是基于开源的OpenBinder实现的,OpenBinder最早并不是由Google公司开发的,而是Be Inc公司开发的,接着由Palm, Inc.公司负责开发。后来OpenBinder的作者Dianne Hackborn加入了Google公司,并负责Android平台的开发工作,顺便把这项技术也带进了Android。 Binder是基于内存映射来实现的,在前面我们知道内存映射通常是用在有物理介质的文件系统上的,Binder没有物理介质,它使用内存映射是为了跨进程传递数据。 Binder通信的步骤如下所示。 1.Binder驱动在内核空间创建一个数据接收缓存区。 2.在内核空间开辟一块内核缓存区,建立内核缓存区和数据接收缓存区之间的映射关系,以及数据接收缓存区和接收进程用户空间地址的映射关系。 3.发送方进程通过copy_from_user()函数将数据拷贝 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。 整个过程只使用了1次拷贝,不会因为不知道数据的大小而浪费空间或者时间,效率更高。 Android是基于Linux内核的 ,Linux提供了很多IPC机制,而Android却自己设计了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采用的是信号。 Binder机制在Android中的地位举足轻重,我们需要掌握的很多原理都和Binder有关: 上面只是列了一小部分,简单来说说,比如系统在启动时,SystemServer进程启动后会创建Binder线程池,目的是通过Binder,使得在SystemServer进程中的服务可以和其他进程进行通信了。再比如我们常说的AMS、PMS都是基于Binder来实现的,拿PMS来说,PMS运行在SystemServer进程,如果它想要和DefaultContainerService通信(是用于检查和复制可移动文件的系统服务),就需要通过Binder,因为DefaultContainerService运行在com.android.defcontainer进程。 还有一个比较常见的C/S架构间通信的问题,Client端的MediaPlayer和Server端的MeidaPlayerService不是运行在一个进程中的,同样需要Binder来实现通信。 可以说Binder机制是掌握系统底层原理的基石。 上图并没有给出Binder机制的具体的细节,而是先给出了一个概念,根据系统的Android系统的分层。2023-06-17 14:56:011
binder综合症国内比例
8:2。Binder综合症”又称先天性中面部凹陷,通俗点说就是中面部及鼻部在不同程度上发育不良,且这类病症在东方人中的发病率不算低,有研究人员称在我国发病比例在8:2;且这种病是遗传的,97例binder综合征的患儿进行研究,发现存在确切家族史的患者比率高达36%。2023-06-17 14:56:081
华为手机binder是病毒吗
不是。那个是华为云为你提供binder的精选文章等,同时提供包含binder相关的软件资源、产品活动、最佳实践以及常见问题文档等信息。工作原理:手机中的软件,嵌入式操作系统(固化在芯片中的操作系统,一般由 JAVA、C++等语言编写),相当于一个小型的智能处理器,所以会遭受病毒攻击。而且,短信也不只是简单的文字,其中包括手机铃声、图片等信息,都需要手机中的操作系统进行解释,然后显示给手机用户,手机病毒就是靠软件系统的漏洞来入侵手机的。手机病毒要传播和运行,必要条件是移动服务商要提供数据传输功能,而且手机需要支持Java等高级程序写入功能。许多具备上网及下载等功能的手机都可能会被手机病毒入侵。传播方式:利用蓝牙方式传播:“卡波尔”病毒会修改智能手机的系统设置,通过蓝牙自动搜索相邻的手机是否存在漏洞,并进行攻击。感染PC上的手机可执行文件:“韦拉斯科”病毒感染电脑后,会搜索电脑硬盘上的SIS可执行文件并进行感染。利用MMS多媒体信息服务方式来传播:。利用手机的BUG攻击:这类病毒一般是在便携式信息设备的“ EPOC”上运行,如“EPOC-ALARM”、“EPOC-BANDINFO.A”、“EPOC-FAKE.A”、“EPOC-GHOST.A”、“EPOC-ALIGHT.A”等。2023-06-17 14:56:161
Android IPC机制 Binder
u2003每次 单向通信 拷贝次数为 1,server用户空间和内核空间通过内存映射可以直接交互。 u2003内核4M 上层限制1m-8k(传输Bitmap过大,就会崩溃的原因,Activity之间传输BitMap)。 u2003 《Android 基础组件 全家桶》 u2003 进程间通信IPC 为什么 Android 要采用 Binder 作为 IPC 机制? Android-Binder机制 Android Bander设计与实现 - 设计篇 Android跨进程通信:图文详解 Binder机制 原理 听说你Binder机制学的不错,来面试下这几个问题(一) Binder学习指南 Android中的Binder机制二(匿名Binder)2023-06-17 14:56:291
dividers for binder 是什么意思?
Dividers 名词 隔板。for介词 为。 binder 名词 粘接剂。合起来意思是: 供粘接剂用的隔板。2023-06-17 14:56:382
Binder文档中的 “Binder通信是同步而不是异步”,如何理解?
binder通信是阻塞的,发出方要一直等到接收方的回复。2023-06-17 14:56:461
binder和adhesive的区别
binder n. 粘合剂; 包扎物,包扎工具; [法] 临时契约; 装订工 adhesive n. 黏合剂,粘着剂; adj. 可黏着的,黏性的;2023-06-17 14:56:551
Android-zygote进程通信为什么不使用Binder?
首先,zygote进程在创建之后,才会创建SystemServer进程,而SystemServer进程是由zygote进程fock自身得到的,在fock自身的过程中,首先会结束自身的其他子线程,这样一来除了自身线程以外,其他线程都会被结束然后GC,而Binder是多线程模型,如果使用Binder进行进程间通信的话,则Binder线程也会被结束,而使用Binder进行进程间通信就无法做到。在fork新进程后,启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程。而在zygote通过fock自身创建子进程之后,如果该进程不是zygote进程,则会调用ZygoteInit.zygoteInit方法 而在zygoteInit方法中,才会对新创建的进程进行运行环境初始化工作以及启动Binder线程池。 其实Binder线程池的启动,是在SystemServer进程创建过程启动的,而在启动SystemServer的过程中,就需要传入ZygoteServer这个Zygote作为Server端的Socket,所以Zygote进程并不能使用Binder进程进行通信,而只能使用Socket。 而且,Binder线程池是在zygote进程启动之后启动的SystemServer进程中启动的,而SystemServer进程是由zygote进程fock自身得到的,所以zygote进程在启动之后,循环等待SystemServer进程的消息的时候,其实还没有Binder线程池。而且fock只支持当前线程的fock,而不支持多线程的fock,但是Binder又是一个多线程模型,在fock的时候会杀死多余的线程,这样一来,binder线程也就会被杀死,这样就没办法使用binder与SystemServer进程进行进程间通信。 fork 的行为是这样的:复制整个用户空间的数据(通常使用 copy-on-write 的策略,所以可以实现的速度很快)以及所有系统对象,然后仅复制当前线程到子进程。这里:所有父进程中别的线程,到了子进程中都是突然蒸发掉的2023-06-17 14:57:021
捆绑机病毒是什么
不是但是捆绑机一般就是用于病毒制作,所以会被一些杀毒软件给拦截了一些正规的捆绑机软件也有不过他做出来的捆绑软件不会在后台进行安装,需进同意后才会进行安装。2023-06-17 14:57:422
Android里用 C 语言编写的应用程序怎么通过 binder 节点通信
我不懂你的意思,什么叫C程序?你要直接call binder driver么?如果只是想在native layer里通过servicemanager 注册一个service,然后用client 去call,我过去用过这个github的project去测android binder的readwrite performance: mcr/Android-HelloWorldService · GitHub 然后你要想办法把service run 起来,我当时很hack,直接在zygote里改了代码,强行让helloworld在系统init的时候生成,但应该有命令行给你用的,你可以在看看。 而去直接去和binder driver做交互也没问题,只要做几个ioctl call,然后起两个process,一个注册一个节点,然后另一个去写message,但我没具体实现过,你玩玩应该就出来了,我感觉过程可能就像这个shmget的example差不多 IPC:Shared Memory。 此外,Binder这东西没什么独特的,它就是把最基本的message passing:一次传输要向kernel copy paste两次(一次sender 到kernel,一次kernel到receiver,每次都有context switch)和shared memory(kernel 和 userland share 一块 内存,不用context switch)合并起来了,就是receiver和kernel共享一块内存,而sender和kernel的交互必须要严格遵守message passing的原则,于是就取了一个折中,两次copy paste就变成了一次。 此外,service manager会在自己被生成的时候现将自己注册成binder里一个最特殊的service,其他程序想要进行ipc,就必须通过binder向service manager注册,在binder生成一个unique id,然后其他client向service manager查询时候就会得到那个id,于是就能通过binder与service process建立通讯。 我过去很喜欢玩这个,还很蛋疼的在minix上把binder原理实现了一遍,还有一个大神 老罗,他研究Android native非常透彻,你可以看他博客,能够对整个Android从init到Dalvik跑起来全部了解,我现在只知道他一个,因为他把Android source code全都读了一遍:老罗的Android之旅2023-06-17 14:57:511
android中Boundservice和 IBinder 还有Binder这三者有什么联系和区别???
IBinder 就是绑定服务的方式启动服务,即服务可以通过Binder与启动service的类通信用的。2023-06-17 14:57:592
android Service中自定义的Binder如何操作service中的handler
你描述不清出。至少我没看清楚。我尝试按照我自己对你描述的问题的理解来作答。binder.taskExecute()里头你没有涉及到“系统通知栏”的代码,所以当然没有变化!!!其次,你对于handler的理解有错误。我粗粗点下:thread A和thread B。A有B的Handler从而能和B通过Handler沟通。B也有A的Handler。当然,这个Handler都是在A或者B构造函数的时候传进去的(例如A exampleA = new A(B"s handler);)至于两个thread如何根据handler沟通?通过Message来沟通。线程A和B都有一个message queue(消息队列)。你构建一个message实例,然后将它加入到(此处具体化,例如放入B里头)线程的message queue里头中。这样线程(从队列里读一条处理一条就可以处理到你加入的Message,用Handler的handleMessage来处理)。(下面用aHandler,bHandler分别表示thread A的handler和B的hanler。)所以aHandler.sendEmptyMessage(int what)就是在添加一只带有what值的Message到A里头。bHandler....类似。所以,假设我现在是A,我为了告诉B一些东西,我就将我要告诉的B的东西(信息)放入到一个Message中,再将这个Message加入到B的消息队列中。(譬如你此问中,需要将“下载完成”“下载失败”这些信息添加进入message里头)。然后这个message怎么加入到B的消息的队列呢?这就是为什么要在A的构造函数里头传入B的Handler(bHandler)一个引用的原因。对于你的需求,Handler和Binder功能重复了。要么用Binder,要么用Handler。至于想在一个activity中调用自定义Binder里头的一个方法,不需要发送消息。只需要在需要调用的地方实例化一个Binder,然后通过这个实例.functionYouNeeded()就行。欢迎追问。2023-06-17 14:58:071
安卓系统的binder通信机制和intent通信机制的不同之处
它们都是串行通讯是没错的,区别I2C同步传送,也没是说每传一位都要一个同步时钟脉冲(脉冲是SCL发出),接收和发送数据都是用SDA,UART则不需要同步时钟脉冲,UART则是通过TXD发,RXD收,它是通过设置好一个固定通讯速率传送数据的,这个速率就是我们所说的波特率了。我相信楼主现在应该明白了哦!2023-06-17 14:58:151
Android Binder Hook的实现
Binder Hook可以Hook掉 当前App 用到的系统Service服务。 以LocationManager为例,在获取一个LocationManager时分为两步。第一,获取IBinder对象;第二:IBinder对象通过asInterface()转化为LocationMangerService对象。最后初始化LocationManager,application层用到的都是LocationManager。 Hook的大致原理是:ServiceManager在获取某个Binder时,如果本地有缓存的Binder,就不再跨进程请求Binder了。我们可以在缓存中加入自己的Binder,使得ServiceManager查询本地缓存时得到一个自定义的CustomBinder对象,不再跨进程向系统请求。并且ILocationManager.Stub.asInterface(CustomBinder)方法返回我们自定义的Service对象。 这里面有两个地方需要用到自定义的对象。由于我们只Hook其中一部分的功能,其他功能还需要保留,所以用动态代理的方式创建自定义的Binder和自定义的Service。 在理解后面的内容前你需要了解这些知识点: Activity等类在获取系统Service时,都是调用getSystemService(serviceName)方法获取的。 Context 的 getSystemService() 方法调用了 SystemServiceRegistry 的 getSystemService() 方法。 SystemServiceRegistry 中有一个常量 SYSTEM_SERVICE_FETCHERS,这是一个Map。保存了ServiceName和对应的ServiceFetcher。ServicFetcher是用于创建具体Service的类。ServiceFetcher 的关键方法是 createService() 方法。 在 ServiceFetcher 的 createService() 方法中,调用了 ServiceManager.getService(name) 方法。以 LocationManager 对应的 ServiceFetcher 为例,它的createService()方法源码如下: 假如我们要修改 LocationManager 的 getLastKnownLocation() 方法(下文都是)。我们要做的就是让ServiceManager.getService("location")返回我们自定义的Binder。先看一下这个方法简化后的源码: sCache是一个Map,缓存了已经向系统请求过的Binder。如果我们需要让这个方法返回我们我们自己的binder,只需要事先往sCache中put一个自定义的Binder就行了。 在put之前,需要先创建出一个自定义的Binder。这个Binder在被 ILocationManager.Stub.asInterface 处理后,可以返回一个自定义的 LocationManagerService。 先看一下Binder的 asInterface() 的实现: 如果把 queryLocalInterface()方法返回一个自定义的Service,使得走if语句内部,不走else,那就算是Hook成功了。 假设我们想让系统的LocationManager返回的位置信息全是在天安门(116.23, 39.54)。那我们需要使得 LocatitionManagerService 的 getLastLocation() 方法 返回的全是 (116.23, 39.54)。 由于我们不能直接拿到系统的这个Service对象,可以先用反射的方式拿到系统的LocationManagerService。然后拦截getLastLocation()方法。 原生的Binder对象在调用 queryLocalInterface() 方法时会返回原生的Service对象。我们希望返回3.1中的自定义Service。所以这里拦截 queryLocalInterface() 方法。 有了自定义的Binder后,将它注入到ServiceManger的sCache变量中就完成Hook了~ 当onClick被调用的时候,Toast和Log都会显示天安门的坐标(116.23, 39.54)。证明Hook成功! 你甚至可以用Binder Hook的方式Hook掉 ActivityManager 。2023-06-17 14:58:231
加拿大的纸和binder 都是什么规格的?
纸啊,问什么纸啊,放在BINDER里面的是三个孔,一般学校有打孔机,可以自己打。binder也使三孔的。确实便宜,1dollar多一点就可以买到。如果问打印纸,216X279mm的。2023-06-17 14:58:332
如何在Android下使用Binder
实现一个binder通信实例,需要经过以下步骤: (1)获得ServiceManager的对象引用 (2)向ServiceManager注册新的Service (3)在Client中通过ServiceManager获得Service对象引用 (3)在Client中发送请求,由Service返回结果。 下面看具体的代码如何实现。 3.1 libmyservice代码实现 (1)新建目录frameworks/base/myservice/libservice,进入该目录 view plain $ cd frameworks/base $ mkdir myservice $ cd myservice $ mkdir libmyservice $ cd libmyservice (2)编写libmyservice/myservic.h文件 view plain #include <utils/threads.h> #include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/BpBinder.h> #include <binder/Parcel.h> namespace android { class MyService : public BBinder { mutable Mutex mLock; int32_t mNextConnId; public: static int instantiate(); MyService(); virtual ~MyService(); virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); }; }; //namespace (2)编写libservice/myservice.cpp文件 view plain #include "myservice.h" #include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> namespace android { static struct sigaction oldact; static pthread_key_t sigbuskey; int MyService::instantiate() { LOGE("MyService instantiate"); // defaultServiceManager ()获得ServiceManager的对象引用,addService()可向ServiceManager注册新的服务 int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService()); LOGE("MyService r = %d/n", r); return r; } MyService::MyService() { LOGV("MyService created"); mNextConnId = 1; pthread_key_create(&sigbuskey, NULL); } MyService::~MyService() { pthread_key_delete(sigbuskey); LOGV("MyService destroyed"); } // 每个系统服务都继承自BBinder类,都应重写BBinder的onTransact虚函数。当用户发送请求到达Service时,系统框架会调用Service的onTransact函数,该函数分析接收到的数据包,调用相应的接口函数处理请求 status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case 0: { pid_t pid = data.readInt32(); int num = data.readInt32(); num = num + 100; reply->writeInt32(num); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } }; //namespace (3)编写libservice/Android.mk文件 view plain # File: Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := myservice.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := libutils libbinder LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libmyservice include $(BUILD_SHARED_LIBRARY) (4)编译libmyservice.so动态库 在android源码主目录下 view plain $ source build/envsetup.sh including device/htc/passion/vendorsetup.sh including device/samsung/crespo4g/vendorsetup.sh including device/samsung/crespo/vendorsetup.sh $ mmm frameworks/base/myservice/libmyservice/ 编译成功后生成文件:out/target/product/generic/system/lib/libmyservice.so2023-06-17 14:58:541
binder 和 bundle的区别
binder英 [u02c8bau026andu0259(r)] 美 [u02c8bau026andu025a] n.粘合剂;包扎物,包扎工具;[法]临时契约;装订工bundle英 [u02c8bu028cndl] 美 [u02c8bu028cndl] n.捆;一批(同类事物或出售的货品);一大笔钱;风趣的人vt.& vi.收集,归拢,把…塞入vt.额外免费提供(设备等),(尤指出售计算机时)赠送软件vi.匆匆送走;推搡;赶;(成群地)匆忙赶往2023-06-17 14:59:021
binder线程数目不够导致ANR
binder线程数目最大为16个2023-06-17 14:59:101
级进冲压模具中,blank on binder 怎么解释?
BLANK,应该是凹模,BINDER是凸模2023-06-17 14:59:171
为什么Android的Handler采用管道而不使用Binder
首先Handler不见得使用管道 (pipe), 事实上, 在Android M中实际上使用了 eventfd. 不过这不关键.要想比较好的理解为什么Handler使用管道而不是Binder, 我们可以从开发者的角度来思考一下: 在Looper中, 他要解决一个什么问题? 我自己本身不是很熟悉Looper这些概念, 粗粗看了下代码: 大约可以看成是消息循环(Message Loop)的样子吧. 其它线程发消息,Looper所在的线程接受并处理消息. 好吧, 开发者要解决的是一个生产者消费者问题. 一般说来对于生产者消费者问题我们需要考虑几个因素: buffer (用于存放"产品"的内存), 上锁 (保护对buffer的访问), 等待/唤醒:1. 生产者和消费者在同一个进程内, 所以无需考虑共享内存问题2. 上锁: posix mutex, 简单好用3. 等待/唤醒: 在没有消息时, 消费者不能忙等, 而应该阻塞 (block) 直到新消息到来 -这里的关键是3), 在Android/Linux中有很多方法可以用来等待/唤醒, 比如条件变量, Posix信号量 (Android不支持System V信号量), 消息队列, Unix socket , pipe, 甚至binder等等. 怎么选呢? Looper开发者的标准很可能是: 选较"轻"的. 于是他先选了pipe, 以后又发现eventfd更好 (很可能开发者不知道eventfd的存在, 毕竟eventfd还是比较新的系统调用).2023-06-17 14:59:241
defaultServiceManager介绍
我们在使用binder时候的大致流程是先获取servicemanger的binder,然后通过该binder获取目标服务的binder,最后调用该binder的接口。本篇就介绍下第一步的内容,涉及了从native到驱动,fwk部分先不涉及,希望可以完全理解servicemanager的获取流程。 整个流程的起点是IServiceManager::defaultServiceManager() 可以看到这是一个单例,在首次调用的时候会进行初始化获取servicemanager的binder,然后用智能指针封装一下。 可以看到这儿还是一个单例,对于参与binder IPC的进程,和binder驱动交互部分就是通过ProcessState实现的。 对于android,有三种binder驱动节点,下面列一下区别: 接下来看下ProcessState的构造方法: 这儿有两个和驱动交互的部分,一个是open_driver,一个是mmap,这里先介绍下open_driver: 这儿的流程比较直接,就是打开节点,用ioctl获取了版本号,设置了线程池数量,设置了允许异步调用检测。接下来看下open 的内容,这时候就会进入内核,因为binder驱动定义了自己的open,ioctl,mmap方法。 接下来看下init_binder_device的实现: 这儿就是将binder驱动设备注册为一个misc设备,并指定了它的操作实现方法。 因为上层是先调用的open,因此看下这儿binder_open的实现: 这儿主要就是创建了一个binder_proc结构,并和当前用户态进程current关联起来。 再看下ioctl的内容: 看到这一块,之前的三个ioctl命令内容就清楚了。接下来需要看下一个关键的地方,就是mmap,对应的实现就是binder_mmap: 这儿没做啥,看下binder_alloc_mmap_handler: 这时候驱动做的事情就是将用户态的地址保存到proc自己的结构里面。 mmap暂时告一段落。 继续回到用户态,继续ProcessState::self()->getContextObject(nullptr) 获取serviemanager的binder过程,前一部分介绍完了,接下来应该是getContextObject部分,看下实现: 对于servicemanager,handle为0,看下getStrongProxyForHandle的内容: 如果本地没有servicemanager的proxy binder,那么就需要用驱动获取。继续看下获取流程: 看下transact: 可以看到transact里面的流程就是封装数据包和与驱动交互,如果有返回值,则直接写入reply。先看下如何封装的数据包: 这时候就把请求相关的写入了parcel,接下来看下waitForResponse: 看下talkWithDriver: 这儿就是将请求写入binder_write_read,并和驱动进行交互。在进入驱动前,先看下binder_write_read的结构: 在驱动中,ioctl的操作如下: 先看下binder_get_thread的操作: binder_get_thread_ilocked的逻辑如下: 拿到线程后,接下来就是binder_ioctl_write_read: 这儿就是读取内容,然后解析出命令,对于我们,命令是BC_TRANSACTION, 然后调用binder_transaction进行操作: 到这里,过去servicemanager的binder流程就结束了。最后再简单看下binder_proc_transaction的内容: 介绍到这里,defaultServiceManager涉及的流程就介绍完了,最后用一个流程图总结下: 本篇介绍了下servicemanager proxy的获取流程,涉及了ProcessState(进程单例), IPCThreadState(线程单例)。 binder驱动的open,mmap,ioctl部分。该流程比起其他调用流程稍微简单一些,不过对于熟悉binder 工作流程还是很有帮助的。2023-06-17 14:59:311
bindervd23如何调温度
1、按显示屏下方第四个按钮一次。2、通过第二三个按钮,既上下键调整温度。3、再按一次第四个按钮确认温度。4、通过第二三个按钮,既上下键,设置开关状态为000。5、再次点击第四个按钮确认。6、调整安全控制器至适宜位置。7、加热灯亮,仪器开始加热至设置温度,然后进入保温状态。BinderVD23系列真空干燥箱是具有安全保护性能的真空干燥箱,采用了的APT.LineTM扩展搁架技术,确保了干燥技术的精确温度调节及内腔温度分布的均衡、稳定,从而为设备的有效性提供了基本保障。2023-06-17 14:59:411
Android系统中的底层协议是如何实现的
Android系统底层协议解析作为目前全球最为广泛使用的移动操作系统之一,Android系统的位置不言自明。无论是在日常生活中,还是在商业领域中,都可以感受到Android系统带来的便利和创造力。而其中非常重要的一环便是Android系统的底层协议。Android系统的底层协议指的是一套能够实现系统内部数据传输和协调的规则和标准。它是由Android系统架构的各组件和级别之间形成的通信桥梁,能够促进系统之间的信息互换和共享。其中,Android系统最为重要的两个协议是:Binder和Socket。Binder协议是一种混合式IPC协议,它是Android系统中间件中最为重要的通信机制。在Binder机制的实现中,服务端通过LocalBinder和客户端通过Stub与代理Binder通信,最终可以在各个进程之间强制调用服务。Binder机制的运作原理主要是通过一个Binder对象,完成了在客户端和服务端之间的数据交换,无需开发人员自己实现IPC功能。它可以通过进程间通信(IPC)将进程之间的内存空间进行共享,使进程可以直接共享内存数据,而无需通过缓存提供一组抽象的接口。Socket协议则是介于应用层和传输层的传输层协议,它是一种电子管通信的方式,是安卓系统网络通讯的一种方式。Socket协议支持TCP/IP和UDP/IP等主流通信协议,具有稳定,可靠,通用性强等优点,也因此成为了Android系统中最为重要的一种通信机制。总的来说,Android系统的底层协议对于整个系统运行和通信起到了非常重要的作用。它们可以促进各组件之间的互动,使得系统的运作可以更加稳定快捷。因此,在设计移动应用程序的过程中,必须考虑到Android系统的底层协议,从而使程序在运行中更多情况下能够顺利完成各个层次的数据处理和传输。最终达到用户所期望的可靠性和效率。2023-06-17 14:59:491
Android Framework
Android Framework包含三个内容:服务端、客户端、linux驱动 Android Framework服务端包括两个很重要的类:WindowManagerService (WMS)、ActivityManagerService(AMS) 客户端包含以下类: Linux驱动和Framework相关的主要两个部分:画家SurfaceFlingeer和快递员Binder 每一个窗口都对应一个画Surface,SF主要是把各个surface显示到同一个屏幕,Binder则提供跨进程间的消息传递 从APK程序的运行过程中看,各个组件都在什么时候干什么样的活: ActivityThread从main()函数中就开始动起来,然后调用PrepareMainLooper()为UI线程创建一个消息快递通道即MessageQueue(), 接着创建ActivityThread对象,创建过程会创建一个消息装卸工Handler对象和一个快递员Binder对象,其中Binder负责接收远程Ams的IPC调用,接收到调用后让Handler把消息装到消息队列,UI线程很忙的都是异步的从消息队列中取出消息并执行相应的操作,比如start,stop、pause 然后UI线程让队列调用Looper.loop()方法进入消息循环体,进入后就会不断的从消息队列中读取并处理消息 当ActivityThread接收到Ams发送start某个Activity的快递后就会创建指定的Activity对象。Activity会先按窗户再去按玻璃和贴窗花,所以先创建PhoneWindow->DecorView->创建相应的View或ViewGroup。创建完成后就可以让大家欣赏了,调用WindowManager把界面显示到屏幕上,然后创建ViewRoot,然后调用Wms提供的远程接口添加一个窗口并显示到屏幕上。 接下来就是用户的操作,事件线程不断的把消息快递发到事件队列中去,然后事件分发线程秘书逐个取出消息,然后调用Wms中的相应函数处理该消息。 2.UI线程是什么? 一直在倾听用户的心声,所有的处理用户消息,以及绘制页面的工作都在该线程中完成2023-06-17 15:00:101
Android bind通信对性能影响
您好,您是想问Android bind通信对性能有什么影响事吗?为什么要使用Binder性能。主要影响的因素是拷贝次数:管道、消息队列、Socket的拷贝次书都是两次,性能不是很好;共享内存不需要拷贝,性能最好;Binder拷贝1次,性能仅次于共享内存;Linux 下传统的进程间通信原理与不足。内核程序在内核空间分配内存并开辟一块内核缓存区,发送进程通过copy_from_user函数将数据拷贝到到内核空间的缓冲区中。同样的,接收进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用 copy_to_user() 函数将数据从内核缓存区拷贝到接收进程。这样数据发送进程和数据接收进程完成了一次数据传输,也就是一次进程间通信;其有两点不足之处:一次数据传递需要经历:用户空间 _> 内核缓存区 _> 用户空间,需要2次数据拷贝,效率不高。接收数据的缓存区由数据接收进程提供,但是接收进程并不知道需要多大的空间来存放将要传递过来的数据,因此只能开辟尽可能大的内存空间或者先调用API接收消息头来获取消息体的大小,浪费了空间或者时间。Binder更加稳定和安全。Binder是基于C/S架构的,技术上已经很成熟,稳定;共享内存没有分层,难以控制,并发同步访问临界资源时,可能还会产生死锁;从稳定性的角度讲,Binder是优于共享内存的。Android是一个开源的系统,并且拥有开放性的平台,市场上应用来源很广,因此安全性对于Android 平台而言极其重要。 传统的IPC接收方无法获得对方可靠的进程用户ID/进程ID(UID/PID),无法鉴别对方身份。Android 为每个安装好的APP分配了自己的UID, 通过进程的UID来鉴别进程身份。另外,Android系统中的Server端会判断UID/PID是否满足访问权限,而对外只暴露Client端,加强了系统的安全性。2023-06-17 15:00:211
请问android进程的binder线程数量有限制吗?
在控制AndroidManifest.xml里面 android:syncable="false" android:multiprocess="false"2023-06-17 15:00:282
什么是IBinder
首先要明白,Android的远程调用(就是跨进程调用)就是通过IBinder实现的,下面是对android开发文档的翻译。IBinder是远程对象的基本接口,是为高性能而设计的轻量级远程调用机制的核心部分。但它不仅用于远程调用,也用于进程内调用。这个接口定义了与远程对象交互的协议。不要直接实现这个接口,而应该从Binder派生。IBinder的主要API是transact(),与它对应另一方法是Binder.onTransact()。第一个方法使你可以向远端的IBinder对象发送发出调用,第二个方法使你自己的远程对象能够响应接收到的调用。IBinder的API都是同步执行的,比如transact()直到对方的Binder.onTransact()方法调用完成后才返回。调用发生在进程内时无疑是这样的,而在进程间时,在IPC的帮助下,也是同样的效果。通过transact()发送的数据是Parcel,Parcel是一种一般的缓冲区,除了有数据外还带有一些描述它内容的元数据。元数据用于管理IBinder对象的引用,这样就能在缓冲区从一个进程移动到另一个进程时保存这些引用。这样就保证了当一个IBinder被写入到Parcel并发送到另一个进程中,如果另一个进程把同一个IBinder的引用回发到原来的进程,那么这个原来的进程就能接收到发出的那个IBinder的引用。这种机制使IBinder和Binder像唯一标志符那样在进程间管理。系统为每个进程维护一个存放交互线程的线程池。这些交互线程用于派送所有从另外进程发来的IPC调用。例如:当一个IPC从进程A发到进程B,A中那个发出调用的线程(这个应该不在线程池中)就阻塞在transact()中了。进程B中的交互线程池中的一个线程接收了这个调用,它调用Binder.onTransact(),完成后用一个Parcel来做为结果返回。然后进程A中的那个等待的线程在收到返回的Parcel后得以继续执行。实际上,另一个进程看起来就像是当前进程的一个线程,但不是当前进程创建的。Binder机制还支持进程间的递归调用。例如,进程A执行自己的IBinder的transact()调用进程B的Binder,而进程B在其Binder.onTransact()中又用transact()向进程A发起调用,那么进程A在等待它发出的调用返回的同时,还会用Binder.onTransact()响应进程B的transact()。总之Binder造成的结果就是让我们感觉到跨进程的调用与进程内的调用没什么区别。当操作远程对象时,你经常需要查看它们是否有效,有三种方法可以使用:1 transact()方法将在IBinder所在的进程不存在时抛出RemoteException异常。2 如果目标进程不存在,那么调用pingBinder()时返回false。3 可以用linkToDeath()方法向IBinder注册一个IBinder.DeathRecipient,在IBinder代表的进程退出时被调用。要实现IBinder来支持远程调用,应从Binder类派生一个类。Binder实现了IBinder接口。但是一般不需要直接实现此类,而是跟据你的需要由开发包中的工具生成,这个工具叫AIDL。你通过AIDL语言定义远程对象的方法,然后用AIDL工具生成Binder的派生类,然后就可使用之。然而,可是,但是,当然,你也可以直接从Binder类派生以实现自定义的RPC调用,或只是实例化一个原始的Binder对象直接作为进程间共享的令牌来使用。2023-06-17 15:00:351
各种文件夹的英文名(比如binder)
documentory container2023-06-17 15:00:441
vehicle binder是什么意思?
车辆活页夹2023-06-17 15:01:043
Binder-free什么意思
无粘合剂的2023-06-17 15:01:252
RachelBinder是哪里人
RachelBinderRachelBinder是一名演员,主要作品有《摩尔·弗兰德斯》、《美女与野兽》等。外文名:RachelBinder职业:演员代表作品:《摩尔·弗兰德斯》合作人物:肯·罗素2023-06-17 15:01:321