上一篇文章 音视频学习阶段(二)Binder native 源码学习(一)
关于 Binder 的学习过程中有一些概念需要重点介绍一下
1:ProcessState 单例对象,每个进程仅有一个
2:handle_entry 记录了所有binder 的指针,非常重要的代理类的核心
3: IPCThreadState 在Android中,每个参与Binder通信的线程都会有一个 IPCThreadState 实例与之关联。
并且在上一篇文章中也提到过 IPCThreadState 的这么一方法
status_t status = IPCThreadState::self()->transact( 0, IBinder::PING_TRANSACTION, data, nullptr, 0);
,用来验证Context Manager 的状态 ,从这里将 IPCThreadState::self 与 IPCThreadState 的创建联系起来就非常清楚了,
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;
}
// Racey, heuristic test for simultaneous shutdown.
if (gShutdown.load(std::memory_order_relaxed)) {
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);
return nullptr;
}
gHaveTLS.store(true, std::memory_order_release);
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
调用 IPCThreadState 的self 先价差 gHaveTLS.load(std::memory_order_acquire) 是否存在,如果当前线程没有与binder 建立过链接,那么肯定是不存在的,走到下面会在 pthread 中写入 &gTLS, threadDestructor,并提交store 并尝试重新 gHaveTLS.load(std::memory_order_acquire),如果可以就从线程中获取 IPCThreadState ,获取到了就返回,获取不到就创建
上一篇文章将 分析了前面2段的代码
sp<ProcessState> proc(ProcessState::self()); // 获取一个 ServiceManager 0 这个级别就代表的是
ServiceManager sp<IServiceManager> sm(defaultServiceManager());
接下来我们继续分析
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());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
// 重要方法 创建线程池 ,上面的应该是和服务有关,在分析binder 的过程中暂不分析
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
::android::hardware::joinRpcThreadpool();
}
接下来要分析的方法是 ProcessState::self()->startThreadPool(); 这个方法是创建与 Binder 链接的线程池的方法,下面来具体分析一下
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
同步调用了 spawnPooledThread 这个方法
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());
}
}
在这个里面创建了 PoolThread 线程池 ,再来分析一下 PoolThread 的构造方法
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 句非常的简单
回到main_mediaserver.cpp 中继续分析
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());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
::android::hardware::configureRpcThreadpool(16, false);
ProcessState::self()->startThreadPool();
// 接下来就是这里了
IPCThreadState::self()->joinThreadPool();
::android::hardware::joinRpcThreadpool();
}
IPCThreadState::self()->joinThreadPool();
//isMain=true。代表是主线程。
void IPCThreadState::joinThreadPool(bool isMain)
{
//isMain=true。代表是主线程。
//BC_ENTER_LOOPER发送给binderDriver后,binderDriver确认能否启动线程,如果不能会报error?
//isMain=false。代表是普通的binder线程。
// BC_REGISTER_LOOPER发送给binderDriver后,binderDriver会确认能否启动线程,如果不能会报error
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
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);
talkWithDriver(false);
}
到了这里就是向 binder 写指令了 ,而且还是一个dowhile 循环向里面写的,到了这里才是 binder 的所有准备才算完成,
关于代码逻辑我已经整理了,但是这个里面还涉及到非常多的 IPC 的知识,并不是这一点点代码能提供的, 网上有非常多的博客 写的都非常的好 传送门,大家可以阅读一下,将这个体系连贯起来,
在FrameWork Binder 相关的内容中,分析了他的流程,是在 SystemServer 的启动过程中,启动的各个服务,然后各个服务在启动后,将自身添加到了SystemServiceManager 来管理的,依照这个流程,我们现在已经打开了了binder驱动,并且已经创建好了 BpBinder ,下一步的流程大概就是向管理器中注册自己,这段代码就在
MediaPlayerService::instantiate();
看一下他的具体的逻辑 ServiceManager
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
在 ServiceManagerShim 但是创建 ServiceManagerShim 又传了一个 impl ,没找到 真是崩溃
status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority)
{
Status status = mTheRealServiceManager->addService(
String8(name).c_str(), service, allowIsolated, dumpsysPriority);
return status.exceptionCode();
}