一 概述
[main_mediaserver.cpp]
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
//1 获得一个ProcessState的实例
sp<ProcessState> proc(ProcessState::self());
//2 获得一个IServiceManager对象
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
//3 注册服务
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
//4 注册其他,默认为空
registerExtensions();
//5 ProcessState有关线程池
ProcessState::self()->startThreadPool();
//6 IPCThreadState有关线程池
IPCThreadState::self()->joinThreadPool();
}
上一篇我们说完了步骤 1 到步骤 3,并且到了 IPCThreadState 在和 Binder 交互时,会调用 waitForResponse,然后在 waitForResponse 中调用 talkWithDriver 和 Binder 进行交互,读出 mIn 中的数据,然后通过 executeCommand 执行,接下来,我们再看看具体的细节
源码目录
frameworks/native/libs/binder/IPCThreadState.cpp
frameworks/native/libs/binder/ProcessState.cpp
frameworks/native/libs/binder/IPCThreadState.cpp
二 talkWithDriver
[IPCThreadState.cpp]
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
//这个就是我们在open_device时拿到的fd
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
//binder_write_read是用来和binder设备交换数据的结构
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_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(__ANDROID__)
//通过ioctl的方式交互
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;
}
IF_LOG_COMMANDS() {
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
//日志
...
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else {
mOut.setDataSize(0);
processPostWriteDerefs();
}
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
//日志
...
return NO_ERROR;
}
return err;
}
三 startThreadPool
因为 registerExtensions 默认为空,所以我们接下来看 startThreadPool 的相关逻辑,相比于之前的逻辑,这个简单很多
[ProcessState.cpp]
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());
//传入的参数是true
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
class PoolThread : public Thread
{
public:
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
四 joinThreadPool
接下来就是最后一步 joinThreadPool 了,它是定义在 IPCThreadState.cpp 中的函数
[IPCThreadState.cpp]
void IPCThreadState::joinThreadPool(bool isMain)
{
//如果isMain是true,则需要写入一个BC_ENTER_LOOPER
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
//处理已经死亡的BBinder对象
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);
//退出Looper
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
4.1 getAndExecuteCommand
在 joinThreadPool 也有一个和之前很像的函数 getAndExecuteCommand,它也是 talkWithDriver 和 executeCommand,因为之前已经说过,所以这里就不重复了
[IPCThreadState.cpp]
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
//和Binder驱动交互
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);
//执行cmd
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;
}
五 总结
终于,一个关于 MediaServer 系统 Server 使用 Binder 的过程,就让我们整理完毕了
- 在使用 Binder 之前,需要获得一个 ProcessState 实例,这个对象是一个单例
- 然后需要拿到一个 defaultServiceManager 对象,这是一个 IServiceManager,它是一个 IBinder 对象,其实就是 BpBinder
- 我们如果想要给其他进程提供 Binder 服务,那么我们需要将自己的服务注册到 ServiceManager 中,这个注册流程就是一个 Binder 通信的过程
- 注册完毕后通过 ProcessState::self()->startThreadPool 启动一个线程进行 Binder 事件的接收处理,这个线程不会退出
- 将 MediaServer 的主线程,通过 IPCThreadState::self()->joinThreadPool 也加入 loop 循环,接收 Binder 事件
当然,这两篇关于 Binder 的介绍,也只是很简单的说明了 Binder 通信时,native 层参与的类以及这些通信的流程,对于更细节的东西,这里并没有提到,接下来我们就看看 Java 层的 Binder 机制,以及这些操作中的细节