Android之IPC5————Binder2 Native层分析
文章目录
- Android之IPC5————Binder2 Native层分析
一.前言
在上一篇里,我们介绍了binder机制的简单介绍,以及binder内核,ServiceManager的启动。
在上一篇也简单提过,ServiceManager的作用,即注册服务,和获取服务。
在这一篇中,我们中 主要分析native层,主要分析其注册服务和获取服务的过程,大致流程就是获取BpServiceManager,通过它来和Binder驱动进行通信,ServiceManager在死循环中读写事物,对注册服务和获取服务进行处理,并将结果返回给Binder驱动,binder驱动在将结果返回给客户端或服务端。
本篇文章主要以下面几个方面展开:
- 获取BpServiceManager
- Native层的注册服务和获取服务
- Binder内核中的注册服务和获取服务
- ServiceManager中的注册服务和获取服务的
二.获取BpServiceManager
1.概述
BpServiceManagerton通过接口IServiceManager实现了接口中的业务逻辑函数(获取服务,注册服务),并通过成员变量mRemote= new BpBinder(0)进行Binder通信工作
获取BpServiceManager是通过defaultServiceManager()方法来完成,当进程注册服务(addService)或 获取服务(getService)的过程之前,都需要先调用defaultServiceManager()方法来获取gDefaultServiceManager对象。对于gDefaultServiceManager对象,如果存在则直接返回;如果不存在则创建该对象
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;
}
上面就是获取BpServiceManager的过程
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
上面这行代码就是关键代码,分为3步,即
- ProcessState::self(),获取ProcessState对象,也是单例
- getContextObject:获取BpBinder,对于handle = 0的BpBinder对象,存在直接返回,否则创建
- 获取BpServiceManager对象
2.获取ProcessState对象
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
//实例化ProcessState 【见小节2.2】
gProcess = new ProcessState;
return gProcess;
}
获取ProcessState对象,也是单例模式.
ProcessState的初始化
ProcessState::ProcessState()
: mDriverFD(open_driver()) // 打开Binder驱动【见小节2.3】
, 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) {
//采用内存映射函数mmap,给binder分配一块虚拟地址空间,用来接收事务
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
close(mDriverFD); //没有足够空间分配给/dev/binder,则关闭驱动
mDriverFD = -1;
}
}
在初始化时打开Binder设备,并设定binder支持的最大线程数,之后再使用mmap分配内存。
3.获取BpBinder对象
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
获取handle = 0的IBinder。
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;
//通过ping操作测试binder是否准备就绪
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//当handle值所对应的IBinder不存在或弱引用无效时,则创建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;
}
4.获取BpServiceManager
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
在源码中INTERFACE::asInterface(obj)使用宏的模的模拟代码。直接写出替换后的代码
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) {
intr = new BpServiceManager(obj);
}
}
return intr;
}
IServiceManager::IServiceManager () { }
IServiceManager::~ IServiceManager() { }
所有说IServiceManager::asInterface() 等价于 new BpServiceManager()。
接下来看BpServiceManager的初始化
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{ }
BpInterface的初始化
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
:BpRefBase(remote)
{ }
BpRefBase的初始化
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this);
mRefs = mRemote->createWeak(this);
}
}
new BpServiceManager(),在初始化过程中,比较重要工作的是类BpRefBase的mRemote指向new BpBinder(0),从而BpServiceManager能够利用Binder进行通过通信。
5.总结
defaultServiceManager 等价于 new BpServiceManager(new BpBinder(0));
在这个过程中:
- 调用open(),打开/dev/binder驱动设备;
- 再利用mmap(),创建大小为1M-8K的内存地址空间;
- 设定当前进程最大的最大并发Binder线程个数为16
- BpBinder通过handler来指向所对应BBinder, 在整个Binder系统中handle=0代表ServiceManager所对应的BBinder。
三.Native层的注册服务和获取服务
1.服务注册
我们以media服务注册为例
int main(int argc __unused, char** argv)
{
...
InitializeIcuOrDie();
//获得ProcessState实例对象
sp<ProcessState> proc(ProcessState::self());
//获取BpServiceManager对象
sp<IServiceManager> sm = defaultServiceManager();
AudioFlinger::instantiate();
//注册多媒体服务
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
registerExtensions();
//启动Binder线程池
ProcessState::self()->startThreadPool();
//当前线程加入到线程池
IPCThreadState::self()->joinThreadPool();
}
上面是native层中media服务注册的过程。
分为下面几个过程:
- 获取ProcessState对象
- 获取ServiceManager对象
- 注册服务
- 启动binder线程池
- 加入到线程池
在这其中,获取ProcessState对象和获取ServiceManager对象的过程,在上一小节。
我们主要来看其注册服务的过程。
void MediaPlayerService::instantiate() {
//注册服务
defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());
}
由上一小节可知 defaultServiceManager()返回的是BpServiceManager,所以相当于bpServiceManager调用addService。
BpSM.addService
virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated) {
Parcel data, reply; //Parcel是数据通信包
//写入头信息"android.os.IServiceManager"
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
// name为 "media.player"
data.writeStrongBinder(service);
// MediaPlayerService对象
data.writeInt32(allowIsolated ? 1 : 0);
// allowIsolated= false
//remote()指向的是BpBinder对象
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
可以看到,在addService中将Service对象和Service名都写入了data中。
之后调用BpBinder对象的transact方法。
2.获取服务
上面是media在native层注册服务的过程,下面介绍一下madia服务被获取的过程
sp<IMediaPlayerService>&
IMediaDeathNotifier::getMediaPlayerService()
{
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
sp<IServiceManager> sm = defaultServiceManager(); //获取ServiceManager
sp<IBinder> binder;
do {
//获取名为"media.player"的服务
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
usleep(500000); // 0.5s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier(); //创建死亡通知对象
}
//将死亡通知连接到binder
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
return sMediaPlayerService;
}
上面的代码就是请求获取为”media.player”的服务过程中,采用不断获取的过程。
也是先获BpServiceManager,然后调用BpServiceManager的getService方法。
来看其获取服务的代码
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name); //见下
if (svc != NULL) return svc;
sleep(1);
}
return NULL;
}
通过ServiceManager来获取服务,检索服务是否存在,存在直接返回,不存在时。暂停1s后,继续请求。最多5次
继续来看checkService(name)过程
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
//写入RPC头
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
//写入服务名
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); //见下
return reply.readStrongBinder(); //见下
}
可以看出了获取服务和注册服务一样,最终都调用了Bpdineder的transact。
3.注册服务中writeStrongBinder(service)
在注册服务中,将Service传入writeStrongBinder中
data.writeStrongBinder(service);
data是Parcel类。
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder(); //本地Binder不为空
if (!local) {
BpBinder *proxy = binder->remoteBinder();
const int32_t handle = proxy ? proxy->handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = 0;
obj.handle = handle;
obj.cookie = 0;
} else { //进入该分支
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
...
}
return finish_flatten_binder(binder, obj, out);
}
将Binder对象扁平化,转换成flat_binder_object对象。
- 对于Binder实体,则cookie记录Binder实体的指针;并且其类型为BINDER_TYPE_HANDLE
- 对于Binder代理,则用handle记录Binder代理的句柄,并且其类型为BINDER_TYPE_BINDER;
4.获取服务的readStrongBinder()
在获取服务中,最后返回的是:
return reply.readStrongBinder();
和data一样,reply也是Parcel类。
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
调用了 unflatten_binder
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) {
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
// 当请求服务的进程与服务属于同一进程
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
//请求服务的进程与服务属于不同进程
*out = proc->getStrongProxyForHandle(flat->handle);
//创建BpBinder对象
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
5.BpBinder.transact
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
在注册服务和获取服务中,最终都调用了上面这行代码。即BpBinder.transact方法。
BpBinder.transact
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
if (mAlive) {
// code=ADD_SERVICE_TRANSACTION
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
可以看出在 BpBinder::transact中最终调用的是IPCThreadState::self()->transact方法。
先来看看IPCThreadState的初始化过程和self过程
6. IPCThreadState的初始化
初始化:
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0)
{
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);//接收来自binder数据
mOut.setDataCapacity(256);//发往binder数据
}
self方法:
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; //初始IPCThreadState
}
if (gShutdown) return NULL;
pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) { //首次进入gHaveTLS为false
if (pthread_key_create(&gTLS, threadDestructor) != 0) { //创建线程的TLS
pthread_mutex_unlock(&gTLSMutex);
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}
在self中,对IPCThreadState进行了初始化,并创建了线程的TLS(线程本地存储空间)。
7.IPC.transact方法。
BpBinder::transact中最终调用的是IPCThreadState::self()->transact方法。
上一小节中,我们查看了IPCThreadState::self()过程,接下来继续查看其transact方法。
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck(); //数据错误检查
flags |= TF_ACCEPT_FDS;
....
if (err == NO_ERROR) { // 传输数据
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
...
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
//等待响应
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
//oneway,则不需要等待reply的场景
err = waitForResponse(NULL, NULL);
}
return err;
}
在上面的代码中主要有三个过程,即数据错误检查,传输数据和等待响应。下两个小节来看数据传输过程和等待响应过程。
8.IPC.writeTransactionData
writeTransactionData即传输数据过程
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.ptr = 0;
tr.target.handle = handle; // handle = 0
tr.code = code; // code = ADD_SERVICE_TRANSACTION
tr.flags = binderFlags; // binderFlags = 0
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
// data为记录Media服务信息的Parcel对象
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize(); // mDataSize
tr.data.ptr.buffer = data.ipcData(); //mData
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); //mObjectsSize
tr.data.ptr.offsets = data.ipcObjects(); //mObjects
} else if (statusBuffer) {
...
} else {
return (mLastError = err);
}
//cmd=BC_TRANSACTION
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr)); //写入binder_transaction_data数据
return NO_ERROR;
}
上面的handle值为用来标识,在注册服务和获取服务的过程中,目的端都是内核中的ServiceManager。
binder_transction_data是binder通信数据结构,最终是将Binder请求码和tr写入到mOut中。
接下来是waitForResponse()方法
9.IPC.waitForResponse
waitForResponse即IPCThreadState.transact中等待响应过程
tatus_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {
//【见下文】
if ((err=talkWithDriver()) < NO_ERROR) break;
...
if (mIn.dataAvail() == 0) continue;
cmd = mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE: ...
case BR_DEAD_REPLY: ...
case BR_FAILED_REPLY: ...
case BR_ACQUIRE_RESULT: ...
case BR_REPLY: ...
goto finish;
default:
err = executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
...
return err;
}
在waitForResponse中,先执行BR_TRANSACTION_COMPLET。另外,目标进程收到事物后,处理处理BR_TRANSACTION事务。 然后发送给当前进程,再执行BR_REPLY命令。
talkWithDriver()
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
...
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
if (doReceive && needRead) {
//接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
//当读缓冲和写缓冲都为空,则直接返回
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
//通过ioctl不停的读写操作,跟Binder Driver进行通信
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
...
} while (err == -EINTR); //当被中断,则继续执行
...
return err;
}
在talkWithDriver方法中,是真正与binder驱动进行交换数据的结构,操作mOut和mIn变量。
经过ioctl()经过系统调用后进入Binder内核.
10.总结
在这一小节中,我们以medie为例分析了Native注册服务和获取服务的过程。
- 即首先获得BpServiceManager对象,在调用ServiceManager对应的addService和gitService方法。在注册服务时,还要将当前线程放入binder线程池中。
- 两个方法都会去调用BpBinder的transact方法,但它只是一个代理方法。最终起用IPCThreadState的transact方法。
- IPCThreadState.transact方法中,首先会检查数据是否有误,通过ioctl和Binder内核进行数据传输。并等待响应。
四.Binder内核中的注册服务和获取服务
在上一节的最后,我们发现IPCThreadState通过ioctl和binder内核进行了通信。这一节中,我们看binder内核是如何处理注册服务和获取服务的。
ioctl -> binder_ioctl -> binder_ioctl_write_read
1.binder_ioctl_write_read
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
struct binder_proc *proc = filp->private_data;
void __user *ubuf = (void __user *)arg;
struct binder_write_read bwr;
//将用户空间bwr结构体拷贝到内核空间
copy_from_user(&bwr, ubuf, sizeof(bwr));
...
if (bwr.write_size > 0) {
//将数据放入目标进程[见下文]
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
...
}
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);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
...
}
//将内核空间bwr结构体拷贝到用户空间
copy_to_user(ubuf, &bwr, sizeof(bwr));
...
}
2.binder_thread_write
static int binder_thread_write(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed)
{
uint32_t cmd;
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
while (ptr < end && thread->return_error == BR_OK) {
//拷贝用户空间的cmd命令,此时为BC_TRANSACTION
if (get_user(cmd, (uint32_t __user *)ptr)) -EFAULT;
ptr += sizeof(uint32_t);
switch (cmd) {
case BC_TRANSACTION:
case BC_REPLY: {
struct binder_transaction_data tr;
//拷贝用户空间的binder_transaction_data
if (copy_from_user(&tr, ptr, sizeof(tr))) return -EFAULT;
ptr += sizeof(tr);
// 见下文
binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
break;
}
...
}
*consumed = ptr - buffer;
}
return 0;
}
3.binder_transaction
在经过内核中的调度后,最终调度到了binde_transaction方法中。binder_transaction方法代码非常长,所以仅展示和注册获取服务相关的操作。
对于flat_binder_object这个数据结构中,type类型
1.当type等于BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER类型时, 代表Server进程向ServiceManager进程注册服务,则创建binder_node对象;
2.当type等于BINDER_TYPE_HANDLE或BINDER_TYPE_WEAK_HEANDLE类型时, 代表Client进程向Server进程请求代理,则创建binder_ref对象;
3.当type等于BINDER_TYPE_FD类型时, 代表进程向另一个进程发送文件描述符,只打开文件,则无需创建任何对象。
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply){
struct binder_transaction *t;
struct binder_work *tcomplete;
...
if (reply) {
...
}else {
if (tr->target.handle) {
...
} else {
// handle=0则找到servicemanager实体
target_node = binder_context_mgr_node;
}
//target_proc为servicemanager进程
target_proc = target_node->proc;
}
if (target_thread) {
...
} else {
//找到servicemanager进程的todo队列
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
t = kzalloc(sizeof(*t), GFP_KERNEL);
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
//非oneway的通信方式,把当前thread保存到transaction的from字段
if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;
else
t->from = NULL;
t->sender_euid = task_euid(proc->tsk);
t->to_proc = target_proc; //此次通信目标进程为servicemanager进程
t->to_thread = target_thread;
t->code = tr->code; //此次通信code = ADD_SERVICE_TRANSACTION
t->flags = tr->flags; // 此次通信flags = 0
t->priority = task_nice(current);
//从servicemanager进程中分配buffer
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
t->buffer->allow_user_free = 0;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
if (target_node)
binder_inc_node(target_node, 1, 0, NULL); //引用计数加1
offp = (binder_size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
//分别拷贝用户空间的binder_transaction_data中ptr.buffer和ptr.offsets到内核
copy_from_user(t->buffer->data,
(const void __user *)(uintptr_t)tr->data.ptr.buffer, tr->data_size);
copy_from_user(offp,
(const void __user *)(uintptr_t)tr->data.ptr.offsets, tr->offsets_size);
off_end = (void *)offp + tr->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
off_min = *offp + sizeof(struct flat_binder_object);
switch (fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: { //注册服务
struct binder_ref *ref;
//【见4.3.1】
struct binder_node *node = binder_get_node(proc, fp->binder);
if (node == NULL) {
//服务所在进程 创建binder_node实体
node = binder_new_node(proc, fp->binder, fp->cookie);
...
}
//servicemanager进程binder_ref
ref = binder_get_ref_for_node(target_proc, node);
...
//调整type为HANDLE类型
if (fp->type == BINDER_TYPE_BINDER)
fp->type = BINDER_TYPE_HANDLE;
else
fp->type = BINDER_TYPE_WEAK_HANDLE;
fp->binder = 0;
fp->handle = ref->desc; //设置handle值
fp->cookie = 0;
binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
&thread->todo);
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
//这是ServiceManager对处理完之后,获取服务
struct binder_ref *ref = binder_get_ref(proc, fp->handle,
fp->type == BINDER_TYPE_HANDLE);
...
//此时运行在servicemanager进程,故ref->node是指向服务所在进程的binder实体,
//而target_proc为请求服务所在的进程,此时并不相等。
if (ref->node->proc == target_proc) {
if (fp->type == BINDER_TYPE_HANDLE)
fp->type = BINDER_TYPE_BINDER;
else
fp->type = BINDER_TYPE_WEAK_BINDER;
fp->binder = ref->node->ptr;
fp->cookie = ref->node->cookie; //BBinder服务的地址
binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
} else {
struct binder_ref *new_ref;
//请求服务所在进程并非服务所在进程,则为请求服务所在进程创建binder_ref
new_ref = binder_get_ref_for_node(target_proc, ref->node);
fp->binder = 0;
fp->handle = new_ref->desc; //重新赋予handle值
fp->cookie = 0;
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
}
} break;
case BINDER_TYPE_FD: ...
}
if (reply) {
..
} else if (!(t->flags & TF_ONE_WAY)) {
//BC_TRANSACTION 且 非oneway,则设置事务栈信息
t->need_reply = 1;
t->from_parent = thread->transaction_stack;
thread->transaction_stack = t;
} else {
...
}
//将BINDER_WORK_TRANSACTION添加到目标队列,本次通信的目标队列为target_proc->todo
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
//将BINDER_WORK_TRANSACTION_COMPLETE添加到当前线程的todo队列
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
//唤醒等待队列,本次通信的目标队列为target_proc->wait
if (target_wait)
wake_up_interruptible(target_wait);
return;
}
4.总结
在binder内核中,最终调用binder内核的binder_transaction方法。在这其中,对于注册服务和获取服务有不同的处理。
对于注册服务:在服务所在的进程中创建该进程对应的binder实体,在ServiceManager中创建binder引用。
最后向servicemanager的binder_proc->todo添加BINDER_WORK_TRANSACTION事务。交给ServiceManager处理。
对于获取服务,binder内核会先将其发往ServiceManager中,ServiceManager处理完毕后,将其他type改为BINDER_TYPE_HANDLE。之后也是在binder_transaction中进行如下处理:
- 当请求服务的进程与服务属于不同的进程,则为请求服务所在的进程创建一个binder引用,指向服务进程中的binder_nodr
- 请求服务的进程与服务属于同一进程是。不在创建新对象,而是引用计数+1.并修改type为BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。
五.ServiceManager中的注册服务和获取服务的
在上面binder内核中,当创建好对应的对象时,最后向servicemanager的binder_proc->todo添加BINDER_WORK_TRANSACTION事务。将对应的事件交给了servicemanager来继续处理。
1.svcmgr_handler
在上一篇博客中,我们知道ServiceManager中的注册服务和获取服务在svcmgr_handler方法中
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
.....
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE: //查找
s = bio_get_string16(msg, &len); //服务名
//根据名称查找相应服务
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
//【见小节3.1.2】
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE: //注册
s = bio_get_string16(msg, &len); //服务名
handle = bio_get_ref(msg); //handle
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)) {
return -1;
}
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
2.注册服务
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;
if (!handle || (len == 0) || (len > 127))
return -1;
//权限检查
if (!svc_can_register(s, len, spid)) {
return -1;
}
//服务检索
si = find_svc(s, len);
if (si) {
if (si->handle) {
svcinfo_death(bs, si); //服务已注册时,释放相应的服务
}
si->handle = handle;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) { //内存不足,无法分配足够内存
return -1;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); //内存拷贝服务信息
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->next = svclist; // svclist保存所有已注册的服务
svclist = si;
}
//以BC_ACQUIRE命令,handle为目标的信息,通过ioctl发送给binder驱动
binder_acquire(bs, handle);
//以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过ioctl发送给binder驱动,主要用于清理内存等收尾工作
binder_link_to_death(bs, handle, &si->death);
return 0;
}
注册服务分为以下4部分的工作:
- 权限检查:检查权限是否满足
- 服务检索:根据服务名来查询是否有匹配的服务。
- 释放服务:释放服务,当查询到已存在同名的服务,则先清理该服务信息,再将当前的服务加入到服务列表svclist(头插)
- 通知内核:最后通知binder驱动,完成注册。让驱动完成主要用于清理内存等收尾工作
3.查询服务
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
//查询相应的服务
struct svcinfo *si = find_svc(s, len);
if (!si || !si->handle) {
return 0;
}
if (!si->allow_isolated) {
uid_t appid = uid % AID_USER;
//检查该服务是否允许孤立于进程而单独存在
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
return 0;
}
}
//服务是否满足查询条件
if (!svc_can_find(s, len, spid)) {
return 0;
}
return si->handle;
}
在这里查询到目标服务,并返回对应的handle,查询成功后,在调用 bio_put_ref(reply, handle)方法,将handle封装到reply。
bio_put_ref
void bio_put_ref(struct binder_io *bio, uint32_t handle) {
struct flat_binder_object *obj;
if (handle)//如果handle==0 即查找的是ServiceManager
obj = bio_alloc_obj(bio); //见下
else
obj = bio_alloc(bio, sizeof(*obj));//见下
if (!obj)
return;
obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
obj->type = BINDER_TYPE_HANDLE; //返回的是HANDLE类型
obj->handle = handle;
obj->cookie = 0;
}
bio_alloc_obj
static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
{
struct flat_binder_object *obj;
obj = bio_alloc(bio, sizeof(*obj));//见下
if (obj && bio->offs_avail) {
bio->offs_avail--;
*bio->offs++ = ((char*) obj) - ((char*) bio->data0);
return obj;
}
bio->flags |= BIO_F_OVERFLOW;
return NULL;
}
bio_alloc
static void *bio_alloc(struct binder_io *bio, size_t size)
{
size = (size + 3) & (~3);
if (size > bio->data_avail) {
bio->flags |= BIO_F_OVERFLOW;
return NULL;
} else {
void *ptr = bio->data;
bio->data += size;
bio->data_avail -= size;
return ptr;
}
}
4. 返回reply结果
在查询成功后,最终通过调用binder_send_reply将reply(包含获取服务的结果)返回到binder内核中。
void binder_send_reply(struct binder_state *bs, struct binder_io *reply, binder_uintptr_t buffer_to_free, int status) {
struct {
uint32_t cmd_free;
binder_uintptr_t buffer;
uint32_t cmd_reply;
struct binder_transaction_data txn;
} __attribute__((packed)) data;
data.cmd_free = BC_FREE_BUFFER; //free buffer命令
data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY; // reply命令
data.txn.target.ptr = 0;
data.txn.cookie = 0;
data.txn.code = 0;
if (status) {
data.txn.flags = TF_STATUS_CODE;
data.txn.data_size = sizeof(int);
data.txn.offsets_size = 0;
data.txn.data.ptr.buffer = (uintptr_t)&status;
data.txn.data.ptr.offsets = 0;
} else {
data.txn.flags = 0;
data.txn.data_size = reply->data - reply->data0;
data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
}
//向Binder驱动通信
binder_write(bs, &data, sizeof(data));
}
在binder_send_reply,将BC_FREE_BUFFER和BC_REPLY命令协议发送给Binder驱动,在向客户端发送reply. 其中data的数据区中保存的是TYPE为HANDLE.
之后就是上一节中,binder_transaction中获取服务那一步。
六.总结
在进行获取服务和注册服务时,首先要获取BpServiceManager,BpServiceManager继承接口IServiceManager,并且含有binder内核中ServiceManager的binder(handle = 0)。
在获取BpServiceManager时:
- 首先获取ProcessState对象,并在其中打开binder驱动,调用mmap分配一块虚拟内存空间。
- 获取bpBinder时,就是ServiceManager的binder,
- C++中的宏函数创建bpServiceManager对象。
获取BpServiceManager之后,就可以调用对应的注册服务和获取服务方法,即addService和getService。之后都会去调用BpServiceManager中的BpBinadr的transact方法。
在BpBinder方法中,去调用了IPCThreadState的transact方法。在这个方法中,,首先会检查数据是否有误,通过ioctl和Binder内核进行数据传输。并等待响应。
之后就是内核对注册获取服务的处理。
在binder内核中,最终调用binder内核的binder_transaction方法。在这其中,对于注册服务和获取服务有不同的处理。
对于注册服务:在服务所在的进程中创建该进程对应的binder实体,在ServiceManager中创建binder引用。
最后向servicemanager的binder_proc->todo添加BINDER_WORK_TRANSACTION事务。交给ServiceManager处理。
在ServiceManager中,经过了如下过程,权限检查,服务检索,释放同名服务,添加新服务,通知内核。
对于获取服务,binder内核会先将其发往ServiceManager中,在ServiceManager中,查询完成后,将查询的handle封装到reply,并将其他ype改为BINDER_TYPE_HANDLE。在发送给内核。
之后也是在binder_transaction中进行如下处理:
- 当请求服务的进程与服务属于不同的进程,则为请求服务所在的进程创建一个binder引用,指向服务进程中的binder_nodr
- 请求服务的进程与服务属于同一进程是。不在创建新对象,而是引用计数+1.并修改type为BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。
七.参考资料
Binder系列3—启动ServiceManager
Binder系列4—获取ServiceManager
Binder系列5—注册服务(addService)
Binder系列6—获取服务(getService)