Binder: ServiceManager的获取
source link: https://mp.weixin.qq.com/s?__biz=MzIzNTc5NDY4Nw%3D%3D&%3Bmid=2247485536&%3Bidx=1&%3Bsn=ede4bc6f83ae86e482015f435da1f825
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
点
击
蓝
字
关
注
我
们
吧
在Binder纯理论分析中介绍了 Binder
的整个通信流程。
下面我们直接通过 Service
的注册来了解一下 Binder
的具体工作原理。
我们以 MediaService
为例,来看下 service
的注册过程。 MediaService
对应的启动文件在 main_mediaserver.cpp
中的 main
方法。
frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(defaultServiceManager()); ALOGI("ServiceManager: %p", sm.get()); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); registerExtensions(); ::android::hardware::configureRpcThreadpool(16, false); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); ::android::hardware::joinRpcThreadpool(); }
ProcessState
首先创建了 ProcessState
,它使用了 sp
的强引用类型。
ProcessState::self
内部是一个单例,如果为空它会创建 ProcessState
对象
ProcessState::ProcessState(const char *driver) : mDriverName(String8(driver)) , mDriverFD(open_driver(driver)) // 启动binder驱动 , mVMStart(MAP_FAILED) , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER) , mThreadCountDecrement(PTHREAD_COND_INITIALIZER) , mExecutingThreadsCount(0) , mWaitingForThreads(0) , mMaxThreads(DEFAULT_MAX_BINDER_THREADS) // 设置最大线程数 , mStarvationStartTimeMs(0) , mThreadPoolStarted(false) , mThreadPoolSeq(1) , mCallRestriction(CallRestriction::NONE) { if (mDriverFD >= 0) { // 映射虚拟内存地址 mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) { // *sigh* ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str()); close(mDriverFD); mDriverFD = -1; mDriverName.clear(); } } LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver); }
上面是 ProcessState
的实例化过程,主要有以下三个重要的设置。
-
open_driver(driver): 启动
binder
驱动 -
mMaxThreads(DEFAULT_MAX_BINDER_THREADS): 设置最大线程数16
-
mmap: 映射虚拟内存地址
static int open_driver(const char *driver) { // 打开binder驱动 int fd = open(driver, O_RDWR | O_CLOEXEC); if (fd >= 0) { int vers = 0; // 通过ioctl与binder驱动交互,获取binder版本信息 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(%d) does not match user space protocol(%d)! ioctl() return value: %d", vers, BINDER_CURRENT_PROTOCOL_VERSION, result); 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 '%s' failed: %s\n", driver, strerror(errno)); } return fd; }
在 open_driver
中通过 open
打开 binder
驱动,在 binder
驱动中对应的方法是 binder_open
,它会创建 binder_proc
对象,并将进程等相关信息保存到 binder_proc
对象中,并返回 fd
文件描述符。
在 Linux
中通过 ioctl
方法与设备进行交互,获取 binder
的版本信息,同时设置 binder
的最大线程数16。在 binder
驱动中对应的是 binder_ioctl
方法,该方法主要通过 fd
文件描述符、 ioctl
命令与数据类型来传递数据。
在 ProcessState
创建的过程中,会通过 mmap
方法,在 binder
驱动中对应的是 binder_mmap
方法,将内核中同一块物理内存分别映射到内核的虚拟内存地址空间与用户的虚拟内存地址空间,保证内核空间 buffer
与用户空间 buffer
的同步操作。
以上就是 ProcessState
的主要流程。
下面继续 main
方法中的下一步操作。
BpServiceManager
sp<IServiceManager> sm(defaultServiceManager());
获取 IServiceManager
对象,所以我们进入 defaultServiceManager
方法
sp<IServiceManager> defaultServiceManager() { std::call_once(gSmOnce, []() { sp<AidlServiceManager> sm = nullptr; while (sm == nullptr) { // 重要方法,获取ServiceManager sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr)); if (sm == nullptr) { ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str()); sleep(1); } } gDefaultServiceManager = new ServiceManagerShim(sm); }); return gDefaultServiceManager; }
在该方法中我们发现它会通过 interface_cast
来获取 sm
,这里的 AidlServiceManager
本质就是 IServiceManager
。我们先把这个方法放一放,先看下它的参数获取
ProcessState::self()->getContextObject(nullptr)
嗯,又看到了 ProcessState::self()
,前面已经分析了,它就是一个 ProcessState
单例,所以直接看 getContextObject
方法
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/) { sp<IBinder> context = getStrongProxyForHandle(0); if (context == nullptr) { ALOGW("Not able to get context object on %s.", mDriverName.c_str()); } internal::Stability::tryMarkCompilationUnit(context.get()); return context; }
返回了 IBinder
,这是我们第一次看到 IBinder
,感觉有点眉目了,继续看 getStrongProxyForHandle(0)
,注意它这里传了一个参数 0
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != nullptr) { IBinder* b = e->binder; if (b == nullptr || !e->refs->attemptIncWeak(this)) { if (handle == 0) { Parcel data; // 数据传输 status_t status = IPCThreadState::self()->transact( 0, IBinder::PING_TRANSACTION, data, nullptr, 0); if (status == DEAD_OBJECT) return nullptr; } // 创建BpBinder b = BpBinder::create(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result; }
IPCThreadState::self()
也是一个单例,通过它的 transact
方法向远端发送数据,关于数据的发送本期不分析,所以我们暂且跳过。
继续,创建了 BpBinder
,并将 handler = 0
传给它,最终通过 result
返回的就是 BpBinder(0)
,此时已经获取到了 IBinder
,作为跨进程通信的载体。
所以我们向上回退,回到最初的地方 interface_cast
,现在已经知道它的参数其实就是 BpBinder(0)
,即 interface_cast(BpBinder(0))
。
现在就只剩下 interface_cast
了,只要我们解开它就能知道 ServiceManager
是如何创建并获取的。
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
发现它调用了 INTERFACE
的 asInterface
方法,那么 INTERFACE
又是什么呢?
找了一圈发现它居然是一个模板,声明如下
#define DECLARE_META_INTERFACE(INTERFACE) public: 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(); static bool setDefaultImpl(std::unique_ptr<I##INTERFACE> impl); static const std::unique_ptr<I##INTERFACE>& getDefaultImpl(); private: static std::unique_ptr<I##INTERFACE> default_impl
这里的 INTERFACE
就是 ServiceManager
,在模板声明中看到了我们所要的 asInterface
。
下面再看模板函数的具体实现
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME)); const ::android::String16 I##INTERFACE::descriptor( I##INTERFACE##_descriptor_static_str16); 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 != nullptr) { intr = static_cast<I##INTERFACE*>( obj->queryLocalInterface( I##INTERFACE::descriptor).get()); if (intr == nullptr) { intr = new Bp##INTERFACE(obj); } } return intr; } ...
将 INTERFACE
替换成 ServiceManager
来看,最终通过 asInterface
返回的是 BpServiceManager
对象,同时它的参数 obj
对应的就是之前的 BpBinder(0)
。
搞明白这个之后,再回到最初的地方(希望没有晕),对应的就是 defaultServiceManager
方法。
所以每次调用 defaultServiceManager
其实就是返回 BpServiceManager(BpBinder(0))
对象。
最后我们再来看下 BpServiceManager
,它在 IServiceManager.cpp
就申明的
class BpServiceManager : public BpInterface<IServiceManager> { public: explicit BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(impl) { } virtual sp<IBinder> getService(const String16& name) const { ... } virtual sp<IBinder> checkService( const String16& name) const { ... } virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated, int dumpsysPriority) { ... } ... };
它提供了 addService
与 getService
方法,暂时不分析,但可以大胆猜一下,应该是通过 BpServiceManager
的这些方法来注册与获取对应的 Service
。至于它内部又是如何传递到 ServiceManager
我们后续再分析。
回到最初的 main
方法,我们接下来应该就是
MediaPlayerService::instantiate(); void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); }
再来看 instantiate
就简单许多了,它通过 defaultServiceManager
向其中注册了名称为 media.player
的 MediaPlayerService
服务。
而 defaultServiceManager
对应的是 BpServiceManager(BpBinder(0))
,所以上面我们的猜想是成立的。关于服务的注册、验证与获取都是通过 BpServiceManager
代理完成的,其实内部最终都是通过 BpBinder(0)
来传输的。
好了,为了尽量缩短篇幅,降低阅读疲劳,提升读者体验,这篇文章就分析到这里。
下面来总结一下 MediaService
所做的一部分核心内容
-
创建
ProcessState
对象 -
ProcessState binder ioctl binder binder mmap
-
IPCThreadState transact server
-
创建
BpBinder
对象,获取IBinder
,作为跨进程通信的载体 -
创建
BpServiceManager
对象,作为服务注册、检验与获取的代理
福 利
为了感谢大家大支持,我特意搞了一个粉丝抽奖福利,只需在公众号后台回复【Android补给站,必出精品】关键字,即可获取二维码进行抽奖,小憩提前预祝大家中奖。
扫码二维码
获取更多精彩
壹伴编辑器
点个 在看 你最好看
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK