本文主要讲这两行代码
C++ 代码解读复制代码sp proc = ProcessState::self();
proc->startThreadPool();
我们都知道binder跨进程通讯不能在zygote中,因为zygote需要fork出其他进程;不适合多线程开启
- 从zygote fork出了systemserver进程,
- 并且zygote进程没有binder的线程池;binder线程池是在systemserver线程中开启的;
看下源码
java 代码解读复制代码
// \frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
//systemserver进程
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
//systemserver进程中处理
return handleSystemServerProcess(parsedArgs);
}
return null;
}
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
//调用zygoteInit
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, cl);
}
public static final Runnable zygoteInit(int targetSdkVersion,
String[] argv, ClassLoader classLoader) {
//调用AndroidRuntime中com_android_internal_os_ZygoteInit_nativeZygoteInit
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
//AndroidRuntime中com_android_internal_os_ZygoteInit_nativeZygoteInit
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
//app_main.cpp 中的onZygoteInit:开启binder线程池
gCurRuntime->onZygoteInit();
}
// \frameworks\base\cmds\app_process\app_main.cpp
virtual void onZygoteInit()
{
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
也就是说下面这两行代码就是开启了binder线程池,那么是如何开启binder线程池的,这个博客专门解释一下
c++ 代码解读复制代码sp proc = ProcessState::self();
proc->startThreadPool();
看下\frameworks\native\libs\binder\ProcessState.cpp这个类; 1.先看下self()方法
C++ 代码解读复制代码//单例,并且创建ProcessState时传入"/dev/binder",这个应该是binder驱动的路径
sp ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
//ProcessState构造器,语法有点特殊,对于java开发可能有点看不懂,下面简单解释下
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)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
题外话,C++语法
C++ 代码解读复制代码class MyClass {
private:
int a;
double b;
public:
MyClass(int x, double y) : a(x), b(y) {
// 构造函数体
}
};
// 初始化列表: 后面的 a(x) 和 b(y) 分别初始化成员变量 x赋值给a 和 y赋值给 b。
C++ 代码解读复制代码
class MyClass : Base1, Base2 {
private:
int a;
double b;
std::string c;
public:
MyClass(int x, double y, const std::string& z) :
Base1(x),
Base2(y),
a(x),
b(y),
c(z)
{
// 构造函数体
}
};
//这里Base1(x),表示执行基类Base1的构造器
//a(x) 还是一样把x赋值给a
回到原题:继续分析ProcessState
所以ProcessState得构造器就是给成员变量赋值
注意:mDriverFD(open_driver(driver))这里赋值的时候执行的open_driver()
并且调用的mmap,映射到虚拟内存,映射的内存大小也是众所周知
C++ 代码解读复制代码mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
binder虚拟内存映射大小:1M - 8k
ok,第一行构造器分析完了,看第二行
C++ 代码解读复制代码void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
//很明显上面startThreadPool方法中: mThreadPoolStarted 为true
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
//这里创建了PoolThread对象,这个类就是ProcessState.cpp这个文件中,如下
sp t = new PoolThread(isMain);
//执行run后,就会执行PoolThread的threadLoop方法
t->run(name.string());
}
}
//PoolThread类
class PoolThread : public Thread
{
public:
//isMain = true
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
// threadLoop返回false,说明这里只执行一次,就退出
return false;
}
const bool mIsMain;
};
我们知道继承自PoolThread继承Thread,对于这个多线程类,之前博客中有解释
现在也就是会执行IPCThreadState 的方法,并且调用joinThreadPool()
接着看IPCThreadState类
C++ 代码解读复制代码// \frameworks\native\libs\binder\IPCThreadState.cpp
IPCThreadState* IPCThreadState::self()
{
//gHaveTLS 默认为false
if (gHaveTLS) {
//3. goto restart会执行到这里
restart:
// 4. gTLS是创建线程时,获取的线程信息
const pthread_key_t k = gTLS;
//5. 这里根据创建线程的gTLS信息,创建一个IPCThreadState对象
// 正常情况下st为null,因为获取不到值
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
//6. 没创建成功,自己new一个IPCThreadState;接着就可以看IPCThreadState构造器了
return new IPCThreadState;
}
if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return NULL;
}
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
//1.先走这里,会创建一个线程
//pthread_key_create有两个参数,
//第一个是创建一个pthread_key_t结构体;第二个参数是线程结束时执行的函数
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 NULL;
}
//2.创建gTLS后,gHaveTLS赋值为true
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
IPCThreadState构造器
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
//这里设置了值也就是IPCThreadState对象,上面方法中的第5步才能获取到值
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
从IPCThreadState::self()方法的第5步很明显可以知道
- 当前线程没有IPCThreadState对象的时候,才会去new一个IPCThreadState;
- 有IPCThreadState对象的时候,直接从pthread_getspecific获取
- 所以,一个线程只有一个IPCThreadState对象。
接着再看joinThreadPool方法
C++ 代码解读复制代码void IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
//数据处理,
processPendingDerefs();
// 主要调用talkWithDriver()和executeCommand(cmd);
result = getAndExecuteCommand();
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
这个方法主要就是调用了talkWithDriver()和executeCommand(cmd);
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数据读取的int值,mIn流的前32位
cmd = mIn.readInt32();
pthread_mutex_lock(&mProcess->mThreadCountLock);
//mProcess就是上面的ProcessState ; 该进程可运行线程数+1
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) {
mProcess->mStarvationStartTimeMs = 0;
}
pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
return result;
}
OK,看下talkWithDriver
arduino 代码解读复制代码//frameworks\native\libs\binder\include\binder\IPCThreadState.h
// 头文件中这样声明talkWithDriver方法,直接调用talkWithDriver(); 就是doReceive=true
status_t talkWithDriver(bool doReceive=true);
talkWithDriver从名字就可以看出是跟驱动进行联系,也就是和binder驱动通讯,开始跨进程通讯
方法逻辑如下,
C++ 代码解读复制代码status_t IPCThreadState::talkWithDriver(bool doReceive)
{
//和Binder驱动通信的结构体
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don't want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
//上面的翻译:如果我们正从输入流读取数据,我们就不会去写任何数据。并且调用者请求读取下一个数据
//意思就是needRead=true时,是写数据,
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
// This is what we'll read.
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.
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
} 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);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
alog << "Remaining data size: " << mOut.dataSize() << endl;
alog << "Received commands from driver: " << indent;
const void* cmds = mIn.data();
const void* end = mIn.data() + mIn.dataSize();
alog << HexDump(cmds, mIn.dataSize()) << endl;
while (cmds < end) cmds = printReturnCommand(alog, cmds);
alog << dedent;
}
return NO_ERROR;
}
return err;
}
总结
- ProcessState的startThreadPool也就是在当前进程中,开启一个线程与binder驱动通讯,然后进程跨进程通讯
评论记录:
回复评论: