很多BAT也不一定能懂的binder机制!
我同事从小米跳槽过来,干安卓framework层10年,是小米的专家级别
然后他把binder驱动层全部和我讲解了一遍,然后我这边做个笔记分享给大家。
因为搞懂binder需要会c,linux内核知识。看java根本就看不懂!
分4篇文字讲解:
01. Android Binder图解 小米系统专家 解析Service 的addService注册过程 (安卓12)
02. Android Binder图解 小米系统专家 解析 ServiceManager和binder通信 (安卓12)
03. Android Binder图解 小米系统专家 解析binder驱动层解析binder通信过程 (安卓12)
04. Android Binder图解 小米系统专家 从binder java层解析binder整个流程(安卓12)
binder包含4部分:我将Binder机制分为了Java Binder、Native Binder、Kernel Binder,
一句话总结:把service服务通过binder驱动添加到serverManager的过程
系统源码位置:
/frameworks/av/media/mediaserver/main_mediaserver.cpp
/frameworks/native/libs/binder/ProcessState.cpp
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
/frameworks/native/libs/binder/IServiceManager.cpp
/frameworks/native/include/binder/IInterface.h
/frameworks/native/libs/binder/IServiceManager.cpp
/frameworks/native/libs/binder/Binder.cpp
/frameworks/native/libs/binder/IPCThreadState.cpp
一. MediaPlayerService是怎么创建的
media进程是init进程解析init.rc开启的
Media 进程是由
init 进程通过解析 init.rc 文件而创建的。
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
二:我们先来看MediaServer的入口函数,代码如下所示。
/frameworks/av/media/mediaserver/main_mediaserver.cpp
**
int main(int argc __unused, char argv __unused)
{
signal(SIGPIPE, SIG_IGN);
//获取ProcessState实例
spproc(ProcessState::self());
spsm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
InitializeIcuOrDie();
//注册MediaPlayerService
MediaPlayerService::instantiate();//1
ResourceManagerService::instantiate();
registerExtensions();
//启动Binder线程池
ProcessState::self()->startThreadPool();
//当前线程加入到线程池
IPCThreadState::self()->joinThreadPool(); }
ProcesState源码的关键:
打开binder驱动
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR);
if (fd >= 0) {
//设置驱动层的最大线程数;调用的时binder_ioctl()方法;
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
} else {
ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
三. 添加defaultServiceManager()
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService,());
}
四:传递数据
frameworks/native/libs/binder/IServiceManager.cpp
virtual status_t addService(const String16& name, const sp& service,
bool allowIsolated, int dumpsysPriority) {
Parcel data, reply;//数据包
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name); //name值为"media.player"
data.writeStrongBinder(service); //service值为MediaPlayerService
data.writeInt32(allowIsolated ? 1 : 0);
data.writeInt32(dumpsysPriority);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);//1
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
然后传给BpBinder的transact函数,代码如下所示。
frameworks/native/libs/binder/BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
BpBinder类通过IPCThreadState类来与Binder驱动交互
BpBinder将逻辑处理交给IPCThreadState
IPCThreadState* IPCThreadState::self()
{
//首次进来gHaveTLS的值为false
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;//1
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);//2
if (st) return st;
return new IPCThreadState;//3
}
...
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
IPCThreadState的transact函数。
在内存中创建一个Binder节点,将自己置为0号节点,这里的handle 值为 0 代表是 ServiceManager 进程
- Binder驱动在内核空间中为传输的Binder实体对象创建对应的Binder节点
frameworks/native/libs/binder/IPCThreadState.cpp
*```
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel reply, uint32_t flags)
{
status_t err;
flags |= TF_ACCEPT_FDS;
...
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);//1
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
...
if (reply) {
err = waitForResponse(reply);//2
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
...
} else {
//不需要等待reply的分支
err = waitForResponse(NULL, NULL);
}
return err;
}
**总结:
1.addService函数将数据打包发送给BpBinder来进行处理。
2.BpBinder新建一个IPCThreadState对象,并将通信的任务交给IPCThreadState。
3.IPCThreadState的writeTransactionData函数用于将命令协议和数据写入到mOut中。
4.IPCThreadState的waitForResponse函数主要做了两件事,一件事是通过ioctl函数操作mOut和mIn来与Binder驱动进行数据交互,另一件事是处理各种命令协议。**
**open 是打开驱动、mmap 是映射驱动、ioctl 是操作驱动、close 是关闭驱动,
分别对应驱动层的 binder_open、binder_mmap、binder_ioctl 和 binder_colse 方法
最终通过ioctl函数和Binder驱动进行通信,最后是交给了binder 驱动的 ioctl 方法,这一部分涉及到Kernel Binder的内容**
面试常问的问题:
问题:请问****MediaPlayerService****所在的进程,如何和binder驱动通信的?(重点)
MediaPlayerService是如何注册的。通过了解MediaPlayerService是如何注册的,可以得知系统服务的注册过程
我的理解:
1).打开binder驱动
2). 把对应的参数,封装成bpbinder序列化的对象,交给binder驱动
打开/dev/binder设备,这样的话就相当于和内核binder机制有了交互的通道
l 映射fd到内存,设备的fd传进去后,估计这块内存是和binder设备共享的
binder_ioctl()
问题:MediaPlayerService和servermanager是不同进程,如何通信的?
通过binder驱动。内核,内存映射关系。
————————————————
问题:bpbinder有什么作用?
Bn 是Binder Native的含义,是和Bp相对的,Bp的p是proxy代理的意思,那么另一端一定有一个和代理打交道的东西,这个就是Bn。
讲到这里会有点乱喔。先分析下,到目前为止都构造出来了什么。
l BpServiceManager
l BnMediaPlayerService
数据流向:
具体的数据有 interfaceToken(远程服务的名称)、handle(远程服务的句柄)、cookie(本地服务的地址),
有两个结构体 flat_binder_object 和 binder_write_read。
问题:Media 服务是如何添加到servermanager中的?
1).Media 进程是由 init 进程通过解析 init.rc 文件而创建的。
2). 最后是交给了binder 驱动的 ioctl 方法
问题:binder进程是在哪里启动的?
我们知道Zygote进程会调用AndroidRuntime::startReg函数注册一系列的JNI函数,而这其中就包括我们的Android Framework层的Binder框架层相关的JNI,此时就标志着Framework层BInder框架的启动,而不是到了system_server进程才开始启动的
!