一.linux进程通信
在操作系统中,进程间是相互隔离的,并且在系统层会分为内核态和用户态,在空间上会分为用户态和内核态,如下图:
为什么要这样设计?因为为了防止用户直接操作内核空间,从而直接操作硬件内存等资源,所以内核空间具有操作硬件的权利,而用户空间只能通过内核去操作,避免了越级访问,保证了系统安全。linux中有两个特权等级分别是0级别的系统和3级别的用户,当3级的用户调用系统指令陷入内核代码时此时的cpu等级为0级别,并且执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。 当执行自己的代码时cpu等级为3,那普通进程和内核进程间通过什么来执行的呢?主要是通过两个函数执行,分别是:
copy_from_user() //将数据从用户空间拷贝到内核空间
copy_to_user() //将数据从内核空间拷贝到用户空间
一般的ipc机制调用流程使发送数据将数据copy到内核缓存空间,之后接收的进程将缓存区的数据copy到本地,也就是通过二次拷贝后完成1次数据发送与接收。通讯示意如下图:
这种通讯有两个弊端:一是需要2次拷贝;二是接收区的内存空间大小的开辟并不可控,因为无法直到传入过来的数据大小是多大。除了这种通过内核的两次拷贝,还有其他ipc通讯方式吗?当然后,比如共享内存、socket、管道、信号量等。
二.binder的通信优点
我们知道在liunx两个进程要通讯,可以借助的手段有共享文件、共享内存、Socket、信号量管道等,android是基于linux的,那为什么还是需要使用Binder呢?其中主要的就是效率和安全的问题,我们知道无论是共享内存还是文件它都不安全,而Socket效率也低,信号量也只是做个简单的控制,管道是属于单向通讯,所以android借助于的binder实现了1次拷贝和安全校验?那他又是怎么做到的?
1.使用内存映射做到一次拷贝
为了提高进程间通讯的效率,android通过内存映射做到了1次拷贝,内存映射是通过 mmap() 来实现,mmap() 是操作系统中一种内存映射的方法。简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间,这样就完成了1次拷贝。
2.安全校验机制
Android 为每个安装好的 APP 分配了自己的 UID,故而进程的 UID 是鉴别进程身份的重要标志。传统的 IPC 只能由用户在数据包中填入 UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标识只有由 IPC 机制在内核中添加。
三.service_manager
1.serviceManager是什么?
ServiceManager是android进程间调用的重要一环,它也是一个单独的进程,是由开机时在init.rc启动的,它是android所有服务的中心,主要是提供服务注册、缓存、和服务获取功能。它也是0号binder。
2.seriviceManager的启动
servicemanager是由init进程启动的,具体流程看下图:
源码目录:frameworks\native\cmds\servicemanager\service_manager.c
3.serviceManager核心函数分析
1.入口函数
程序的入口函数就是打开binder驱动,并且将自己注册成为0号binder后,开启消息循环,设置回调函数,当收到binder驱动传来的消息后就会执行回调函数。
int main(int argc, char** argv)
{
struct binder_state *bs;
union selinux_callback cb;
char *driver;
if (argc > 1) {
driver = argv[1];
} else {
driver = "/dev/binder";
}
//打开驱动
bs = binder_open(driver, 128*1024);
if (!bs) {
#ifdef VENDORSERVICEMANAGER
ALOGW("failed to open binder driver %s\n", driver);
while (true) {
sleep(UINT_MAX);
}
#else
ALOGE("failed to open binder driver %s\n", driver);
#endif
return -1;
}
//注册成为0号binder
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
#ifdef VENDORSERVICEMANAGER
cb.func_log = selinux_vendor_log_callback;
#else
cb.func_log = selinux_log_callback;
#endif
selinux_set_callback(SELINUX_CB_LOG, cb);
#ifdef VENDORSERVICEMANAGER
sehandle = selinux_android_vendor_service_context_handle();
#else
sehandle = selinux_android_service_context_handle();
#endif
selinux_status_open(true);
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();
}
//开启读取binder消息循环 svcmgr_handler为回调函数
binder_loop(bs, svcmgr_handler);
return 0;
}
2.回调函数
可以看到,回调函数主要是根据code的不同执行不同的操作,比如查找或添加服务
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data_secctx *txn_secctx,
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;
uint32_t dumpsys_priority;
struct binder_transaction_data *txn = &txn_secctx->transaction_data;
//ALOGI("target=%p code=%d pid=%d uid=%d\n",
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target.ptr != BINDER_SERVICE_MANAGER)
return -1;
if (txn->code == PING_TRANSACTION)
return 0;
// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
strict_policy = bio_get_uint32(msg);
bio_get_uint32(msg); // Ignore worksource header.
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s, len));
return -1;
}
if (sehandle && selinux_status_updated() > 0) {
#ifdef VENDORSERVICEMANAGER
struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
#else
struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
#endif
if (tmp_sehandle) {
selabel_close(sehandle);
sehandle = tmp_sehandle;
}
}
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(s, len, txn->sender_euid, txn->sender_pid,
(const char*) txn_secctx->secctx);
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;
dumpsys_priority = bio_get_uint32(msg);
if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
txn->sender_pid, (const char*) txn_secctx->secctx))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
uint32_t n = bio_get_uint32(msg);
uint32_t req_dumpsys_priority = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
si = svclist;
// walk through the list of services n times skipping services that
// do not support the requested priority
while (si) {
if (si->dumpsys_priority & req_dumpsys_priority) {
if (n == 0) break;
n--;
}
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;
}
3.添加服务
可以看到,服务的添加前会对其校验,校验后也会从缓存中检测,再次检测不含有后才会根据其句柄等参数生成性的svcinfo后添加到缓存中去。
int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
struct svcinfo *si;
//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
// allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
if (!handle || (len == 0) || (len > 127))
return -1;
//权限校验
if (!svc_can_register(s, len, spid, sid, uid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s, len), handle, uid);
return -1;
}
//缓存检测
si = find_svc(s, len);
if (si) {
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
//添加到缓存中去
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = 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->dumpsys_priority = dumpsys_priority;
si->next = svclist;
svclist = si;
}
binder_acquire(bs, handle);
binder_link_to_death(bs, handle, &si->death);
return 0;
}
4.获取服务
这个比较简单就是从缓存列表中查询服务,并返回句柄。
uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
{
struct svcinfo *si = find_svc(s, len);
if (!si || !si->handle) {
return 0;
}
if (!si->allow_isolated) {
// If this service doesn't allow access from isolated processes,
// then check the uid to see if it is 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, sid, uid)) {
return 0;
}
return si->handle;
}
四.Native层的Binder
Native层的Binder的流程如上图,首先是服务注册,Process2作为服务端会将自己的BBinder注册到ServiceManager进程中去,当然它也是先拿到ServiceManager代理后才做的交互,而Process1则是获取到注册在ServiceManager中Binder但是它拿到的是BpBinder也就是BBinder的代理,他们之间的调用是通过系统调用的驱动来实现的。这里的交互过程涉及很多不同的类,下面对这些类做些介绍:
1.ProcessState:
- ProcessState从字面意思可以理解,表示是“进程状态”,代表了这个进程的行为,Android中,每个进程都是独立的,所以每个进程都要有一个“进程状态”--ProcessState.
- 在Binder通信机制中,ProcessState使用了单例模式,即一个进程只有个ProcessState对象,一个进程中有很多个线程,不能每个线程都来new一个新的ProcessState(),采用单例模式后,每个线程都可以使用同一个ProcessState来和Binder驱动通信。
- ProcessState作为进程状态的记录器,主要用来打开Binder驱动获取句柄,mmap申请一块(1M-8K)的内存空间,设置Binder线程最大个数。
2.IPCThreadState
- IPCThreadState从字面意思可以理解,表示是“进程间通信的线程状态”,有了进程状态后,自然需要有线程状态。
- ProcessState代表了进程,IPCThreadState代表了线程。Android系统中有很多进程,进程间相互隔离,每个进程内部又有很多线程,线程之间也是相互独立的。所以说一个进程会存在很多个线程,每个线程都有自己的“线程状态”--IPCThreadState对象.这个对象存储在线程的本地存储区(TLS:Thread local storage)中,每个线程都拥有自己的TLS,并且是私有空间,线程之间不会共享。
- IPCThreadState对象根据key:gTLS去进行存储。通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间中的内容。
- IPCThreadState负责与Binder驱动进行数据交互。
3.BpBinder
BpBinder 展开后就是Binder Proxy,也就是Binder代理的含义。BpBinder是客户端用来与服务交互的代理类,负责实现跨进程传输的传输机制,不关心具体的传输内容。通信功能由其它类和函数实现,但由于这些类和函数被BpBinder代理,所以客户端需要通过BpBinder来发送Binder通信数据。
4.BBinder
BBinder代表服务端,可以理解为服务的Binder实体,当服务端从Binder驱动中读取到数据后,由BBinder类进行处理。
5.MediaServer过程分析
1.服务添加
mediaServer是由init.rc启动meidaServer.rc启动的,代码路径为: \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());//获取serverManager代理即BpServiceManager对象
ALOGI("ServiceManager: %p", sm.get());
AIcu_initializeIcuOrDie();
MediaPlayerService::instantiate();////注册多媒体服务
ResourceManagerService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();//启动Binder线程池
IPCThreadState::self()->joinThreadPool();//当前线程开启线程池
}
frameworks/native/libs/binderIServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
//这里是单例模式
if (gDefaultServiceManager != nullptr) return gDefaultServiceManager;
{
//1. ProcessState::self() 打开驱动
//2. getContextObject(nullptr) 0号BpBinder
//3. interface_cast<IServiceManager> //转换
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == nullptr) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(nullptr));//获取ServiceManager的BpBinder
if (gDefaultServiceManager == nullptr)
sleep(1);
}
}
return gDefaultServiceManager;
}
//添加服务
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) {
Parcel data, reply; //定义一个data和reply的Parcel数据包
//写入RPC头信息"android.os.IServiceManager"
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name); //服务名为 "media.player"
data.writeStrongBinder(service); //把一个binder实体“打扁”并写入parcel, 服务的实体对象:new MediaPlayerService()
data.writeInt32(allowIsolated ? 1 : 0); //allowIsolated= false
data.writeInt32(dumpsysPriority); //dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT
//remote()函数返回的是mRemote,就是BpRefBase中的mRemote,即BpBinder对象。
//这里调用了BpBinder的transact()方法
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
BpBinder.cpp
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.cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err;
flags |= TF_ACCEPT_FDS;
...
// 传输数据
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
ALOGE("Process making non-oneway call but is restricted.");
CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
ANDROID_LOG_ERROR);
} else /* FATAL_IF_NOT_ONEWAY */ {
LOG_ALWAYS_FATAL("Process may not make oneway calls.");
}
}
//等待响应
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
...
} else {
//oneway,则不需要等待reply的场景
err = waitForResponse(nullptr, nullptr);
}
return err;
}
frameworks/native/libs/binder/ProcessState.cpp
#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
const char* kDefaultDriver = "/dev/binder";
#endif
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
//ProcessState的实例存在,直接返回该实例对象--单例模式
if (gProcess != nullptr) {
return gProcess;
}
//实例化ProcessState,kDefaultDriver 根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder"
gProcess = new ProcessState(kDefaultDriver);
return gProcess;
}
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver)) //打开驱动,根据VNDK的宏定义来决定当前进程使用"/dev/binder" 还是"/dev/vndbinder",假设为"/dev/binder"
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS) //Binder线程的最大个数16
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
if (mDriverFD >= 0) {
// 向Binder驱动申请一块(1M-8K)的虚拟地址空间来接收事务。
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 could not be opened. Terminating.");
}
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
/frameworks/native/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
//添加服务
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
BpServiceManager()的继承关系:
1.class BpServiceManager : public BpInterface
2.class BpInterface : public INTERFACE, public BpRefBase
3.class BpRefBase : public virtual RefBase
MediaPlayerService的类关系
我们可以看到Media服务添加的过程:
1.首先初始化ProcessState
2.获取BpServiceManager
3.通过BpServiceManager将MediaService(BBinder)添加到serverManager中去
4.开启binder线程循环读取消息
2.服务获取
服务的获取流程大致如下:
1.获取ServiceManager的代理对象BpServiceManager,用于和ServiceManager进行通信
2.通过ServiceManager的代理接口,调用getService()这种接口来获取指向服务实体的代理接口
3.客户端通过调用已得到的service代理的成员函数,把自己的binder实体作为参数,传递到目标service进程
4.获得合法的服务代理对象
我们看下代码:
//framework/av/media/libMedia/IMediaDeathNotifier.cpp
//1.获取ServiceManager的代理对象BpServiceManager
//2.调用BpServiceManager的getService接口,来获取服务名称为“media.player”的Binder 服务对象
//3.创建死亡通知对象
//4.将死亡通知连接到binder
//5.得到服务对象
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
//framework/native/libs/binder/IServiceManager.cpp
defaultServiceManager->getService()其实就是BpServiceManager->getService。
virtual sp<IBinder> getService(const String16& name) const
{
//检索指定服务是否存在
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
//如果ProcessState和Binder驱动交互的是"/dev/vndbinder",那么isVendorService为True,表明Vendor进程之间可以进行Binder通信
const bool isVendorService =
strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
const long timeout = uptimeMillis() + 5000;
if (!gSystemBootCompleted && !isVendorService) {
//vendor分区的代码不能访问system的属性
char bootCompleted[PROPERTY_VALUE_MAX];
property_get("sys.boot_completed", bootCompleted, "0");
gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
}
//vendor分区的服务sleepTime 为100ms, system为1000ms
const long sleepTime = gSystemBootCompleted ? 1000 : 100;
int n = 0;
while (uptimeMillis() < timeout) {
n++;
ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
ProcessState::self()->getDriverName().c_str());
usleep(1000*sleepTime);
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
}
ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
return nullptr;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
//写入RPC头信息"android.os.IServiceManager"
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name); //写入服务的名称
//remote()函数返回的是mRemote,就是BpRefBase中的mRemote,即BpBinder对象。这里调用了BpBinder的transact()方法
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();//parcel.cpp调用
}
//BpBinder的transact()的流程这里就不展开,上面addService()
//已经有了详细的说明。CHECK_SERVICE_TRANSACTION
//在ServiceManager中对应的是SVC_MGR_CHECK_SERVICE(),
//从svclist中,根据服务的name查到对应的handle,最终得到服务的对象。
//和addService类似,ServiceManager查到对应的handle后,把handle存入reply,
//addService的reply没有数据getService的reply有数据,返回BR_REPLY相应码。
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
...
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");
if (err != NO_ERROR) goto finish;
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
} else {
err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
}
} else {
freeBuffer(nullptr,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t), this);
continue;
}
}
goto finish;
...
}
//parcel.cpp
//checkservice()收到ServiceManager发来的reply后,
//调用readStrongBinder()来获取服务的对象。主要在unflatten_binder
// 中,根据flat的type是handle还是实体,从而返回BpBinder对象 或者BBinder实体。
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
readNullableStrongBinder(&val);
return val;
}
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);
}
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->hdr.type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(nullptr, *flat, in); //返回BBinder实体
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in); //返回BpBinder代理对象
}
}
return BAD_TYPE;
}
1.客户端进程获取ServiceManager的代理对象BpServiceManager,主要通过new BpBinder(0,xxx)得到。
2.调用BpServiceManager的getService,再到checkService(),然后组装一个Parce数据,传入服务名称、传输code-CHECK_SERVICE_TRANSACTION
3.先通过IPCThreadThread的writeTransactionData()把上面的Parcel数据写入mOut,用来进行发送
4.通过IPCThreadThread的talkWithDriver()与Binder驱动通信,传递语义BINDER_WRITE_READ
5.ServiceManager有个循环不停的解析Binder驱动的BINDER_WRITE_READ信息,调用binder_parse()进行解析
6.ServiceManager中解析后,CHECK_SERVICE_TRANSACTION对应的值为SVC_MGR_CHECK_SERVICE,从svclist中,根据服务的name查到对应的handle,ServiceManager再通过binder_send_reply()把返回的数据发送出来,在talkWithDriver()中填入mIn中,waitForResponse()进行最终的语义处理,发送出去。
五.Framework中的服务
1.服务添加的过程
-
-
- 获取BinderProxy的java对象,获取0号bpBinder(ServiceManager的代理)
- add方法执行,通过parcel.writeStrongBinder将Binder服务转成flatter_biner通过BinderProxy执行transact方法,实际执行的是bpBinder的transact方法
-
2.服务获取过程
-
-
- 获取BinderProxy的java对象,获取0号bpBinder(ServiceManager的代理)
- get方法执行,通过mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0)和serviceManager交互将flatter_binder写入到reply中,在通过parcel.java经过的jni和一系列转换得到java的BinderProxy(底层是服务的bpBinder)
-