一、前言
两个进程之间想要通信,就必须要知道对方的地址才行,这样的话,就必须要有一个"中间人"来做注册才行,servicemanager
正是做这个事的,那又涉及到一个问题,应用进程怎么知道servicemanager
的地址?看起来是一个"先有鸡还是先有蛋"的问题。我们知道,一般这种情况,我们可以将中间人设置一个大家都知道的公用地址,这样就都可以进行访问了。
二、servicemanager
进程
既然是中间人,那么servicemanager
就应该有一个"中立的"进程。
2.1 进程启动
servicemanager
是通过.rc
初始化的,在系统初始化的时候,.rc
文件会被解析:
frameworks/native/cmds/servicemanager/servicemanager.rc
sql
service servicemanager /system/bin/servicemanager
class core animation
user system
group system readproc
critical
onrestart restart apexd
onrestart restart audioserver
onrestart restart gatekeeperd
onrestart class_restart main
onrestart class_restart hal
onrestart class_restart early_hal
writepid /dev/cpuset/system-background/tasks
shutdown critical
关于.rc
的语法,我们不需要过多了解,等解析完之后,系统会将/system/bin/servicemanager
文件启动为servicemanager
进程,通过ps也可以看到该进程:
perl
$ adb shell "ps -A | grep servicemanager"
system 216 1 10865356 4284 0 0 S servicemanager
2.2 入口
servicemanager
的入口是main.cpp
,位置是frameworks\native\cmds\servicemanager\main.cpp
,main
函数我们再熟悉不过了,看下代码:
c++
int main(int argc, char** argv) {
//获取binder驱动名
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
//初始化Binder驱动
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
//设置最大线程数量
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
//新建ServiceManager对象
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
if (!manager->addService("manager", manager, false /*allowIsolated*/)
//将ServiceManager设置到IPCThreadState
IPCThreadState::self()->setTheContextObject(manager);
// !!成为ContextManager
ps->becomeContextManager();
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
//开启事件循环
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);
}
return EXIT_FAILURE;
}
进程启动之后,做这几件事情:
-
1、初始化Binder驱动
-
2、新建
ServiceManager
对象,并执行addService
方法 -
3、将
ServiceManager
设置到IPCThreadState
-
4、成为ContextManager
-
5、开启事件循环
2.2.1 initWithDriver
initWithDriver
与我们上一次分析的init
方法实际上区别不大
2.2.2 ServiceManager
初始化
c++
ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access))
平平无奇,下一个
2.2.3 addService
c++
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
auto ctx = mAccess->getCallingContext();
//异常逻辑,省略
// Overwrite the old service if it exists
mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
};
}
异常逻辑省略,主要是存到mNameToService
中,方面后面获取
2.2.4 becomeContextManager
c++
bool ProcessState::becomeContextManager()
{
AutoMutex _l(mLock);
flat_binder_object obj {
.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
};
//只看这个
int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
// fallback to original method
if (result != 0) {
android_errorWriteLog(0x534e4554, "121035042");
int unused = 0;
result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);
}
return result == 0;
}
我们只关注第一个ioctl
,这里调用到Binder驱动中,关键字为BINDER_SET_CONTEXT_MGR_EXT
:
c++
case BINDER_SET_CONTEXT_MGR_EXT:
{
struct flat_binder_object fbo;
if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
ret = -EINVAL;
goto err;
}
ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
if (ret)
goto err;
break;
}
看一下binder_ioctl_set_ctx_mgr
:
c++
static int binder_ioctl_set_ctx_mgr(struct file *filp,
struct flat_binder_object *fbo)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
struct binder_context *context = proc->context;
struct binder_node *new_node;
kuid_t curr_euid = current_euid();
//创建Binder节点
new_node = binder_new_node(proc, fbo);
//修改引用计数
new_node->local_weak_refs++;
new_node->local_strong_refs++;
new_node->has_strong_ref = 1;
new_node->has_weak_ref = 1;
//将new_node设置为binder_context_mgr_node
context->binder_context_mgr_node = new_node;
binder_put_node(new_node);
return ret;
}
-
1、创建Binder节点
-
2、修改节点的引用计数
-
3、设置该节点为
binder_context_mgr_node
,后续其他进程正是用这个来访问servicemanager
的
在这里我们又看到两个数据结构binder_node
与binder_context
:
图2.1 - binder_node的结构
c++
struct binder_context {
struct binder_node *binder_context_mgr_node;
struct mutex context_mgr_node_lock;
kuid_t binder_context_mgr_uid;
const char *name;
};
binder_context
结构相对比较简单。主要是保存binder_context_mgr_node
的地址,也就是servicemanager
。
至此,我们将servicemanager
设置给了驱动层,后面的操作就可以通过引用binder_context_mgr_node
来完成了。
2.2.5 BinderCallback::setupTo
说完了becomeContextManager
,我们回头看下最后一段逻辑,首先是创建一个Looper
,Looper
我们知道是消息循环机制,然后看BinderCallback::setupTo
:
c++
static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
sp<BinderCallback> cb = sp<BinderCallback>::make();
int binder_fd = -1;
//获取Binder驱动的fd
IPCThreadState::self()->setupPolling(&binder_fd);
//添加对Binder驱动fd的监听
int ret = looper->addFd(binder_fd,
Looper::POLL_CALLBACK,
Looper::EVENT_INPUT,
cb,
nullptr /*data*/);
return cb;
}
int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
IPCThreadState::self()->handlePolledCommands();
return 1; // Continue receiving callbacks.
}
我们知道looper
使用的是epoll
机制,在收到事件的时候,就会触发这里的handleEvent
,最终进入handlePolledCommands
:
c++
status_t IPCThreadState::handlePolledCommands()
{
status_t result;
do {
//循环与Binder驱动通信
result = getAndExecuteCommand();
} while (mIn.dataPosition() < mIn.dataSize());
processPendingDerefs();
flushCommands();
return result;
}
在没有事情做的时候,这个线程就会睡眠,等有事件过来,线程就被唤醒,然后开始从Binder驱动中读取数据,具体的交互逻辑我们在后面分析。
三、总结
servicemanager
作为一个单独的进程存在,为其他的进程提供服务,servicemanager
在启动之后,将创建出来的对象地址设置到Binder驱动层,然后进入循环,等待Binder驱动的唤醒,servicemanager
初始化完毕。
图3.1 - ServiceManager初始化时序图