Binder 框架 -- binder 用户空间框架
一 ServiceManager 启动
int main(int argc, char **argv)
{
struct binder_state *bs;
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
......
binder_loop(bs, svcmgr_handler);
return 0;
}
1. 打开binder 设备
bs = binder_open(128*1024); 打开binder 设备驱动。相关的信息保存在binder_state 结构中。
struct binder_state
{
int fd; binder 设备的fd
void *mapped; 映射到用户空间的地址
size_t mapsize; 大小
};
struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
......
}
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
return bs;
}
binder_open 中做的工作主要是打开binder 设备,然后通过mmap 将binder内核空间映射到用户空间。标准的linux 设备访问方法:
- open("/dev/binder", O_RDWR | O_CLOEXEC); 打开设备
- ioctl(bs->fd, BINDER_VERSION, &vers) ioctl 命令设置版本号。 在下面对binder 驱动的访问中主要是通过 ioctl 函数,没有用我们常见的 read write, 这个也是binder 驱动设计的一个特点
- mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 内核空间mapsize大小映射到用户空间,注意映射的空间是只读权限。
- 设备的文件描述符, 用户空间地址, 大小用binder_state结构体保存。
2. binder_become_context_manager 通知binder驱动成为管理者。
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
注意最后一个参数为0;函数设计上可能是为了表示ServiceManager hander为0.但是在驱动中收到的消息为BINDER_SET_CONTEXT_MGR,已经表示是表示ServiceManager自己,直接把自己的 hander置为0,没有使用这个参数。ServiceManager 本身管理服务的特殊性,没有其它进程负责它的注册,ServiceManager需要自己完成注册,同时自己的handler 为0.
3. binder_loop 进入循环
binder_loop调用的时候同时传入回调函数。
- binder_write(bs, readbuf, sizeof(uint32_t)); 调用 ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 通知binder 驱动进入循环。这次调用没有阻塞。
- 在 for 循环中的 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 阻塞,当有消息来得时候,读出数据,交给binder_parse解析同时指定svcmgr_handler func处理解析数据。
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = ;
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;
}
}
}
4. svcmgr_handler 处理信息
svcmgr_handler func 函数指针指向svcmgr_handler
信息主要有这几个类型:
- SVC_MGR_GET_SERVICE 获取服务
- SVC_MGR_CHECK_SERVICE 检查服务
- SVC_MGR_ADD_SERVICE 添加服务,如mediaservice 添加就会到这里
- SVC_MGR_LIST_SERVICES 主要是 service list 命令使用
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
......
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
uint32_t n = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
5 servicemanager 是一单线程,
可能因为是工作不太繁忙,不需要多线程加班。
ps -t | grep servicemanager
system 2450 1761 10228 752 ffffffff f7685976 S /system/bin/servicemanager
servicemanager 已经启动,并且在一个while 循环中阻塞,等待唤醒。
ProcessState
ProcessState 是单例模式,每个进程只有一个实例。ProcessState在构造函数中会打开binder 驱动获取文件描述符mDriverFD,设置binder的参数,为进程进行binder 通信准备必要的条件。
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
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(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
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 | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
}
} else {
}
return fd;
}
open_driver 函数和binder_open 差不多,打开设备驱动,设置版本号并检查, 然后设置BINDER_SET_MAX_THREADS ,支持的最大线程数。
- open("/dev/binder", O_RDWR | O_CLOEXEC);
- octl(fd, BINDER_VERSION, &vers);
- ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
- 最后在构造函数中mmap。 为什么不在 open_driver 中一起把这个事情给做了呢?从API调用的角度放在一起比较合适吧。
startThreadPool 函数
从名字上看启动一个线程池,创建一个新的线程,spawnPooledThread isMain 参数为true,new了一个PoolThread,然后run函数 启动threadLoop(),在threadLoop 调用 IPCThreadState::self()->joinThreadPool(mIsMain); 对线程调用的封装,具体可以参考线程使用的方法。
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
IPCThreadState
IPCThreadState 是一个线程单例模式
IPCThreadState 是一个看似单例却不是单例的类。主要涉及了线程的局部存储,看下self 的实现:
第一次进来 gHaveTLS == false 所以走下边的代码:
- if (pthread_key_create(&gTLS, threadDestructor) != 0)
创建线程的局部存储然后goto 到 restart; - 调用pthread_getspecific,由于线程的局部key k还没有关联变量这是返回值为空;所以
new IPCThreadState;看到这里很疑惑,创建了线程的局部存储key 却没有变量存储到线程的局部存储里面,直接new 了一个IPCThreadState,和self 函数名也不匹配,搞什么鬼呢。 - 继续看IPCThreadState的构造函数:这下明白了 在构造函数里面IPCThreadState把自己作为线程的局部存储
pthread_setspecific(gTLS, this); - 如果是第二次进来 gHaveTLS == true.直接pthread_getspecific 获取IPCThreadState自身。
IPCThreadState 是一个线程单例模式, 持有两个类型为Parcel 的变量
class IPCThreadState{
......
private:
Parcel mIn;
Parcel mOut;
}
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}
if (gShutdown) return NULL;
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
if (pthread_key_create(&gTLS, threadDestructor) != 0) {
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
IPCThreadState::joinThreadPool
在上面的ProcessState::startThreadPool() 中调用了IPCThreadState::joinThreadPool 那这个函数到底干了什么呢。
- 首先根据是否主线程 mOut.writeInt32,注意参数为BC_ENTER_LOOPER 或者BC_REGISTER_LOOPER 这个后边分析。
- 在一个循环中不停的getAndExecuteCommand。
- 在getAndExecuteCommand 首先talkWithDriver, 然后executeCommand,和ServiceManager 类似,在一个循环中不停的读取binder 驱动,然后解析数据。
到这里其实服务端和客户端的交互框架已经建立。在后边的MediaPlayerService中看下具体的细节。
void IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
status_t result;
do {
......
result = getAndExecuteCommand();
......
} while (result != -ECONNREFUSED && result != -EBADF);
......
}
status_t IPCThreadState::getAndExecuteCommand()
{
status_t result;
int32_t cmd;
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
result = executeCommand(cmd);
......
}
}
return result;
}
Binder 通信架构
Android 为了便于使用Binder 通信,提供了一套框架,只要继承这个框架的各个类,就能够实现一个Binder通信服务。主要分为代理端和服务端。代理端和服务端通的通信通过 IInterface BpInterface BnInterface IBinder BpBinder BBinder 这几个模板类进行。
binder 下的相关类类图:
MediaPlayerService 启动
ServiceManager 单独运行在一个进程中,其它的Android系统服务如MediaPlayerService 如何启动和注册呢,在ServiceManager 的启动过程中分析到有一个 SVC_MGR_ADD_SERVICE 处理流程,在while 循环中已经阻塞。在上面分析IPCThreadState::joinThreadPool 的时候也会在循环中阻塞,根据linux 进程间通信的知识,双方应该互相发送数据唤醒对方。在这里就是MediaPlayerService 进程和ServiceManager 相互交互了,MediaPlayerService 对它的Client 来说是一个服务端,但是对ServiceManager 来说是一个客户端。
MediaPlayerService 同样基于上面的Binder通信框架,继承了相关的子类。
看一下MediaPlayerService 的启动代码。
int main(int argc __unused, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
defaultServiceManager
调用 sp<IServiceManager> sm = defaultServiceManager()获取ServiceManger 的代理; 函数定义在IServiceManager.cpp 中
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;
}
ProcessState::getStrongProxyForHandle
- 依次调用ProcessState 的 getContextObject ->
-
getStrongProxyForHandle 函数,参数为0,
首先查表 lookupHandleLocked。注意BpBinder.mHander = 0;
ProcessState 为单例模式,持有一个 Vector<handle_entry>mHandleToObject对象,进程中所有的Binder 对象都会添加到这个容器中。由于是是第一次查找,mHandleToObject为空,lookupHandleLocked会添加一个未初始化过的handle_entry对象,所以e->binder == NULL。
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
e.binder = NULL;
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle);
}
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
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;
}
e->binder == NULL handle == 0 条件成立,经过下面两步调用
status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, NULL, 0);
b = new BpBinder(handle);
变成了
gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
其中ServiceManager 的hander 为0,
transact 函数第一个参数为0,表示的是传递给 handle 为0 的Service,就是ServiceManager,
interface_cast 以及DECLARE_META_INTERFACE IMPLEMENT_META_INTERFACE
interface_cast 以及DECLARE_META_INTERFACE IMPLEMENT_META_INTERFACE 这几个宏定义在
IInterface.h 中。
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
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(); \
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() { } \
替换掉INTERFACE 变成了, 这段代码变成了:
android::sp<IServiceManager> interface_cast<IServiceManager>(const sp<IBinder>& obj){
return IServiceManager::asInterface(obj);
}
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) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
BpBinder(0)->queryLocalInterface, queryLocalInterface 为IBinder 的虚函数,默认返回空值,BpBinder 继承IBinder,并且没有覆盖queryLocalInterface。所以sp<IServiceManager> sm = defaultServiceManager()实际是这个样子:
sp<IServiceManager> sm = new BpServiceManager(obj);
这段代码就是为了拿到ServiceManager的BpServiceManager. 当中在线程中做了记录,然后对引用计数做了处理,通过transact 通知了ServiceManager 。这样我们就拿到了ServiceManger 的客户端BpServiceManager。代码好绕,有没有看到其他的代码使用这个机制?
MediaPlayerService 注册到 ServiceManger
再回到MediaPlayerService 初始化的代码:
int main(int argc __unused, char** argv)
{
......
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
。。。。。。
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
MediaPlayerService::instantiate
调用 MediaPlayerService::instantiate();
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
defaultServiceManager() 返回的结果就是BpServiceManager,所以这段代码变成了:
void MediaPlayerService::instantiate() {
BpServiceManager()->addService(String16("media.player"), new MediaPlayerService());
}
BpServiceManager()->addService
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
在 remote 就是在new BpServiceManager 中穿进去的BpBinder(0)。
BpBinder 的 transact
BpBinder 的 transact 函数如下:
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
IPCThreadState transact 先后调用了writeTransactionData 和 waitForResponse, writeTransactionData中把binder 相关的通信数据写入binder 驱动。然后呢,然后呢,其实在一开始ServiceManger 已经在binder_loop 中阻塞了,现在写入binder 驱动数据,binder_loop会被激活,读出数据 解析,然后ServiceManger 向bindr 驱动注册Service,将结果写入reply 参数。waitForResponse 读取reply 结果。通信完成,MediaPlayService 注册完成。
启动线程池
在最后先后调用了,根据上面的分析,startThreadPool 最后也调用了joinThreadPool。也就是启动了两个线程。
ProcessState::self()->startThreadPool(); //启动子线程
IPCThreadState::self()->joinThreadPool(); //主线程循环
在LoopThread 反复调用 joinThreadPool 函数做如下工作:
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result;
cmd = mIn.readInt32();
result = executeCommand(cmd);
......
}
}
有一个疑问,为什么需要两个线程?
总结:
- ProcessState.self() 建立实例
- defaultServiceManager()
- ProcessState::self()->getContextObject(nuLl)->ProcessState::self()->getStrongProxyForHandle(0)-> New BpBinder(0)
- interface_cast(BpBinder(0))->asInterface(BpBinder(0)) -> new BpServiceManager(BpBinder(0));
- 依次调用 BpServiceManger::addService ->BpBinder::transact->IPCThreadState::self()->transact 通知服务端
- IPCThreadState::waitForResponse 等待服务端返回。
- 启动线程池
调用序列图:
为什么需要两个线程,在需要用到回调函数的Binder通信中,在BnClass::doSome 是有callback ,而此时BpClass 进程中只有一个线程,这个线程正在waitRespose,而无法响应callback , 就会造成异常。