前言
本章主要围绕 ServiceManager 进行讲解,通过注册、启动等流程,玩转 ServiceManager;
ServiceManager 是什么?
客户端想要调用系统的 AMS 或者 PMS,但是客户端直接调用不到,只能获取到 AMS-IBinder 对象,AMS 在启动的时候就会把 AMS-IBinder 对象注册到 ServiceManager 中,客户端只要找到 ServiceManager 之后,就可以把 AMS-IBinder 对象返回给客户端,客户端就可以通过 AMS-IBinder 同 AMS 进行通信;
ServiceManager 它也是一个服务,但是它的句柄是确认的,也就是 handle = 0,而我们客户端在调用系统服务的时候,只需要调用这个已知道的 handle = 0 的服务就可以获取到 ServiceManager 的代理对象,然后就可以 同其他系统服务通信了;
ServiceManager 服务是如何注册的?
那么 ServiceManager 是怎么注册的呢?我们进入源码看一下,它的注册就在 init.rc 中:
sql
// 打开 ServiceManager 这个程序,就会 调用 ServiceManager 的 main 方法
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
打开 ServiceManager 这个程序,就会 调用 servicemanager.c 的 main 方法,我们进入 main 方法看下:
scss
int main(int argc, char **argv)
{
struct binder_state *bs;
// 这个方法做了两件事情,一是 open 方法,打开 binder 驱动,二是 mmap 方法,建立映射关系
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
// 把 ServiceManager 设置成服务大管家
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
abort();
}
if (getcon(&service_manager_context) != 0) {
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
abort();
}
}
union selinux_callback cb;
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
// 循环监听有没有其他服务访问
binder_loop(bs, svcmgr_handler);
return 0;
}
binder_open 这个方法做了两件事情,一是 open(128*1024) 方法,打开 binder 驱动,二是 mmap 方法,建立映射关系;
binder_become_context_manager 把 ServiceManager 设置成服务大管家;
binder_loop 循环监听有没有其他服务访问;
我们进入 binder_become_context_manager 这个方法看下,它是如何成为大管家的
arduino
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
直接调用的 ioctl 方法,传入的参数是 BINDER_SET_CONTEXT_MGR,而 这个方法最终调用到 binder_ioctl 中,我们进入 BINDER_SET_CONTEXT_MGR 这个 case 看下:
ini
case BINDER_SET_CONTEXT_MGR:
ret = binder_ioctl_set_ctx_mgr(filp);
if (ret)
goto err;
break;
这个 case 中调用的是 binder_ioctl_set_ctx_mgr,我们进入这个方法看下:
ini
static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
struct binder_context *context = proc->context;
kuid_t curr_euid = current_euid();
// 先判断是不是已经存在了,存在则直接返回
if (context->binder_context_mgr_node) {
pr_err("BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
goto out;
}
ret = security_binder_set_context_mgr(proc->tsk);
if (ret < 0)
goto out;
// 判断 sm 的 uid 是否是有效的,第一次肯定是无效的,所以直接进入 else
if (uid_valid(context->binder_context_mgr_uid)) {
if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
from_kuid(&init_user_ns, curr_euid),
from_kuid(&init_user_ns,
context->binder_context_mgr_uid));
ret = -EPERM;
goto out;
}
} else {
// 设置 uid
context->binder_context_mgr_uid = curr_euid;
}
// 通过 binder_new_node 创建 SM 的 binder_context_mgr_node 结构体
context->binder_context_mgr_node = binder_new_node(proc, 0, 0);
if (!context->binder_context_mgr_node) {
ret = -ENOMEM;
goto out;
}
context->binder_context_mgr_node->local_weak_refs++;
context->binder_context_mgr_node->local_strong_refs++;
context->binder_context_mgr_node->has_strong_ref = 1;
context->binder_context_mgr_node->has_weak_ref = 1;
out:
return ret;
}
到这里,就把 ServiceManager 设置成了大管家;
我们接下来看下 binder_loop 这个方法:
ini
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
// 结构体,这个结构体中有读和写,以及buffer
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
// BC_ENTER_LOOPER 是一个命令,进入循环的命令
readbuf[0] = BC_ENTER_LOOPER;
// 执行 binder_write 把 buffer 放进去,内部执行 ioctl 方法,最终调用到 binder_ioctl_write_read 方法
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
if (res == 0) {
ALOGE("binder_loop: unexpected reply?!\n");
break;
}
if (res < 0) {
ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
break;
}
}
}
// 执行 binder_write 把 buffer 放进去,内部执行 ioctl 方法,最终调用到 binder_ioctl_write_read 方法,我们进入这个方法看下:
ini
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto out;
}
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
binder_debug(BINDER_DEBUG_READ_WRITE,
"%d:%d write %lld at %016llx, read %lld at %016llx\n",
proc->pid, thread->pid,
(u64)bwr.write_size, (u64)bwr.write_buffer,
(u64)bwr.read_size, (u64)bwr.read_buffer);
// 两个 if 来判断是要执行 read 还是 write 方法
if (bwr.write_size > 0) {
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
if (bwr.read_size > 0) {
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size,
&bwr.read_consumed,
filp->f_flags & O_NONBLOCK);
trace_binder_read_done(ret);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto out;
}
}
binder_debug(BINDER_DEBUG_READ_WRITE,
"%d:%d wrote %lld of %lld, read return %lld of %lld\n",
proc->pid, thread->pid,
(u64)bwr.write_consumed, (u64)bwr.write_size,
(u64)bwr.read_consumed, (u64)bwr.read_size);
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
ret = -EFAULT;
goto out;
}
out:
return ret;
}
bwr.write_size > 0 执行 write 或者 bwr.read_size > 0 执行 read 操作,我们进入 write 的操作看下,这个方法最终执行的命令是我们前面看到的 BC_ENTER_LOOPER 这个命令,我们直接进入这个 case 看下
rust
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 设置了一个状态
thread->looper |= BINDER_LOOPER_STATE_ENTERED;
break;
其实就做了一件事情,给当前 thread 的 looper 设置了一个状态;
我们接着回到 binder_loop 方法往下看,下面一个是 for(;;) 无限循环,这里依然调用的是 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 这个方法,只是 case 传递了 BINDER_WRITE_READ,我们继续进入这个方法看下,最终进入的是 binder_thread_read 方法,这个方法 最终调用到 ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); 进入等待状态了
scss
if (wait_for_proc_work) {
if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED))) {
binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",
proc->pid, thread->pid, thread->looper);
wait_event_interruptible(binder_user_error_wait,
binder_stop_on_user_error < 2);
}
binder_set_nice(proc->default_priority);
if (non_block) {
if (!binder_has_proc_work(proc, thread))
ret = -EAGAIN;
} else {
// binder 是阻塞的,所以最终进入到这里
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
}
}
SM 的注册还是比较简单的,一共就三步,第一步是 binder_open,第二步是 binder_become_context_manager(成为大管家,也叫设置为守护进程),第三步是 binder_loop
整体就是图上 1 、2 、3 三个步骤;
ServiceManager 服务是如何获取的
我们接下来看下 SM 是如何获取的;获取 SM 的情况一般是两种,一种是注册服务到 SM,一种是通过 SM 去获取服务,这两种都需要拿到 SM 才能实现;SM 的 native 层获取一般是在 IServiceManager.cpp 中,我们进入这个文件看下
scss
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
native 层的获取 SM 都是从这里执行的,首先是一个单例,然后一个 while 循环来获取 SM,如果获取不到会进行一个休眠等待,主要的获取逻辑在下面这行代码
css
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
self()
我们来逐步分析这个方法都做了什么,首先我们来看下 ProcessState::self()->getContextObject(NULL) 这个参数都做了什么操作;
首先是 self 方法,我们进入这个 self 方法看下做了什么
php
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
很简单,就是 new ProcessState 并返回,创建这个 ProcessState 的时候做了什么呢?我们进入构造函数看一下
scss
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted{
if (mDriverFD >= 0) {
// XXX Ideally, there should be a specific define for whether we
// have mmap (or whether we could possibly have the kernel module
// availabla).
#if !defined(HAVE_WIN32_IPC)
// 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;
}
#else
mDriverFD = -1;
#endif
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
第一步,是 open_driver() 通过 open 方法打开 binder 设备(驱动),并通过 maxThreads 设置最大线程数;
ini
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR);
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
我们接着看创建的逻辑,
ini
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
通过 mmap 设置共享内存, 1M-8K(普通服务的大小);可以看到有一个常量参数 BINDER_VM_SIZE 它的值就是 #define BINDER_VM_SIZE ((110241024) - (4096 *2));
所以这个 self() 方法做了三件事情,分别是:
- 打开驱动,open_driver() 方法;
- 设置最大线程数据,15;
- mmap,设置共享内存大小,1M-8K;
getContextObject(NULL)
我们接下来看下 getContextObject(NULL) 做了些什么?这个方法直接调用了
javascript
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
这个方法直接调用了 getStrongProxyForHandle(0) 传入了 0;我们进入这个方法看下都发生了什么?
ini
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
// 查找 handle 对应的资源线
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
// 测试 binder 是否已经准备就绪
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
// 创建 BpBinder 并返回;
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
这个方法就做了一件事情,就是创建 BpBinder,我们可以看下,在创建这个 BpBinider 的时候做了什么?
BpBinder
scss
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
// 主要是调用 incWeakHandle 做一个弱引用的计数
IPCThreadState::self()->incWeakHandle(handle);
}
所以 ProcessState::self()->getContextObject(NULL) 这个参数本质就是返回 BpBinder 对象;这个 BpBinder 对象就是指向服务端的代理对象,我们在这里就可以认为是 ServiceManager;
BpBinder 是 BBinder 的代理对象,这里可以认为它俩是一样的;
Java 层和 Native 层通信的时候,需要一个 BinderProxy 和 ServiceManagerProxy,ServiceManagerProxy 里面有一个 BinderProxy,这个 BinderProxy 指向 BpBinder,也就是说 Java 层需要拿到这个 BpBinder 才能通信,Java 通过操作 ServiceManagerProxy,而 ServiceManagerProxy 通过操作 Remote(BinderProxy),这个时候,这个 BinderProxy 它是 Java 层的,它要指向 Native 层的才能通信,而这个 Native 层的就是 BpBinder,这个 BpBinder 就是代理对象;
Native 层也需要获取 BpBinder,但是它与 Java 层的获取方式不同,它是通过操作 BpServiceManager ,而 BpServiceManager 可以直接操作 BpBinder,这就少了一步,Java 层和 Native 层都是 BpBinder,再由 BpBinder 进行 transac 进行通信
interface_cast
我们接下来看下这个 interface_cast 方法,这个方法传入的参数就是 BpBinder;
arduino
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
这个方法调用的是 INTERFACE::asInterface(obj),这里是一个泛型操作,所以最终调用的是 IServiceManager 的 asInterface(obj) 方法; 但是这个方法并不在 IServiceManager 这个文件中,它使用的模板放进行了一个宏定义,我们在找下这个宏定义
php
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
这里通过宏定义之后会进行一个替换,替换之后的 C++ 代码实现如下:
rust
static const android::String16 descriptor;
static android::sp< IServiceManager > asInterface(const
android::sp<android::IBinder>& obj)
virtual const android::String16& getInterfaceDescriptor() const;
IServiceManager ();
virtual ~IServiceManager();
该过程主要是声明asInterface(),getInterfaceDescriptor()方法,所以这里我们不用过多的关心;
我们接着看下面的宏定义以及替换之后的逻辑
less
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
替换之后的逻辑如下:
php
const android::String16
IServiceManager::descriptor("android.os.IServiceManager");
const android::String16& IServiceManager::getInterfaceDescriptor() const
{
return IServiceManager::descriptor;
}
android::sp<IServiceManager> IServiceManager::asInterface(const
android::sp<android::IBinder>& obj)
{
android::sp<IServiceManager> intr;
if(obj != NULL) {
intr = static_cast<IServiceManager *>(
obj->queryLocalInterface(IServiceManager::descriptor).get());
if (intr == NULL) {
// 等价于 new BpServiceManager(BpBinder)
intr = new BpServiceManager(obj);
}
}
return intr;
}
IServiceManager::IServiceManager () {}
IServiceManager::~ IServiceManager() {}
展开之后,我们主要关心的就是 asInterface 方法,这个方法具体做了什么,我们来看下:
这里就是创建了 BpServiceManager,构造方法中传入的 BpBinder,我们来看下它是怎么使用 BpBinder 的;
BpServiceManager
csharp
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
我们来看下 BpInterface
arduino
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
这里我们直接看 BpInterface 的继承 BpRefBase
scss
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
到此,我们就找到了 mRemote 它来操作 BpBinder,也就是对应的 java 层调用 mRemote.transact() 的时候,就是调用的 BpBinder.transact() 来进行通信;
所以这个方法也是做了三件事情
- new BpServiceManager(new BpBinder)
- remote.transcat() 远程调用
- remote = BpBinder
到此,ServiceManager 的注册与获取就写完了;
下一章预告
进程通信注册与获取服务及线程池讲解
欢迎三连
来都来了,点个关注点个赞吧,你的支持是我最大的动力~~~