oracle process state,Android应用程序启动过程(二)——ProcessState和Binder线程池

在Android应用程序启动过程(一)——进程创建中,我们已经讲述了一个app进程的创建过程。一个app进程刚被fork出来时,它还不具备与AMS“沟通”的能力。它需要进行一些初始化,以开启这种能力。

Android中提供了Binder进程间通信机制,两个进程通过Binder Driver来实现数据跨进程交换。Binder Driver为用户空间提供了/dev/binder节点,我们可以使用open、mmap和ioctl来操作它。

因此一个app进程要想访问AMS(AMS在systemserver进程),它也需要先打开Binder Driver,建立好内存映射后,再执行IPC操作,执行完后关闭。但如果每次要和AMS通信都要重复打开Binder Driver和建立内存映射,这样很浪费资源,也会降低效率。一个好的方式就是,app进程只在一开始打开Binder Driver、建立内存映射,之后就一直使用直到进程被关闭。

围绕这个思路,我们再来看下,app进程被创建后,执行到RuntimeInit.zygoteInit()时所进行的初始化操作。

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv)

throws ZygoteInit.MethodAndArgsCaller {

...

// 这里调用了一个native方法

zygoteInitNative();

applicationInit(targetSdkVersion, argv);

}

public static final native void zygoteInitNative();

// frameworks/base/core/jni/AndroidRuntime.cpp

static JNINativeMethod gMethods[] = {

{ "finishInit", "()V",

(void*) com_android_internal_os_RuntimeInit_finishInit },

{ "zygoteInitNative", "()V",

(void*) com_android_internal_os_RuntimeInit_zygoteInit },

{ "isComputerOn", "()I",

(void*) com_android_internal_os_RuntimeInit_isComputerOn },

{ "turnComputerOn", "()V",

(void*) com_android_internal_os_RuntimeInit_turnComputerOn },

{ "getQwertyKeyboard", "()I",

(void*) com_android_internal_os_RuntimeInit_getQwertyKeyboard },

};

static AndroidRuntime* gCurRuntime = NULL;

static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)

{

// gCurRuntime在AndroidRuntime类的构造函数中被赋值的

// 创建的位置是Zygote进程的main()方法,实际类型是AppRuntime

gCurRuntime->onZygoteInit();

}

// frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit()

{

// 打开/dev/binder,建立内存映射

sp proc = ProcessState::self();

LOGV("App process: starting thread pool.\n");

proc->startThreadPool();

}

1. ProcessState

ProcessState::self()是返回一个单例对象,保证进程内只有一个实例,再看看它的构造函数:

// frameworks/base/libs/binder/ProcessState.cpp

ProcessState::ProcessState()

: mDriverFD(open_driver()) // 打开/dev/binder

, mVMStart(MAP_FAILED)

, mManagesContexts(false)

, mBinderContextCheckFunc(NULL)

, mBinderContextUserData(NULL)

, mThreadPoolStarted(false)

, mThreadPoolSeq(1) {

if (mDriverFD >= 0) {

// 使用mmap进行内存映射

mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

}

}

static int open_driver() {

int fd = open("/dev/binder", O_RDWR);

if (fd >= 0) {

...

// 设置支持的最大线程数

size_t maxThreads = 15;

result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);

...

}

return fd;

}

2. Binder线程池

Binder是支持并发执行IPC的,通过Binder线程池来执行。线程池的大小上限是1+15=16个。1是我们下面要说的Binder主线程,15正是上面我们打开Binder Driver后设置的值。 在app进程创建后一开始只会创建一个Binder主线程,Binder Driver会根据需要向用户空间发送创建线程的命令。

// frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit()

{

sp proc = ProcessState::self();

LOGV("App process: starting thread pool.\n");

// 创建一个Binder主线程 (主线程不会退出)

proc->startThreadPool();

}

void ProcessState::startThreadPool()

{

AutoMutex _l(mLock);

if (!mThreadPoolStarted) {

mThreadPoolStarted = true;

// true表示是创建Binder主线程

spawnPooledThread(true);

}

}

void ProcessState::spawnPooledThread(bool isMain)

{

...

// 启动Binder主线程

sp t = new PoolThread(isMain);

t->run(buf);

}

class PoolThread : public Thread

{

public:

PoolThread(bool isMain)

: mIsMain(isMain)

{

}

protected:

virtual bool threadLoop()

{

IPCThreadState::self()->joinThreadPool(mIsMain);

return false;

}

const bool mIsMain;

};

参考:

《深入理解Android内核设计思想 第2版》

Binder通信过程中的用户空间线程池的管理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值