首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

  • 24-11-26 09:05
  • 3402
  • 18526
juejin.cn

本文主要讲这两行代码

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,对于这个多线程类,之前博客中有解释

Android native层多线程类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驱动通讯,然后进程跨进程通讯
注:本文转载自juejin.cn的回车的文章"https://juejin.cn/post/7441033757399777306"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top