1.一文分析Binder机制和AIDL的核心核心理解
2.AndroidFramework ä¹å¯å¨ ServiceManager
3.深度分析Binder线程池的启动流程
4.一文总结Android系统服务大管家-ServiceManager
5.Android进程间通信之bindService篇
6.Android Binder Hookçå®ç°
一文分析Binder机制和AIDL的理解
理解Android进程间通信的关键在于Binder机制,这是源码源代Android系统用于不同进程间交互的基础。不理解此机制,核心核心阅读源码时会面临诸多困难,源码源代难以把握系统深层次的核心核心逻辑与实现。尤其在遇到复杂问题时,源码源代源码法码补码深入理解进程间通信原理至关重要。核心核心
Binder机制的源码源代引入主要是为了弥补Linux进程中其他通信方式在性能与安全性方面的不足。尽管Binder并非Android的核心核心原创技术,其源自更早的源码源代OpenBinder项目,但它已经成为Android进程间通信的核心核心核心手段。Binder机制通过代理对象实现进程间的源码源代数据交换,确保跨进程操作的核心核心高效与安全。
在Android中,源码源代Binder代理是核心核心进程间通信的桥梁。当两个应用或进程需要交互时,它们之间不能直接通信,而必须通过Binder实现。同样,应用调用系统服务时,也需通过Binder进行跨进程通信。常见的系统服务如ActivityManagerService(AMS)、WIFI、定位、媒体服务等,都需要通过Binder机制与应用进程交换信息。
Binder本身是strncmp函数源码一个实现IBinder接口的Java类,它并非底层驱动,而是Android系统各层通信代码的集合。要理解Binder机制,需要从底层驱动到应用层逐步剖析,耐心分析其代码结构。
理解AIDL的关键在于其如何简化进程间通信的复杂性。尽管AIDL与实现进程间通信无关,它通过生成的代码模板减少了开发者的负担,降低了出错概率。通过对比使用AIDL与不使用AIDL实现的进程间通信代码,可以更清晰地理解AIDL生成的类是如何构建客户端与服务端之间的桥梁。
实现进程间通信的示例代码展示了一个简单的客户端和服务端应用。在不使用AIDL的情况下,客户端通过直接调用IBinder对象的transact方法实现通信,这直接展示了Binder通信的核心逻辑。而在使用AIDL的情况下,客户端与服务端通过生成的类实现通信,AIDL生成的Stub类与Proxy类简化了这一过程,使得客户端更容易地与服务端交互,而服务端通过实现Stub类中的方法处理通信请求。
总结来说,理解AIDL是为了更高效、更简洁地实现进程间通信,而Binder机制则是Android系统实现这一目标的核心技术。通过深入理解这两个组件,开发者可以更有效地与系统交互,wordpress 源码 解读提升应用的性能与稳定性。
AndroidFramework ä¹å¯å¨ ServiceManager
æ¬ææºç åºäº Android ï¼æ¶åç¸å ³æºç å¦ä¸ãServiceManagaer æ¯ Binder çå®æ¤è¿ç¨ï¼å¨ Binder æºå¶ä¸èµ·çéè¦çä½ç¨ãæ¬æå°ä»æºç çè§åº¦å¯¹å ¶è¿è¡åæï¼æ´ä½æµç¨å¦ä¸ï¼
æ¶åºå¾å¦ä¸ã
å æ¥çç ServiceManager æ¯å¦ä½å¯å¨çï¼
å¨ Zygote ä¸æä¸è¯´è¿ï¼ init è¿ç¨å¯å¨ç第äºé¶æ®µä¼è§£æ init.rc æ件ã
å¨è¿ä¹åä¼è§¦å trigger init ã
ç»å init.rc çç action init åäºä»ä¹ã
å½è§¦å trigger init åï¼ä¼å¯å¨ servicemanager æå¡ï¼å ¶å£°æå¦ä¸ã
对åºçæ§è¡æ件为 /system/bin/servicemanager ï¼å¨ç¼è¯åä½äº frameworks/native/cmds/servicemanager ä¸ï¼æ¥çç Android.bp ã
å ¶å¯¹åºçæºç 为 service_manager.c å binder.c ï¼å ¥å£å½æ° main() ä½äº servicemanager.c ã
å¯å¨å® ServiceManager åä¼æå¼ Binder 驱å¨ã
å¨ main() ä¸é¦å è°ç¨ binder_open() ã
binder_open() 主è¦åäºå¦ä¸äºæ ï¼
ç»ç»æä½ binder_state åé å åã
ç³»ç»è°ç¨ open() æå¼ /dev/binder ï¼å¦ææå¼é©±å¨å¤±è´¥ï¼åæ§è¡ fail_open éæ¾å åã
ç®åç解éä¸ä¸ä»ä¹æ¯ç³»ç»è°ç¨ï¼
ç±äºéè¦éå¶ä¸åçç¨åºä¹é´ç访é®è½åï¼é²æ¢ç¨åºè·åå«çç¨åºçå åæ°æ®ï¼ CPU åååºä¸¤ä¸ªæéç级ï¼ç¨æ·æå å æ ¸æã
ææçç¨æ·ç¨åºé½æ¯è¿è¡å¨ç¨æ·æï¼ä½ææ¶éè¦åä¸äºå æ ¸æçäºæ ï¼èå¯ä¸å¯ä»¥åè¿äºäºæ çå°±æ¯æä½ç³»ç»ï¼æ以ç¨åºéè¦åæä½ç³»ç»å起请æ±ï¼ä»¥ç¨åºçååæ¥æ§è¡è¿äºæä½ãè¿æ¶å°±éè¦ä¸ä¸ªä»ç¨æ·æåæ¢å°å æ ¸æä½ä¸è½æ§å¶å æ ¸æä¸æ§è¡çæºå¶ï¼è¿ç§æºå¶å°±æ¯ ç³»ç»è°ç¨ã
ç³»ç»è°ç¨ ioctl() ä¼ å ¥ BINDER_VERSION å½ä»¤è·å Binder 驱å¨çæ¬ï¼å¯¹æ¯çæ¬æ¯å¦ä¸è´ï¼ä¸ä¸è´åæ§è¡ fail_open éæ¾å åã
ç³»ç»è°ç¨ mmap() æ å° kb çå å空é´ï¼å³æ Binder 驱å¨æ件ç kb æ å°å°å å空é´ä¾ ServiceManager 使ç¨ï¼å åæ å°å¤±è´¥åæ§è¡ fail_map ï¼å ³é fd 并éæ¾å åã
ServiceManager è¿ç¨ mmap çå å大å°å¯ä»¥éè¿ adb shell å½ä»¤æ¥çã
å¯ä»¥çå°å åæ å°å°å为 0xff ~ 0xf ï¼å·®ä¸º 0x å³åè¿å¶ç kb ã
æå¼ Binder 驱å¨åä¼å° ServiceManager 设置为ä¸ä¸æ管çè ã
è°ç¨ binder_become_context_manager() ã
android æ°å¢ BINDER_SET_CONTEXT_MGR_EXT å½ä»¤æ¥è®¾ç½®å®å ¨çä¸ä¸æ管çè ï¼å¦æ设置失败ï¼å使ç¨åæç BINDER_SET_CONTEXT_MGR å½ä»¤æ¥è®¾ç½®ä¸ä¸æ管çè ï¼ä¸¤è åºå«å¨äºæ¯å¦æºå¸¦åæ°ã
æåä¼è¿å ¥å¾ªç¯ï¼ä» Binder 驱å¨è¯»åå解ææ°æ®ã
è°ç¨ binder_loop() è¿å ¥å¾ªç¯ï¼ä¸æå°éè¿ç³»ç»è°ç¨ ioctl() ä» Binder 驱å¨è¯»åæ°æ®ï¼å¹¶éè¿ binder_parse() è¿è¡æ°æ®è§£æã
注æè¿éè°ç¨ binder_loop() ä¼ å ¥ç svcmgr_handler() ï¼åé¢ä¼ä½¿ç¨å°ã
binder_write() ä¼å°è£ struct binder_write_read ï¼å¹¶éè¿ç³»ç»è°ç¨ ioctl() å°å¯¹åºçå½ä»¤ä¼ éç» Binder 驱å¨ã
binder_parse() ç¨æ¥è§£æä» Binder 驱å¨è¯»åå°çæ°æ®ï¼ç¶åæ ¹æ®ä¸åçå½ä»¤æ§è¡å¯¹åºçæä½ã
å 为 cmd å½ä»¤å¯è½æå¤ä¸ªï¼æ以éè¿ while 循ç¯æ¯æ¬¡å¤çä¸ä¸ª cmd å½ä»¤ï¼å¤ cmd çç»æ大è´å¦ä¸å¾æ示ã
è¿ééç¹çä¸ BR_TRANSACTION å½ä»¤ã
BR_TRANSACTION æ¯ Binder 驱å¨å Server 端åé请æ±æ°æ®ã
binder_transaction_data çç»æå¦ä¸ï¼å ¶è¡¨æäº transcation ä¼ è¾çå ·ä½è¯ä¹ï¼è¯ä¹ç è®°å½å¨ code ä¸ï¼ä¸åè¯ä¹ç æºå¸¦çæ°æ®æ¯ä¸åçï¼è¿äºæ°æ®ç± data æå®ã
å¨è§£æå® binder_transaction_data çå ·ä½è¯ä¹åï¼ä¼è°ç¨åé¢ä¼ ç» binder_loop() ç svcmgr_handler() ï¼å ¶å®å°±æ¯ switch case è¯ä¹ç åä¸åçäºæ ã
ServiceManager çåè½å ¶å®å¾ç®åï¼
è³æ¤ ServiceManager å°±åæå®äºã
深度分析Binder线程池的启动流程
理论基础Binder
Binder它是Android中的一种进程间通信机制,它主要采用的是CS架构模式。Binder框架中主要涉及到4个角色Client、Server、ServiceManager及Binder驱动,其中Client、Server、ServiceManager运行在用户空间,Binder驱动运行在内核空间。
线程池线程池它是一种用于多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。
简单的说:线程池就是创建一些线程,它们的集合称为线程池。
Binder线程池启动流程我们知道一个新的app应用程序进程在创建完成之后,它会通过调用RunTimeInit类的静态成员函数zygoteInitNative来进行启动Binder线程池。
Binder线程池启动过程中,主要调用几个关键函数:ZygoteInitNative--->onZygoteInit--->startThreadPool。
下面的源码分析主要是以android5.0版本为例。
ZygoteInitNative源码分析由于ZygoteInitNative函数是java实现的代码,实践上最终调用的球投注源码是由C++实现的JNI方法。以下代码来源于系统的/frameworks/base/core/jni/androidRuntime.cpp文件中
staticvoidcom_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv*env,jobjectclazz){ //gCurRuntime是个全局的变量,后面跟上的是另外实现的方法。gCurRuntime->onZygoteInit();}onZygoteInit源码分析onZygoteInit函数在需要源码的位置:/frameworks/base/cmds/app_process/app_main.cpp文件中。
该函数是个虚函数,并且是一个无返回值和无参数的函数virtualvoidonZygoteInit(){ //Re-enabletracingnowthatwe'renolongerinZygote.atrace_set_tracing_enabled(true);//获取进程的状态信息sp<ProcessState>proc=ProcessState::self();//打印日志信息ALOGV("Appprocess:startingthreadpool.\n");//启动线程池proc->startThreadPool();}startThreadPool源码分析startThreadPool系统实现在\frameworks\native\libs\binder\ProcessState.cpp文件中。
每一个支持Binder进程间通信机制的进程内都有一个唯一的ProcessState对象,当这个ProcessState对象的成员函数StartThreadPool函数被第一次调用的时候,它就会在当前进程中启动一个线程池,并将mThreadPoolStarted这个成员变量设置为true。
//该函数是个无参数,无返回值的函数voidProcessState::startThreadPool(){ AutoMutex_l(mLock);//判断线程池是否启动状态,启动的话就将标志信息设置为true属性。if(!mThreadPoolStarted){ mThreadPoolStarted=true;spawnPooledThread(true);}}总结Binder在android底层中是一个非常重要的机制,我们在实际的项目调用过程中,我们在app应用程序中只要实现自己的Binder本地对象的时候,跟其他服务一样,只需要将它进行启动起来,并且进行注册到ServerMananger就可以了。至于内部的实现一般是不需要去关心的。
一文总结Android系统服务大管家-ServiceManager
本文以源码文件为切入点,旨在解析Android系统服务大管家 - ServiceManager的具体运作。首先介绍ServiceManager简介,定义了其为C/C++编写的系统服务,并说明其源码位于/framework/native/cmds/servicemanager,通过Android.bp文件明确,该服务以程序方式构建,leap motion源码启动入口位于main.cpp的main()函数。运行期间,ServiceManager将不断执行looper->pollAll(-1)操作,并默认依托于设备节点/dev/binder,同时也允许通过参数设置自定义节点。ServiceManager作为binder机制的核心组件,负责实现进程间通信。
文章接下来指出在Android.bp文件中,ServiceManager对应程序名为servicemanager,同样存在vndservicemanager程序。两者的源码一致,主要差异在于rc文件,vndservicemanager通过/dev/vndbinder作为binder驱动。在Android启动时,vndservicemanager和servicemanager都被init拉起,它们的功能区别体现在如何指定binder驱动路径。
文章深入探讨ServiceManager的启动过程。首先介绍init进程由内核管理,该进程在启动时,依据init.rc文件拉起关键服务进程,其中包括ServiceManager。在特定目录下(/framework/native/cmds/servicemanager/),存在servicemanager.rc文件,这是servicemanager初始化的配置文件。
进入ServiceManager详细剖析阶段。主要步骤包括获取驱动名称、初始化进程状态、创建ServiceManager实例、设置上下文对象、创建并启动looper,并执行pollAll操作。其中获取驱动名称步骤依据命令行参数或默认采用/dev/binder。初始化进程状态涉及调用initWithDriver()设置libbinder支持特定驱动,同时为进程配置参数。创建ServiceManager实例并作为上下文对象,随后创建并启动looper,执行pollAll(-1)完成核心服务功能实现。
文章最后指出ServiceManager的唤醒时机,通常发生在系统启动、服务注册、通信调用等场景。在Android系统中,ServiceManager的作用主要为实现应用程序与系统组件之间通过Binder机制的跨进程通信,访问和管理系统级服务,从而提供丰富的功能扩展性和灵活性。
Android进程间通信之bindService篇
在Android的进程间通信中,binder是一种核心机制,广泛应用于四大组件之一的Service。本文专注于使用Service与binder结合的bindservice通信方式,探讨其实现方法与关键特性。
创建Service作为服务端,其主要功能是向客户端提供接口。创建Service的方式包括扩展binder类、使用Messenger和AIDL。扩展binder类适用于服务端与客户端在同进程场景,不具备跨进程能力,因此这里不详细说明。使用Messenger能实现跨进程通信,特点是请求放入队列,服务端无需线程安全设计,但在实际项目中使用较少。
AIDL(Android Interface Definition Language)是一种便捷实现跨进程通信的工具。它支持客户端并发访问,要求服务端实现线程安全设计。创建.aidl文件定义接口,服务端和客户端均需包含源码。实现AIDL接口的实例在onBind()接口返回给客户端,使得客户端能调用接口。
使用AIDL的关键技术点在于通过IPC调用传递对象。支持Java语言原语类型、String、CharSequence、List和Map等数据类型传递。对于自定义对象,必须实现Parcelable接口,以完成序列化。在Android 及以上版本中,可直接定义Parcelable对象。AIDL工具在编译时协助生成序列化代码。
在方法中使用Bundle参数时,需在解析前显式设置ClassLoader。这样能确保Bundle中对象正确加载。
本文总结了使用binder和bindservice实现Java端与Java端跨进程通信的方式,并简单概述了AIDL工具的关键技术点。使用bindservice结合AIDL,能在多个场景下有效实现Java应用之间的高效通信。
Android Binder Hookçå®ç°
Binder Hook å¯ä»¥ Hook æå½åè¿ç¨ç¨å°çç³»ç» Service æå¡ã以 LocationManager 为ä¾ï¼å¨è·åä¸ä¸ª LocationManager æ¶å为两æ¥ï¼
(1) è·å IBinder 对象ï¼
(2) éè¿ IBinder ç asInterface() æ¹æ³è½¬å为 LocationMangerService 对象ï¼æ¥çåå§å LocationManager ã
application å±ç¨å°çé½æ¯ LocationManager 对象ã
åçï¼
æ´ä¸ªè¿ç¨éè¦å©ç¨åå°è®¾ç½®ä¸ä¸ªèªå®ä¹ç Binder 对象åä¸ä¸ªèªå®ä¹ç Service 对象ãç±äºæä»¬åª Hook å ¶ä¸ä¸é¨åçåè½ï¼å ¶ä»åè½è¿éè¦ä¿çï¼æ以è¦ç¨å¨æ代ççæ¹å¼å建èªå®ä¹å¯¹è±¡ã
å¨ç解åé¢çå 容åä½ éè¦äºè§£è¿äºç¥è¯ç¹ï¼
Activity çç±»å¨è·åç³»ç» Service æ¶ï¼é½æ¯è°ç¨ getSystemService(serviceName) æ¹æ³è·åçã
Context # getSystemService() æ¹æ³æç»ä¼è°ç¨å° ServiceManager # getService() æ¹æ³ä¸ã以 LocationManager 对åºç ServiceFetcher 为ä¾ï¼å®ç createService() æ¹æ³æºç å¦ä¸ï¼
åå¦æä»¬è¦ Hook æ LocationManager # getLastKnownLocation() æ¹æ³ï¼ä¸æé½æ¯ï¼ãæ们è¦åçå°±æ¯è®©
ServiceManager.getService(Context.LOCATION_SERVICE) è¿åæ们èªå®ä¹ç Binder 对象ã
å çä¸ä¸è¿ä¸ªæ¹æ³çæºç ï¼
sCache æ¯ä¸ä¸ª Mapï¼ç¼åäºå·²ç»åç³»ç»è¯·æ±è¿ç Binderãå¦æéè¦è®©è¿ä¸ªæ¹æ³è¿åæ们èªå·±ç binder 对象ï¼åªéè¦äºå å¾ sCache ä¸ put ä¸ä¸ªèªå®ä¹ç Binder 对象就è¡äºã
å¨ put ä¹åï¼éè¦å å建åºä¸ä¸ªèªå®ä¹ç Binderãè¿ä¸ª Binder å¨è¢« ILocationManager.Stub.asInterface å¤çåï¼å¯ä»¥è¿åä¸ä¸ªèªå®ä¹ç LocationManagerService 对象ã
å çä¸ä¸ Binder ç asInterface() çå®ç°ï¼
å¦ææ queryLocalInterface()æ¹æ³è¿åä¸ä¸ªèªå®ä¹çServiceï¼ä½¿å¾èµ° if è¯å¥å é¨ï¼ä¸èµ° elseï¼é£å°±ç®æ¯Hook æåäºã
å设æ们æ³è®©ç³»ç»ç LocationManager è¿åçä½ç½®ä¿¡æ¯å ¨æ¯å¨å¤©å®é¨(., .)ãé£æ们éè¦ä½¿å¾ LocatitionManagerService ç getLastLocation() æ¹æ³ è¿åçå ¨æ¯ (., .)ã
ç±äºæ们ä¸è½ç´æ¥æ¿å°ç³»ç»çè¿ä¸ªService对象ï¼å¯ä»¥å ç¨åå°çæ¹å¼æ¿å°ç³»ç»çLocationManagerServiceãç¶åæ¦æª getLastLocation() æ¹æ³ã
åççBinder对象å¨è°ç¨ queryLocalInterface() æ¹æ³æ¶ä¼è¿ååççService对象ãæ们å¸æè¿å3.1ä¸çèªå®ä¹Serviceãæ以è¿éæ¦æª queryLocalInterface() æ¹æ³ã
æäºèªå®ä¹ç Binder åï¼å°å®æ³¨å ¥å° ServiceManger ç sCache åéä¸å°±å®æ Hook äº~
å½onClick被è°ç¨çæ¶åï¼ToaståLogé½ä¼æ¾ç¤ºå¤©å®é¨çåæ (., .)ãè¯æHookæåï¼
ä½ çè³å¯ä»¥ç¨Binder Hookçæ¹å¼Hookæ ActivityManagerã
面试 | 再也不怕被问 Binder 机制了
Binder机制是Android特有的进程间通信(IPC)方式,它基于C/S架构,由运行在用户空间的Client、Server、Service Manager组件,以及运行在内核空间的Binder驱动组成。完整过程包括:通过内存映射技术减少数据拷贝次数,发送方进程也做内存映射可以实现数据0拷贝传输,但考虑到性能和复杂性,Binder方式更适合Android。
mmap内存映射原理是在进程的用户空间和内核空间之间建立映射关系,实现文件磁盘地址与进程虚拟地址空间中的虚拟地址一一对映,使得进程可以采用指针方式读写操作内存,系统自动回写脏页面到磁盘,完成文件操作而无需再调用read、write等系统调用函数。同时,内核空间对这段区域的修改直接反映用户空间,实现不同进程间的文件共享。
在进程间通信(IPC)场景下使用mmap时,通常只需要在进程的用户空间和内核空间之间建立映射关系,不一定需要映射到外部存储介质,除非希望将共享内存内容持久化到磁盘上。
当使用匿名内存映射进行进程间通信时,创建一段内核空间内存并在进程的用户空间与之建立映射关系,允许多个进程共享同一段内核空间内存,实现数据共享和同步。匿名内存映射不与任何文件关联,仅在进程间实现高效数据传输。
在使用mmap进行进程间通信时,创建匿名内存映射,不映射到外部存储介质,仅在用户空间与内核空间之间建立映射关系。这允许多个进程共享内核空间内存,提高数据访问效率和性能。
在实际应用中,使用带有回调接口(Callback)的方法参数调用服务端进程提供的方法时,方法调用线程和回调线程是否相同取决于服务端实现。通常服务端采用异步处理方式,将请求放入队列或线程池中处理,调用回调接口,线程可能不相同。
对于oneway接口调用,即使服务端立即在当前线程中处理请求并调用回调接口,客户端的调用也不会阻塞。oneway调用是单向异步的,客户端调用后立即返回,不会等待服务端响应。
Intent传递参数在同一个进程中的两个Activity间,由于涉及Binder IPC通信,Intent数据携带大小会受到Binder事务大小限制。通常限制在1MB左右,超过限制会抛出异常。解决方法包括优化数据结构、使用事件总线或回调接口传递大对象。
为了深入理解Android框架,可参考《Android Framework核心知识点》手册,内容涵盖Init、Zygote、SystemServer、Binder、Handler、AMS、PMS、Launcher等知识点,以及相关源码分析资料,帮助快速掌握Android框架核心。