Binder通讯原理
基于Android 11的源码剖析,笔记记录binder通讯原理的实现过程;
根据网络上的各路大神案例,都是从典型的mediaserver进程开始分析,binder服务的注册注册过程;
mediaserver进程启动的main函数开始分析,至于init.rc的注册启动进程就跳过了;main函数代码如下:
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
::android::hardware::joinRpcThreadpool();
}
Binder线程池的注册
每个采用 Binder 的进程会有一个或多个用于处理接收数据的线程,位于 Binder 线程池。采用 Binder 机制的进程最典型的就是应用程序进程了。那应用程序进程的 Binder 线程池是在什么时候启动的呢?
ProcessState
源码位置:frameworks/native/libs/binder/ProcessState.cpp
ProcessState 是 Binder 机制核心之一,它是 Binder 通信的基础,负责与 Binder 驱动的交互与 Binder 线程池的管理。它实现了单例模式,通过 self() 函数获取实例,每个进程仅有一个。
ProcessState 创建
实现了单例模式,通过 self() 函数获取实例。来看看它的构造函数,如下:
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
#if defined(__ANDROID_APEX__)
LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
#endif
if (mDriverFD >= 0) {
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
#ifdef __ANDROID__
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
#endif
}
ProcessState创建是主要步骤是:
- 访问binder设备,并与binder驱动交互;
- 映射binder驱动,提供通讯基础的虚拟空间;
其中提供通讯基础的虚拟空间默认大小是由BINDER_VM_SIZE 这个宏来决定的,宏定义如下:
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
下面来主要看看open_driver 函数,函数内容如下:
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
在open_driver 函数中主要处理:
-
访问binder设备,通过open函数来实现,具体现在不做详细说明; -
通过ioctl进行binder的版本比较 -
通知binder驱动binder线程池的默认最大线程数,而这个最大线程数由DEFAULT_MAX_BINDER_THREADS 宏来决定;宏定义如下:
#define DEFAULT_MAX_BINDER_THREADS 15
启动binder线程池
ProcessState 实例后调用其 startThreadPool 函数,以启动进程的 Binder 线程池。
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
mThreadPoolStarted 用于标识线程池是否已经启动过,以确保 Binder 线程池仅初始化一次。spawnPooledThread() 函数启动了一个 Binder 线程,类型为 PoolThread ,函数参数表示这是 Binder 线程池中的第一线程。
class PoolThread : public Thread
{
public:
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
PoolThread 继承Thread 类。t->run() 方法最终调用内部类 PoolThread 的threadLoop ()方法。在主要创建了IPCThreadState 和执行了IPCThreadState 的joinThreadPool 函数;
在mediaserver的main函数中后面又执行了一次IPCThreadState 的joinThreadPool 函数,这两次的区别是一个在子线程执行,一个是在进程主线程执行,**mediaserver默认binder的事件监听线程数是2吗?**这样binder线程池算基本完成!
IPCThreadState
源码位置:frameworks/native/libs/binder/IPCThreadState.cpp
IPCThreadState 同样是 Binder 机制的核心之一,它用于管理与 Binder 通信相关线程的状态,每个 Binder 线程都会通过此将自己注册到 Binder 驱动。一个具有多个线程的进程里应该会有多个IPCThreadState对象了,只不过每个线程只需一个IPCThreadState对象而已。所以要放在binder线程池中统一管理。
IPCThreadState 创建
IPCThreadState 同样是通过 self() 函数获取实例的。
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS.load(std::memory_order_acquire)) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}
if (gShutdown.load(std::memory_order_relaxed)) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return nullptr;
}
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS.load(std::memory_order_relaxed)) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return nullptr;
}
gHaveTLS.store(true, std::memory_order_release);
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
self() 函数是一个工厂函数,用于获取 IPCThreadState 实例。self() 根据 pthread_getspecific() 管理每个参与 Binder 通信线程的实例,类似Looper 里的ThreadLocal ,每个参与 Binder 通信的线程其 IPCThreadState 对象都是相互独立的,保证了后续操作的线程安全。构造函数内容其实,很简单主要是绑定线程唯一标记和初始化输入输出缓冲区;
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mServingStackPointer(nullptr),
mWorkSource(kUnsetWorkSource),
mPropagateWorkSource(false),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0),
mCallRestriction(mProcess->mCallRestriction)
{
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
IPCThreadState::joinThreadPool 函数
joinThreadPool 函数就是一个死循环,不断从驱动获取数据;
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
processPendingDerefs();
result = getAndExecuteCommand();
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
}
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n",
(void*)pthread_self(), getpid(), result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
如此看来IPCThreadState 是通过getAndExecuteCommand 来不断获取通讯数据的;
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing top-level Command: "
<< getReturnString(cmd) << endl;
}
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount++;
if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
mProcess->mStarvationStartTimeMs == 0) {
mProcess->mStarvationStartTimeMs = uptimeMillis();
}
pthread_mutex_unlock(&mProcess->mThreadCountLock);
result = executeCommand(cmd);
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount--;
if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
mProcess->mStarvationStartTimeMs != 0) {
int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
if (starvationTimeMs > 100) {
ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
mProcess->mMaxThreads, starvationTimeMs);
}
mProcess->mStarvationStartTimeMs = 0;
}
pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
return result;
}
getAndExecuteCommand 的执行步骤:
- 通过
talkWithDriver 向binder驱动获取通讯数据; - 读取命令字段,并通过
executeCommand 函数进行不同命令字段的解析和处理
获取ServiceManager
获取Service Manager是通过defaultServiceManager 方法来完成,当进程注册服务(addService)或 获取服务(getService)的过程之前,都需要先调用defaultServiceManager()方法来获取gDefaultServiceManager 对象。
大概流程图如下:
defaultServiceManager 函数代码如下:
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
while (sm == nullptr) {
sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
if (sm == nullptr) {
ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
sleep(1);
}
}
gDefaultServiceManager = new ServiceManagerShim(sm);
});
return gDefaultServiceManager;
}
ServiceManager 的对象获取也采用了一个单例模式,一个进程中只要获取一次即可,对象存储在gDefaultServiceManager 中。
主要流程如下:
- 获取
ProcessState 对象—ProcessState::self() ,在上面的流程中可知ProcessState 已获取,存入了全局变量中 - 获取
BpBinder 对象 –ProcessState::getContextObject(nullptr) - 获取
BpServiceManager 对象----interface_cast<IServiceManager> - 创建
ServiceManagerShim 对象对BpServiceManager 对象进行接管
在ProcessState::getContextObject(nullptr) 函数中,主要调用getStrongProxyForHandle 进行处理,传入handle=0,那主要看看getStrongProxyForHandle 函数;
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}
b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
getStrongProxyForHandle 的过程也很简单,当handle=0 所对应的IBinder 不存在或弱引用无效时,先看下Binder是否已经准备就绪,即ServiceManager 是否已经就绪,准备好后,创建一个BpBinder(0,trackedUid) ,创建BpBinder 对象中会将handle 相对应Binder 的弱引用增加1,最终返回一个BpBiner 的对象。
真正获取ServiceManager 的代理对象的是 interface_cast<AidlServiceManager> 方法。零号引用的 BpBinder 对象传入 interface_cast() 模版函数,会最终通过 IMPLEMENT_META_INTERFACE() 宏,生成 BpServiceManager 对象。该对象被传入 ServiceManagerShim 的构造函数中,成为其成员变量 mTheRealServiceManager 。
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\
const ::android::StaticString16 \
I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
const ::android::String16 I##INTERFACE::descriptor( \
I##INTERFACE##_descriptor_static_str16); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != nullptr) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl; \
bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\
{ \
\
\
\
assert(!I##INTERFACE::default_impl); \
if (impl) { \
I##INTERFACE::default_impl = std::move(impl); \
return true; \
} \
return false; \
} \
const std::unique_ptr<I##INTERFACE>& I##INTERFACE::getDefaultImpl() \
{ \
return I##INTERFACE::default_impl; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
Android 10在此之后,BpServiceManager 不再通过手动实现,而是采用 AIDL(文件为 IServiceManager.aidl ),生成 IServiceManager 、BnServiceManager 、BpServiceManager 的头文件及具体实现。
关于通过 AIDL 生成 C++ 代码,详见 Generating C++ Binder Interfaces with aidl-cpp
BpServiceManager 的继承关系图如下:
Binder 数据传输流程
Binder 数据发送过程
从addService 函数来分析Binder的数据传输流程;从获取servicemanage的章节我们得知,servicemanage的Client端是BpServiceManager ,那我们直接来看BpServiceManager 中的addService 函数,如下:
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
data.writeInt32(dumpsysPriority);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flattenBinder(val);
}
status_t Parcel::flattenBinder(const sp<IBinder>& binder)
{
flat_binder_object obj;
if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
} else {
obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
}
if (binder != nullptr) {
BBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == nullptr) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : 0;
obj.hdr.type = BINDER_TYPE_HANDLE;
obj.binder = 0;
obj.handle = handle;
obj.cookie = 0;
} else {
if (local->isRequestingSid()) {
obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
}
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finishFlattenBinder(binder, obj);
}
从代码分析Parcel 通过writeStrongBinder 函数把service 封装成flat_binder_object 结构体,其中保存了service 的Binder弱引用指针地址和Binder实体的指针;flat_binder_object 结构体定义如下:
struct flat_binder_object {
struct binder_object_header hdr;
__u32 flags;
union {
binder_uintptr_t binder;
__u32 handle;
};
binder_uintptr_t cookie;
};
remote()->transact() 将传出,从defaultServiceManager 分析总结remote 对应的是在getStrongProxyForHandle 函数中创建的BpBinder ;而在BpBinder 的transact 函数中,主要是执行了status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); ,接下来我们就分析一下IPCThreadState 的transact 函数;
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;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
<< handle << " / code " << TypeCode(code) << ": "
<< indent << data << dedent << endl;
}
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
ALOGE("Process making non-oneway call (code: %u) but is restricted.", code);
CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
ANDROID_LOG_ERROR);
} else {
LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code);
}
}
#if 0
if (code == 4) {
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction %d", code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
#if 0
if (code == 4) {
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d", code);
}
#endif
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
<< handle << ": ";
if (reply) alog << indent << *reply << dedent << endl;
else alog << "(none requested)" << endl;
}
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}
IPCThreadState 中有 mIn、mOut 两个 Parcel 数据,mIn 用来存放从别处读取而来的数据,mOut 存放要写入到别处的数据,而在transact 函数中关键代码只有两行(writeTransactionData 和waitForResponse ),从命名上来看就是一次请求和接收应答的过程。在 writeTransactionData 函数中将一堆参数组装进binder_transaction_data 结构体并存放到 mOut,准备写入到 binder 驱动;
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.ptr = 0;
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
}
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
binder_transaction_data 结构体在中组装的Parcel 数据:
? 图片来源
binder_transaction_data 结构体定义如下:
struct binder_transaction_data {
union {
__u32 handle;
binder_uintptr_t ptr;
} target;
binder_uintptr_t cookie;
__u32 code;
__u32 flags;
pid_t sender_pid;
uid_t sender_euid;
binder_size_t data_size;
binder_size_t offsets_size;
union {
struct {
binder_uintptr_t buffer;
binder_uintptr_t offsets;
} ptr;
__u8 buf[8];
} data;
};
waitForResponse 函数去实际执行写入到 binder 驱动,简化后的 waitForResponse 函数代码如下:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
...
}
goto finish;
case BR_REPLY:
{
...
}
goto finish;
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
可以看到 waitForResponse 中并没有直接执行写入数据到 binder,而是进一步调用 talkWithDriver 去处理,随后 waitForResponse 处理了由 binder 驱动发送过来的命令,因为在BpServiceManager 传过来的reply不等于空,所以正常的逻辑是收到BR_REPLY才退出循环;
由 transact 到 waitForResponse ,已经将要发送的数据准备好,并对后续 binder 驱动的回复也做了处理,但还没看到真正写入数据给 binder 驱动的代码,但已经知道就在 talkWithDriver 函数中,此函数中主要做了三个工作:
- 将要发送的数据封装成
binder_write_read 结构体; - 通过ioctl把
binder_write_read 结构体数据写入binder驱动; - 处理驱动回复
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD < 0) {
return -EBADF;
}
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
#if defined(__ANDROID__)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD < 0) {
err = -EBADF;
}
} while (err == -EINTR);
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
else {
mOut.setDataSize(0);
processPostWriteDerefs();
}
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
return NO_ERROR;
}
return err;
}
在IPCThreadState.h定义talkWithDriver 函数时,doReceive 的默认值为true ,waitForResponse() 中没有传入参数,所以这里的 doReceive 为 true。
status_t talkWithDriver(bool doReceive=true);
binder_write_read 是 binder 驱动与用户态共用的、存储读写操作的结构体,在 binder 驱动内部依赖 binder_write_read 决定是要读取还是写入数据:其内部变量 read_size>0 则代表要读取数据,write_size>0 代表要写入数据,若都大于 0 则先写入,后读取。binder_write_read 结构体定义如下:
struct binder_write_read {
binder_size_t write_size;
binder_size_t write_consumed;
binder_uintptr_t write_buffer;
binder_size_t read_size;
binder_size_t read_consumed;
binder_uintptr_t read_buffer;
};
这样基本完成了数据的发送过程,其中主要的数据类型结构体一定要记住,很重要;
flat_binder_object 封装service 的结构体,其中重要的参数是binder、handle、cookiebinder_transaction_data 组装Parcel 数据的结构体;binder_write_read 是binder 驱动与用户态共用的、存储读写操作的结构体
Binder 数据接收过程
Binder 线程用于在 Server 中接收处理从 Binder 驱动发送来的数据。startThreadPool 提及的函数 IPCThreadState.joinThreadPool 将自己注册到 Binder 线程池,等待接收数据。
在joinThreadPool 函数中,循环执行getAndExecuteCommand ,调用 talkWithDriver 从 mIn 窗口解析出需要执行的命令后,执行 executeCommand 。在executeCommand 的BR_TRANSACTION 分支,其中 the_context_object 为 BBinder 对象,也就是 Server 的 Binder 本体。BBinder.transact 会再调用 BBinder.onTransact 函数,实现 Server 进程 Binder 的调用。
而在ServiceManager 采用了LooperCallback 方式监听binder数据,最终也是循环执行getAndExecuteCommand ;这部分的分析会在创建ServiceManager 进程详细分析;
接收数据时也在talkWithDriver 中ioctl读写获取一个binder_write_read 结构体,在executeCommand 的BR_TRANSACTION 分支中在把数据进一步解析binder_transaction_data 结构体并将相应的输入数据转换buffer ,buffer 是Parcel 对象,在 BBinder 的onTransact 函数会在BnServiceManager 重载onTransact 函数;
status_t BnServiceManager::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case GET_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which);
reply->writeStrongBinder(b);
return NO_ERROR;
} break;
case CHECK_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = const_cast<BnServiceManager*>(this)->checkService(which);
reply->writeStrongBinder(b);
return NO_ERROR;
} break;
case ADD_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = data.readStrongBinder();
status_t err = addService(which, b);
reply->writeInt32(err);
return NO_ERROR;
} break;
case LIST_SERVICES_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
Vector<String16> list = listServices();
const size_t N = list.size();
reply->writeInt32(N);
for (size_t i=0; i<N; i++) {
reply->writeString16(list[i]);
}
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
在ADD_SERVICE_TRANSACTION 分支,会通过Parcel 的readStrongBinder 函数将数据读取flat_binder_object 结构体,再获取IBinder弱引用指针地址;其中主要执行的函数是unflattenBinder ;
status_t Parcel::unflattenBinder(sp<IBinder>* out) const
{
const flat_binder_object* flat = readObject(false);
if (flat) {
switch (flat->hdr.type) {
case BINDER_TYPE_BINDER: {
sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
return finishUnflattenBinder(binder, out);
}
case BINDER_TYPE_HANDLE: {
sp<IBinder> binder =
ProcessState::self()->getStrongProxyForHandle(flat->handle);
return finishUnflattenBinder(binder, out);
}
}
}
return BAD_TYPE;
}
最后会调用ServiceManager 的addService 函数;
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
auto ctx = mAccess->getCallingContext();
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
return Status::fromExceptionCode(Status::EX_SECURITY);
}
if (!mAccess->canAdd(ctx, name)) {
return Status::fromExceptionCode(Status::EX_SECURITY);
}
if (binder == nullptr) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
if (!isValidServiceName(name)) {
LOG(ERROR) << "Invalid service name: " << name;
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
LOG(ERROR) << "Could not linkToDeath when adding " << name;
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}
auto entry = mNameToService.emplace(name, Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
});
auto it = mNameToRegistrationCallback.find(name);
if (it != mNameToRegistrationCallback.end()) {
for (const sp<IServiceCallback>& cb : it->second) {
entry.first->second.guaranteeClient = true;
cb->onRegistration(name, binder);
}
}
return Status::ok();
}
addService 函数中主要执行的是将Ibinder对象封装成Service 结构体,并于name 为key插入mNameToService 中,而mNameToService 是一个std::map<std::string, Service> ;这样addService 在除了内核部分的代码算是基本完成;binder驱动中的数据传递会在binder驱动分析中进行解析;
数据传递过程如下:
ServiceManager 进程创建
启动的main 函数在frameworks/native/cmds/servicemanager/main.cpp 中,其中关键步骤和media进行类型;
- 创建
ProcessState ,ServiceManager 进程没有调用self ,而是通过initWithDriver 创建,其实关键代码还是一样的,实现了单例模式,通过initWithDriver 获取实例;并通过setThreadPoolMaxThreadCount 设置最大线程数为0; - 创建
ServiceManager 实例,同样使用addService 函数同样把ServiceManager 插入mNameToService 中;并创建IPCThreadState 实通过setTheContextObject 设置the_context_object为ServiceManager ; - 通过
ProcessState 的becomeContextManager 函数设置ServiceManager 进程为binder驱动的上下文管理者; - 通过
Looper::prepare 创建Looper ,Looper 也是和IPCThreadState 一样线程单例,这里可以理解成是java中handle 事件中的looper ,后续会再对native层的Looper 进行详细分析;并BinderCallback 的setupTo 注册Looper 的事件监听和ClientCallbackCallback 的setupTo 注册Looper 的事件; - 进入死循环,调用
looper->pollAll 函数,实则是在epoll_wait 等待消息;
int main(int argc, char** argv) {
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
if (!manager->addService("manager", manager, false , IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager(nullptr, nullptr);
sp<Looper> looper = Looper::prepare(false );
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);
}
return EXIT_FAILURE;
}
再BinderCallback 中如果有事件返回会回调handleEvent ,然后执行IPCThreadState::handlePolledCommands ;再看看handlePolledCommands 函数中执行了getAndExecuteCommand ;getAndExecuteCommand 在IPCThreadState::joinThreadPool 函数中已经提到过了,是用于读取binder驱动的数据和命令字段的解析处理;
status_t IPCThreadState::handlePolledCommands()
{
status_t result;
do {
result = getAndExecuteCommand();
} while (mIn.dataPosition() < mIn.dataSize());
processPendingDerefs();
flushCommands();
return result;
}
这样ServiceManager 进程的启动和消息监听也就分析完成了!
那我们要想想
- binder驱动是如果把Client端的数据进行一次拷贝到
ServiceManager 进程中来读取的呢? ServiceManager 进程又是如何成为binder驱动的上下文管理者?- binder驱动如何管理每个进程的binder服务呢?
|