Binder线程池
目录
- 设置进程Binder线程数量
- 创建线程池
- PoolThread
- joinThreadPool
- binder 驱动对BC_ENTER_LOOPER 以及BC_REGISTER_LOOPER的处理
- Binder 驱动通知用户态创建线程
- 进程创建线程
https://blog.csdn.net/qq_40587575/article/details/130394731
在这种情况下,如果Server只有一个线程处理响应,就会导致客户端的请求可能需要排队而导致响应过慢的现象发生。解决这个问题的方法就是引入多线程。【多个客户端不同线程去请求,服务端需要使用多线程机制,binder线程池,创建多个线程去回复多个客户端的请求】
binder线程有主线程和非主线程之分,主线程是启动的时候才会有的,每个binder线程池只有一个。其他情况下申请的都是非主线程,binder线程(非主线程)有两种情况启动:client进程向binderDriver发送IPC请求,以及 client进程向binderDriver回复IPC请求结果,binder线程池的默认大小是16,1个主线程和15个非主线程。
设置进程Binder线程数量
创建 ProcessState 进程单实例时,设置默认的最大线程数量为 DEFAULT_MAX_BINDER_THREADS
。
ProcessState::ProcessState(const char* driver)
: mDriverName(String8(driver)),
mDriverFD(-1),
mVMStart(MAP_FAILED),
mThreadCountLock(PTHREAD_MUTEX_INITIALIZER),
mThreadCountDecrement(PTHREAD_COND_INITIALIZER),
mExecutingThreadsCount(0),
mWaitingForThreads(0),
mMaxThreads(DEFAULT_MAX_BINDER_THREADS), //15
mCurrentThreads(0),
mKernelStartedThreads(0),
mStarvationStartTimeMs(0),
mForked(false),
mThreadPoolStarted(false),
mThreadPoolSeq(1),
mCallRestriction(CallRestriction::NONE) {
unique_fd opened = open_driver(driver);
if (opened.ok()) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
opened.get(), 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.", driver);
opened.reset();
mDriverName.clear();
}
}
#ifdef __ANDROID__
LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating.",
driver);
#endif
if (opened.ok()) {
mDriverFD = opened.release();
}
}
/*------------------------------------------------------------------*/
static unique_fd open_driver(const char* driver) {
auto fd = unique_fd(open(driver, O_RDWR | O_CLOEXEC));
if (!fd.ok()) {
PLOGE("Opening '%s' failed", driver);
return {};
}
int vers = 0;
int result = ioctl(fd.get(), BINDER_VERSION, &vers);
if (result == -1) {
PLOGE("Binder ioctl to obtain version failed");
return {};
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! "
"ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
return {};
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
// 与 binder 驱动交互,设置 proc->max_threads = max_threads
result = ioctl(fd.get(), BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
result = ioctl(fd.get(), BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
if (result == -1) {
ALOGE_IF(ProcessState::isDriverFeatureEnabled(
ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
"Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
return fd;
}
可单独调用函数设置线程池数量:
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
// 如果开启线程池后,则不能再更改线程池数量
LOG_ALWAYS_FATAL_IF(mThreadPoolStarted && maxThreads < mMaxThreads,
"Binder threadpool cannot be shrunk after starting");
status_t result = NO_ERROR;
if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {
mMaxThreads = maxThreads;
} else {
result = -errno;
ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
}
return result;
}
ServiceManager 未开启线程池,只有一个主线程。
创建线程池
void ProcessState::startThreadPool()
{
std::unique_lock<std::mutex> _l(mLock);
if (!mThreadPoolStarted) {
if (mMaxThreads == 0) {
// see also getThreadPoolMaxTotalThreadCount
ALOGW("Extra binder thread started, but 0 threads requested. Do not use "
"*startThreadPool when zero threads are requested.");
}
// 开启线程池
mThreadPoolStarted = true;
// 主线程
spawnPooledThread(true);
}
}
// 创建线程实例及运行
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.c_str());
// 创建一个线程实例
sp<Thread> t = sp<PoolThread>::make(isMain);
// 线程启动
t->run(name.c_str());
pthread_mutex_lock(&mThreadCountLock);
mKernelStartedThreads++;
pthread_mutex_unlock(&mThreadCountLock);
}
// TODO: if startThreadPool is called on another thread after the process
// starts up, the kernel might think that it already requested those
// binder threads, and additional won't be started. This is likely to
// cause deadlocks, and it will also cause getThreadPoolMaxTotalThreadCount
// to return too high of a value.
}
PoolThread
PoolThread
继承于 Thread 类,run
函数回调 threadLoop
,isMain 为 true 时,创建主线程,反之则创建非主线程。
// ProcessState.cpp
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop() {
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
joinThreadPool
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mCurrentThreads++;
pthread_mutex_unlock(&mProcess->mThreadCountLock);
//先往mOut中往binder驱动写入指令
//如果是主线程的话发送BC_ENTER_LOOPER,不会退出
//如果是一般线程的话发送BC_REGISTER_LOOPER,表示 binder 驱动创建出来的线程
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
mIsLooper = true;
status_t result;
do {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
// 调用 talkWithDriver 将 mOut 中的内容发送给 binder
// 调用 executeCommand 处理 binder 驱动的响应码
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);
mIsLooper = false;
talkWithDriver(false);
pthread_mutex_lock(&mProcess->mThreadCountLock);
LOG_ALWAYS_FATAL_IF(mProcess->mCurrentThreads == 0,
"Threadpool thread count = 0. Thread cannot exist and exit in empty "
"threadpool\n"
"Misconfiguration. Increase threadpool max threads configuration\n");
mProcess->mCurrentThreads--;
pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
binder 驱动对BC_ENTER_LOOPER 以及BC_REGISTER_LOOPER的处理
**binder_thread_write
**中
while (ptr < end && thread->return_error.cmd == BR_OK) {
// 调用 spawnPooledThread(false) 则创建普通线程
case BC_REGISTER_LOOPER: //普通线程
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_REGISTER_LOOPER\n",
proc->pid, thread->pid);
binder_inner_proc_lock(proc);
if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
proc->pid, thread->pid);
} else if (proc->requested_threads == 0) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n",
proc->pid, thread->pid);
} else {
proc->requested_threads--;
proc->requested_threads_started++;
}
thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
binder_inner_proc_unlock(proc);
break;
// 调用 spawnPooledThread(true) 创建主线程
// 由 startThreadPool 调用
case BC_ENTER_LOOPER: // 主线程
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_ENTER_LOOPER\n",
proc->pid, thread->pid);
if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
proc->pid, thread->pid);
}
// 设置 thread->looper 为 BINDER_LOOPER_STATE_ENTERED
thread->looper |= BINDER_LOOPER_STATE_ENTERED;
break;
case BC_EXIT_LOOPER:
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_EXIT_LOOPER\n",
proc->pid, thread->pid);
thread->looper |= BINDER_LOOPER_STATE_EXITED;
break;
}
Binder 驱动通知用户态创建线程
binder 驱动拷贝 BR_SPAWN_LOOPER 到用户空间,执行用户空间的代码创建普通线程:
**binder_thread_read
**函数中:
当发生以下3种情况之一,便会进入done:
- 当前线程的return_error发生error的情况;
- 当Binder驱动向client端发送死亡通知的情况;
- 当类型为BINDER_WORK_TRANSACTION(即收到命令是BC_TRANSACTION或BC_REPLY)的情况;
binder_thread_read(){
...
retry:
//当前线程todo队列为空且transaction栈为空,则代表该线程是空闲的
wait_for_proc_work = thread->transaction_stack == NULL &&
list_empty(&thread->todo);
if (thread->return_error != BR_OK && ptr < end) {
...
put_user(thread->return_error, (uint32_t __user *)ptr);
ptr += sizeof(uint32_t);
goto done; //发生error,则直接进入done
}
thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (wait_for_proc_work)
proc->ready_threads++; //可用线程个数+1
binder_unlock(__func__);
if (wait_for_proc_work) {
if (non_block) {
...
} else
//当进程todo队列没有数据,则进入休眠等待状态
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
} else {
if (non_block) {
...
} else
//当线程todo队列没有数据,则进入休眠等待状态
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
}
binder_lock(__func__);
if (wait_for_proc_work)
proc->ready_threads--; //可用线程个数-1
thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
if (ret)
return ret; //对于非阻塞的调用,直接返回
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
//先考虑从线程todo队列获取事务数据
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct binder_work, entry);
//线程todo队列没有数据, 则从进程todo对获取事务数据
} else if (!list_empty(&proc->todo) && wait_for_proc_work) {
w = list_first_entry(&proc->todo, struct binder_work, entry);
} else {
... //没有数据,则返回retry
}
switch (w->type) {
case BINDER_WORK_TRANSACTION: { // client 端写入binder_work 时的type
binder_inner_proc_unlock(proc);
t = container_of(w, struct binder_transaction, work);
} break;
case BINDER_WORK_TRANSACTION_COMPLETE:... break;
case BINDER_WORK_NODE: ... break;
case BINDER_WORK_DEAD_BINDER:
case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
struct binder_ref_death *death;
uint32_t cmd;
death = container_of(w, struct binder_ref_death, work);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
else
cmd = BR_DEAD_BINDER;
put_user(cmd, (uint32_t __user *)ptr;
ptr += sizeof(uint32_t);
put_user(death->cookie, (void * __user *)ptr);
ptr += sizeof(void *);
...
if (cmd == BR_DEAD_BINDER)
goto done; //Binder驱动向client端发送死亡通知,则进入done
break;
}
if (!t)
continue; //只有BINDER_WORK_TRANSACTION命令才能继续往下执行
...
// 跳出 while 循环,执行 done 分支
break;
}
done:
*consumed = ptr - buffer;
//创建线程的条件
if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED))) {
proc->requested_threads++;
// 生成BR_SPAWN_LOOPER命令,用于创建新的线程
put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer);
}
return 0;
}
进程创建线程
status_t IPCThreadState::executeCommand(int32_t cmd)
{
switch ((uint32_t)cmd) {
case BR_TRANSACTION: ...
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false); // 创建普通线程
break;
}
return result;
}