一.序言
说到Binder这个东西大家都不陌生,为什么今天又聊起Binder呢?最近看到大家都在Android群里都在卷fw层,所以我也就开始学起了Binder。本文主要从Native层面讲起,系统版本Android13
二.概述
Binder是Android系统提供的IPC机制。由于Android是基于Linux内核的,因此除了Binder,Android还有其他机制,例如管道和socket。Binder机制相比其他IPC来说更加方便和灵活了。 在基于Binder的C/S架构中,除了C端和S端,还有一个全局的Android的ServiceManager端,它是管理系统中的各种服务(Service)的。client和Service关系如下:
通过图中可以得出一个结论:
1.Service要先注册到ServiceManager,Service就是ServiceManager的客户端了,而ServiceManager就是服务端了。 2.client要想使用Service,必须先到ServiceManager获取Service相关的信息,所以client是ServiceManager客户端。 3.client拿到Service后建立通信的通路,client就可以和Service进行通信了。
三.进程
一个进程是不能访问到另一个进程的,也就是说进程是具有独立性的。
那么进程之间要通信,就不能使用属于进程的资源,而应该使用一份公共的资源。
所以进程间通信的本质是:由OS参与,提供一份所有进程都能访问的公共资源。
Binder跨进程通信首先得有进程的吧,那就从进程创建的那时候说起。一个APP至少一个进程,进程创建的时候会调用onZygoteInit函数
xref: /frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
//创建ProcessState对象
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
}
ProcessState翻译过来就是进程状态,我们看看ProcessState是什么?它负责打开 Binder 驱动设备以及mmap
sp<ProcessState> ProcessState::self()
{
return init(kDefaultDriver, false /*requireDefault*/);
}
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
//call_once保证函数只调用一次
[[clang::no_destroy]] static std::once_flag gProcessOnce;
std::call_once(gProcessOnce, [&](){
if (access(driver, R_OK) == -1) {
driver = "/dev/binder";
}
std::lock_guard<std::mutex> l(gProcessMutex);、
//调用ProcessState构造函数 并且一个进程对应一个gProcess
gProcess = sp<ProcessState>::make(driver);
});
verifyNotForked(gProcess->mForked);
return gProcess;
}
ProcessState::ProcessState(const char* driver)
: mDriverName(String8(driver)),
mDriverFD(-1),
......
mCallRestriction(CallRestriction::NONE) {
//打开驱动driver参数 /dev/binder
base::Result<int> opened = open_driver(driver);
if (opened.ok()) {
// mmap,提供一块虚拟地址空间来接收事务
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
}
}
static base::Result<int> open_driver(const char* driver) {
//打开驱动driver参数 /dev/binder
int fd = open(driver, O_RDWR | O_CLOEXEC);
//通过ioctl方式告诉binder驱动线程最大数
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
close(fd);
}
return fd;
}
通过上述代码得知当进程创建的时候会创建一个ProcessState对象且一个进程只有一个ProcessState。在ProcessState构造函数里面打开通过open函数打开binder驱动,这就相当于与内核的 Binder 驱动有了交互的通道。然后通过mmap,提供一块虚拟地址空间来接收事务。它可以将文件直接映射到进程的地址空间(虚拟内存)。实现了文件和虚拟内存地址一一映射的关系.在完成映射后,进程就可以使用指针直接读写文件,而系统会自动回写被修改过得脏页到磁盘对应位置。mmap 在完成了 read、write 相同效果的同时不仅省去了内核到进程的内存拷贝过程,而且还可以实现数据的共享操作:一个文件可以同时被多个进程、内核映射,如果映射的文件被内核或其他进程修改,那么最终的结果也会反映到映射当中。
通过ioctl方式告诉binder驱动线程最大数。
设置Server端线程池中支持的最大线程数,保存在binder驱动中的binder_proc结构体中。由于Client端是并发向Server发送请求的,所以Server端必须有线程池来处理并发请求。binder驱动中会记录Client端请求的线程数,如果超过最大线程数,则不再处理Client端发送的请求。
创建完ProcessState后调用startThreadPool函数,通过方法名称顾名思义就是启动线程池
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
if (mMaxThreads == 0) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string
//PoolThread继承Thread 也就是说调用Thread的run函数执行任务
//isMain=true;
sp<Thread> t = sp<PoolThread>::make(isMain);
t->run(name.string());
}
}
PoolThread继承Thread,PoolThread又把任务交给了IPCThreadState的joinThreadPool函数,那IPCThreadState这个又是个什么东西呢?它才是实际干活的跨进程通信的。PoolThread在 ProcessState.cpp中
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
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;
}
goto restart;
首次进入self函数的时候gHaveTLS.load(std::memory_order_acquire)是false的,然后同goto函数执行restart。TLS是本地线程存储空间,全程叫做Thread local storage。并且这种空间每个线程都有,线程空间不共享这些空间。
通过pthread_getspecific/pthread_setspecific函数可以获取│设置这些空间中的内客。从线程本地存储空间中荻得保存在其中的IPCThreadstate对象。 有调用pthread_getspecific的地方,肯定也有调用pthread_setspecific的地方。
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mServingStackPointer(nullptr),
mServingStackPointerGuard(nullptr),
mWorkSource(kUnsetWorkSource),
mPropagateWorkSource(false),
mIsLooper(false),
mIsFlushing(false),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0),
mCallRestriction(mProcess->mCallRestriction) {
//在构造函数中,把自已设置到线程本地存储中去。
pthread_setspecific(gTLS, this);
clearCaller();
//mIn和mOut是两个Parcel。把它看成是发送和接收命令的缓冲区即可。
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
一个线程一个,每个IPCThreadState都有mIn和mOut,mIn是接收binder的数据,而mOut是用来发送数据的。 构造函数展示就分析这里,接着分析threadLoop函数里面调用的joinThreadPool函数出传入的参数true
void IPCThreadState::joinThreadPool(bool isMain)
{
//此时isMain是true代表主线程 isMain是false 代表普通的binder线程
//BC_ENTER_LOOPER代表的是Binder主线程,不会退出的线程
//BC_REGISTER_LOOPER,表示是由binder驱动创建的线程
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
mIsLooper = true;
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);
}
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
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);
mIsLooper = false;
talkWithDriver(false);
}
tatus_t IPCThreadState::talkWithDriver(bool doReceive)
{
//此时doReceive是false
......
binder_write_read bwr;
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
// Return immediately if there is nothing to do.
//如果数据空的话 被NO_ERROR调了
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
do{
//特殊的read,write, 当你用read,write不能完成某一功能时,就用ioctl
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0){
}
}
}
这里请注意bwr是与binder交互数据,如果write和read都是空的话就返回NO_ERROR。
进程创建后的准备工作就基本是这些了,接下来我们就用 main_mediaserver.cpp来分析两个进程之间如何用binder通信的。
四.如何跨进程
我们就从 main_mediaserver.cpp作为切入点, AudioPolicyService是android音频系统的两大服务之一,另一个服务是AudioFliger。这两个服务都是在系统启动时由MediaServer加载
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
//创建ProcessState,在进程里面已经讲过。创建ProcessState对象
sp<ProcessState> proc(ProcessState::self());
//创建了BpServiceManager
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
//添加服务
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
//启动线程池
ProcessState::self()->startThreadPool();
//内部也回调用joinThreadPool
IPCThreadState::self()->joinThreadPool();
::android::hardware::joinRpcThreadpool();
}
ProcessState::self()函数前面已经见过了,简单概括下就是创建了IPCThreadState每个IPCThreadState都有mIn和mOut,mIn是接收binder的数据,而mOut是用来发送数据的。
1.defaultServiceManager函数
defaultServiceManager函数它位于xref: /frameworks/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
//call_once只调用一次
std::call_once(gSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
while (sm == nullptr) {
sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
......
}
gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
});
return gDefaultServiceManager;
}
call_once用于保证某个函数只调用一次,即使是多线程环境下,它也可以可靠地完成一次函数调用。也就是只有一个实例。先是调用 getContextObject函数
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
sp<IBinder> context = getStrongProxyForHandle(0);
......
return context;
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
......
//句柄值查询handle_entry
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) { //此时handle是0满足这个条件
IPCThreadState* ipc = IPCThreadState::self();
CallRestriction originalCallRestriction = ipc->getCallRestriction();
ipc->setCallRestriction(CallRestriction::NONE);
Parcel data;
status_t status = ipc->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
//设置调用限制
ipc->setCallRestriction(originalCallRestriction);
if (status == DEAD_OBJECT)
return nullptr;
}
//主要是创建BpBinder
sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle);
e->binder = b.get();
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
getStrongProxyForHandle函数的作用就是创建了一个BpBinder。BpBinder是IBinder的子类,BpBinder是客户端(p代表proxy代理的意思) BBinder是服务端。
sp<BpBinder> BpBinder::create(int32_t handle) {
.....
return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);
}
//handle等于0 代表serviceManager对应的BBinder
BpBinder::BpBinder(Handle&& handle)
: mStability(0),
mHandle(handle),
mAlive(true),
mObitsSent(false),
mObituaries(nullptr),
mTrackedUid(-1) {
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
}
简化下 interface_cast(ProcessState::self()->getContextObject(nullptr))代码就是 interface_cast((BpBinder(0)))
我们继续往下分析interface_cast函数,在IServiceManager.cpp里面并没有搜到interface_cast具体代码,其实在头文件里面IServiceManager.h里面的IServiceManager.h有一段这样的代码
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE) \
const ::android::String16& ITYPE::getInterfaceDescriptor() const { return ITYPE::descriptor; } \
::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) { \
::android::sp<ITYPE> intr; \
if (obj != nullptr) { \
intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor)); \
if (intr == nullptr) {
/* 这里创建的是BpServiceManager对象 */
intr = ::android::sp<BPTYPE>::make(obj); \
} \
} \
return intr; \
} \
::android::sp<ITYPE> ITYPE::default_impl; \
bool ITYPE::setDefaultImpl(::android::sp<ITYPE> impl) {
assert(!ITYPE::default_impl); \
if (impl) { \
ITYPE::default_impl = std::move(impl); \
return true; \
} \
return false; \
} \
const ::android::sp<ITYPE>& ITYPE::getDefaultImpl() { return ITYPE::default_impl; } \
ITYPE::INAME() {} \
ITYPE::~INAME() {}
这里的BpServiceManager不再通过手动实现,而是采用 AIDL(文件为 IServiceManager.aidl),生成 IServiceManager、BnServiceManager、BpServiceManager 的头文件及具体实现。BpServiceManager内部的持有BpBinder,它是怎么持有的呢?代码如下:
xref: /frameworks/native/libs/binder/aidl/android/os/IServiceManager.aidl
简化一下代码就是BpServiceManager(BpBinder(0))。我们再来分析下BpServiceManager构造函数,它是父类是BpInterface
在BpServiceManager的父类BpInterface,把BpBinder(0)又传给了BpInterface,而BpInterface又把BpBinder(0)传给了BpRefBase,然后传给了它的BpRefBase父类。
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
// mRemote就是BpBinder(0)
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(nullptr), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
也就是说BpServiceManager的一个变量mRemote指向了BpBinder。回想一下defaultServiceManager 函数,可以得到以下两个关键对象:
有一个BpBinder对象,它的handle值是0。
有一个BpServiceManager对象,它的 mRemote值是BpBinder。
2.instantiate如何添加服务
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
defaultServiceManager通过之前的分析知道这是一个BpServiceManager,也就是说BpServiceManager.addService函数
namespace android {
namespace os {
BpServiceManager::BpServiceManager(const ::android::sp<::android::IBinder>& _aidl_impl)
: BpInterface<IServiceManager>(_aidl_impl){//_aidl_impl 就是 BpBinder(0) 实例
}
--------------------------------------------------
::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) {
::android::Parcel _aidl_data;
_aidl_data.markForBinder(remoteStrong());//0、和 Rpc Binder有关
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
//1、写 interface
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
//2、写 name
_aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
//3、写 binder 对象
_aidl_ret_status = _aidl_data.writeStrongBinder(service);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
//4、写 allowIsolated
_aidl_ret_status = _aidl_data.writeBool(allowIsolated);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
//5、写 dumpPriority
_aidl_ret_status = _aidl_data.writeInt32(dumpPriority);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
//这里的remote就是我们BpBinder的
//6、借助 BpBinder(0)#transact 来发起 Binder 通信
_aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0);
if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IServiceManager::getDefaultImpl())) {
return IServiceManager::getDefaultImpl()->addService(name, service, allowIsolated, dumpPriority);
}
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
//7、如果有返回值就从这个 parcel 包里读
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}
在addService函数可能发现了一个remote()是不是有点熟悉。remote()这话就是我们前面提到BpBinder(0)也就说调用了 Binder.cpp的transact函数
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
```
if (CC_UNLIKELY(isRpcBinder())) {
status = rpcSession()->transact(sp<IBinder>::fromExisting(this), code, data, reply,
flags);
} else {
//把工作又交给了IPCThreadState的函数了
status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
}
return status;
}
return DEAD_OBJECT;
}
前面提到的IPCThreadState是实际干活的 ,transact里面调用了writeTransactionData函数写入了事务数据。
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
LOG_ALWAYS_FATAL_IF(data.isForRpc(), "Parcel constructed for RPC, but being used with binder.");
status_t err;
flags |= TF_ACCEPT_FDS;
//注意这里的第一个参数BC_TRANSACTION,它是应用程序向binder发备发运消息的消总码,
//而binder设备向应用程序回复消息的消息码以BR_开头。消息码的定义在binder_module.h 中,
//请求消息码和回应消息码的对应关系,需要查看Binder驱动的实现才能将其理清楚,。
//writeTransactionData
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
if ((flags & TF_ONE_WAY) == 0){
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
//等待响应
err = waitForResponse(nullptr, nullptr);
}
return err;
}
//写入事物数据
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是和binder设备通信的数据结构。简单来说就是通信的一个对象
binder_transaction_data tr;
tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
//handle的值传递给了target,用来标识目的端,其中0是ServiceManager的标志。
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();
......
//把命令写到mout中,而不是直接发出去,可见这个函数有点名不刮实。
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
现在,已经把addService的请求信息写到mOut中了。接下来再看发送请求和接收回复部分的实现,代码在 waitForResponse函数中,从函数名称就是一个等待响应,现在我们可以假设收到回复了,如下所示:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
//将IPC数据通过Binder驱动发送给服务进程,talkWithDriver是和Binder驱动交互的核心、阻塞型函数
if ((err=talkWithDriver()) < NO_ERROR) break;
//检查服务进程返回来的数据
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
.....
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;
}
status_t IPCThreadState::executeCommand(int32_t cmd){
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
case BR_TRANSACTION:
//读取mIn中的数据到一个binder_transaction_data中
binder_transaction_data_secctx tr_secctx;
binder_transaction_data& tr = tr_secctx.transaction_data;
if (cmd == (int) BR_TRANSACTION_SEC_CTX) {
result = mIn.read(&tr_secctx, sizeof(tr_secctx));
} else {
result = mIn.read(&tr, sizeof(tr));
tr_secctx.secctx = 0;
}
if (tr.target.ptr) {
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
//cookie域存放的是Binder对象
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
//the_context_object它是一个全局变量,也是一个BBinder对象
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
case BR_DEAD_BINDER:
{
//收到驱动发来Service挂掉的消息,只有BpBinder能收到
BpBinder *proxy = (BpBinder*)mIn.readPointer();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writePointer((uintptr_t)proxy);
} break;
case BR_SPAWN_LOOPER:
//收到驱动层发来的消息,创建一个新的线程用于和binder通信的
mProcess->spawnPooledThread(false);
break;
}
waitForResponse函数的作用比较简单,就是根据(uint32_t)cmd做出相应的事情。
我们再来分析下talkWithDriver里面的ioctl函数
tatus_t IPCThreadState::talkWithDriver(bool doReceive) {
//与binder交互数据
binder_write_read bwr;
//命令的填充
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
//重点是ioctl函数
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0){
err = NO_ERROR;
else
err = -errno;
}
}
ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。
startThreadPool函数
这个函数在进程里面已经讲过,简单来说调用了IPCThreadState::self()->joinThreadPool(mIsMain);
joinThreadPool函数
void IPCThreadState::joinThreadPool(bool isMain) {
do {
......
// 现在获取要处理的下一个命令,如果需要,请等待
result = getAndExecuteCommand();
}
while (result != -ECONNREFUSED && result != -EBADF);
//向Binder驱动发BC_REGISTER_LOOPER通知驱动用户空间线程已经创建
mOut.writeInt32(BC_EXIT_LOOPER);
mIsLooper = false;
talkWithDriver(false);
}
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();
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;
}
// Cond broadcast can be expensive, so don't send it every time a binder
// call is processed. b/168806193
if (mProcess->mWaitingForThreads > 0) {
pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
}
pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
return result;
}
这里用do while循环用来检查是否client端有信息发过来并且处理信息。通过pthread_mutex_lock返回时,该互斥锁已被锁定。线程调用该函数让互斥锁上锁,如果该互斥锁已被另一个线程锁定和拥有,则调用该线程将阻塞,直到该互斥锁变为可用为止。到这里binder的就基本分析完成一部分,下一篇计划写ServiceManager
binder支持多线程:
通过前面的分析startThreadPool创建的线程启动joinThreadPool读取binder是否有请求以及主线程调用的joinThreadPool。 参考资料如下:
-<<深入理解android>>
本文在写作过程中参考了很多文章、在这里感谢大佬们的无私分享!