目录
0x03.Client端和Server端的通讯过程(Native层) 首先看Client端:
0x04.Client端和Server端的通讯过程(Native层) Server端:
本文不打算深入到linux内核中的binder驱动,只分析binder驱动之上的native层和Java层。所以我们认为,binder驱动的作用就是充当路由器,为Client和server端的通讯提供桥梁。
0x01.为什么要使用Binder
我们都知道,Binder是Android进程间通讯的主要方式。
问:Android为什么要选择Binder机制呢?
答:a.当然是Binder机制的高效性。Binder通讯过程中,数据只要copy一次就可以了。注意是进程间的数据只copy了一次,Client和server端建立链接时,通讯协议还是copy了好几次的。
b.稳定性 基于C/S架构,稳定性毋庸置疑
c.安全性 传统的IPC没有任何安全措施,安全完全依赖上层来实现。传统的IPC无法获得可靠的用户ID和进程ID(UID/PID),从而无法可靠的获得对方的身份。Android 为每个安装好的 APP 分配了自己的 UID,故而进程的 UID 是鉴别进程身份的重要标志。传统的 IPC 只能由用户在数据包中填入 UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标识只有由 IPC 机制在内核中添加。其次传统的 IPC 访问接入点是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。同时 Binder 既支持实名 Binder,又支持匿名 Binder,安全性高。
问:为什么数据只需要copy一次就能完成进程间的通讯?
答:关键是mmap() 函数。用户层调用mmap()函数,就会调用到驱动的binder_mmap函数,我们大致可以理解为,binder_mmap函数会为我们申请一块物理地址,然后建立用户空间和内核空间对这块地址的映射,这样用户空间和内核空间就都可以访问这段内存了。当client端需要传数据给server端时,只要copy_from_user一次到这段地址,server端既可以直接访问这段数据了。
这里盗一张图:
0x02.ServiceManager充当的角色
ServiceManager充当类似网络通讯中DNS的角色,Server端首先向ServiceManager注册自己,Client端则通过ServiceManager查询到这个服务,并且获得这个服务的一个类似fd=open()的句柄,然后Client端就可以通过这个句柄与Server端通讯了。需要注意的是,Client端和Server端与ServiceManager的交互,最终都是通过binder驱动完成的。
Binder 通信过程:
0x03.Client端和Server端的通讯过程(Native层) 首先看Client端:
先给出整体代码
int main(int argc, char **argv)
{
int cnt;
if (argc < 2){
ALOGI("Usage:\n");
ALOGI("%s <readfile>\n", argv[0]);
ALOGI("%s <hello|goodbye>\n", argv[0]);
ALOGI("%s <hello|goodbye> <name>\n", argv[0]);
return -1;
}
/* getService */
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
if (strcmp(argv[1], "hello") == 0)
{
sp<IBinder> binder =
sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
/* service肯定是BpHelloServie指针 */
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
/* 调用Service的函数 */
if (argc < 3) {
service->sayhello();
ALOGI("client call sayhello");
}
else {
cnt = service->sayhello_to(argv[2]);
ALOGI("client call sayhello_to, cnt = %d", cnt);
}
}
else if (strcmp(argv[1], "readfile") == 0)
{
sp<IBinder> binder =
sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
/* service肯定是BpHelloServie指针 */
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
/* 调用Service的函数 */
int fd = service->get_fd();
ALOGI("client call get_fd = %d", fd);
char buf[500];
int len;
int cnt = 0;
while (1)
{
/* 向 test_server 进程发出: Hello, test_server */
len = sprintf(buf, "Hello, test_server, cnt = %d", cnt++);
write(fd, buf, len);
/* 读取数据(test_server进程发回的数据) */
len = read(fd, buf, 500);
buf[len] = '\0';
ALOGI("%s\n", buf);
sleep(5);
}
}
else
{
sp<IBinder> binder =
sm->getService(String16("goodbye"));
if (binder == 0)
{
ALOGI("can't get goodbye service\n");
return -1;
}
/* service肯定是BpGoodbyeServie指针 */
sp<IGoodbyeService> service =
interface_cast<IGoodbyeService>(binder);
/* 调用Service的函数 */
if (argc < 3) {
service->saygoodbye();
ALOGI("client call saygoodbye");
}
else {
cnt = service->saygoodbye_to(argv[2]);
ALOGI("client call saygoodbye_to, cnt = %d", cnt);
}
}
return 0;
}
现在一步步分析:
a.打开驱动, mmap
sp<ProcessState> proc(ProcessState::self());
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)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
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()和mmap
b.获得BpServiceManager
sp<IServiceManager> sm = defaultServiceManager();
我们看下defaultServiceManager()是怎么实现的。
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;
}
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
这是一个模板,展开如下:
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(getStrongProxyForHandle(0));
}
可以看到最终调用了IServiceManager::asInterface方法,输入参数是getStrongProxyForHandle(0),但我们并没有发现IServiceManager::asInterface方法
看下IServiceManager.cpp中有这样一句
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
这是一句宏调用,展开如下:
#define DECLARE_META_INTERFACE(ServiceManager) \
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(); \
#define IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager") \
const android::String16 IServiceManager::descriptor("android.os.IServiceManager"); \
const android::String16& \
IerviceManager::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() { } \
#define CHECK_INTERFACE(interface, data, reply) \
if (!data.checkInterface(this)) { return PERMISSION_DENIED; } \
所以我们可以看到,sm=gDefaultServiceManager就是一个BpServiceManager对象。
c.getService引用
sp<IBinder> binder = sm->getService(String16("hello"));
由上一步sm=gDefaultServiceManager就是一个BpServiceManager对象,可知,sm->getService是BpServiceManager::getService()
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
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;
ALOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
}
可见BpServiceManager::getService最终调用了BpServiceManager::checkService,而BpServiceManager::checkService最终调用了remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
我们看下remote是怎么得来的。
BpServiceManager的构造函数
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
会先初始化他的父类BpInterface<IServiceManager>(impl)
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
然后是BpInterface的父类BpRefBase
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.
}
}
在BpRefBase类中有
inline IBinder* remote() { return mRemote; }
看来,remote()->transact相当于mRemote->transact。追溯mRemote=getStrongProxyForHandle(0)
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
// Special case for context manager...
// The context manager is the only object for which we create
// a BpBinder proxy without already holding a reference.
// Perform a dummy transaction to ensure the context manager
// is registered before we create the first local reference
// to it (which will occur when creating the BpBinder).
// If a local reference is created for the BpBinder when the
// context manager is not present, the driver will fail to
// provide a reference to the context manager, but the
// driver API does not return status.
//
// Note that this is not race-free if the context manager
// dies while this code runs.
//
// TODO: add a driver API to wait for context manager, or
// stop special casing handle 0 for context manager and add
// a driver API to get a handle to the context manager with
// proper reference counting.
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 {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
可知,这个mRemote是BpBinder对象,mRemote->transact是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::self()->transact,这里就和binder驱动打交道了。我们不分析驱动的代码,默认binder驱动帮我们找到了hello这个服务。
继续看checkService这个方法的返回值:
return reply.readStrongBinder();
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);
return 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->type) {
case BINDER_TYPE_BINDER:
*out = static_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc->getStrongProxyForHandle(flat->handle);
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
重点看*out = proc->getStrongProxyForHandle(flat->handle);
可知,这个out是getStrongProxyForHandle方法的返回值,也是一个BpBinder对象。还记得获取BpServiceManager时调用getStrongProxyForHandle方法的参数值吗,当时是0,这里是hello这个服务返回给Client端的handle值。
也就是说,sp<IBinder> binder = sm->getService(String16("hello"));这里的binder是一个BpBinder对象,构造参数是hello这个服务返回给Client端的handle值。
d.获得BpHelloServie对象
sp<IHelloService> service = interface_cast<IHelloService>(binder);
IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");
看起来和获得BpServiceManager一样的处理方法
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
相当于
inline sp<IHelloService> interface_cast(const sp<IBinder>& obj)
{
return IHelloService::asInterface(binder);
}
展开IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");如下:
#define DECLARE_META_HelloService(HelloService) \
static const android::String16 descriptor; \
static android::sp<IHelloService> asHelloService( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getHelloServiceDescriptor() const; \
IHelloService(); \
virtual ~IHelloService(); \
#define IMPLEMENT_META_HelloService(HelloService, "android.media.IHelloService") \
const android::String16 IHelloService::descriptor("android.media.IHelloService"); \
const android::String16& \
IHelloService::getHelloServiceDescriptor() const { \
return IHelloService::descriptor; \
} \
android::sp<IHelloService> IHelloService::asHelloService( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<IHelloService> intr; \
if (obj != NULL) { \
intr = static_cast<IHelloService*>( \
obj->queryLocalHelloService( \
IHelloService::descriptor).get()); \
if (intr == NULL) { \
intr = new BpHelloService(obj); \
} \
} \
return intr; \
} \
IHelloService::IHelloService() { } \
IHelloService::~IHelloService() { } \
#define CHECK_HelloService(HelloService, data, reply) \
if (!data.checkHelloService(this)) { return PERMISSION_DENIED; } \
所以service = interface_cast<IHelloService>(binder);返回一个BpHelloService(binder)对象,对象的构造参数是第c步获得的IBinder类对象
e.调用Service的方法
service->sayhello();
由第d步可知,service 是一个BpHelloService(binder)对象,这里肯定调用到了BpHelloService对象的sayhello()方法
void sayhello(void)
{
/* 构造/发送数据 */
Parcel data, reply;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}
这里的remote()=mRemote=第c步获得的BpBinder类对象
这样,remote()->transact一样是调用到了IPCThreadState::transact方法,直接和binder驱动打交道了。同样,我们不分析驱动层代码,我们直接认为,binder驱动帮我们把HELLO_SVR_CMD_SAYHELLO这条命令发送给了server端。
不过这里有个地方需要注意,就是
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
虽然第c步和第e步都是通过同一个方法来和binder通讯,但最主要的一点是传入的handle不同,一个是handle=0,默认指servicemanager;一个是通过查询获得的server端的handler句柄,binder驱动通过不同的handle和servicemanager或者server端打交道。
0x04.Client端和Server端的通讯过程(Native层) Server端:
首先给出全部代码
int main(void)
{
int sockets[2];
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
/* 创建一个线程, 用于跟test_client使用socketpiar通信 */
sp<MyThread> th = new MyThread(sockets[0]);
th->run();
/* addService */
/* while(1){ read data, 解析数据, 调用服务函数 } */
/* 打开驱动, mmap */
sp<ProcessState> proc(ProcessState::self());
/* 获得BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("hello"), new BnHelloService(sockets[1]));
sm->addService(String16("goodbye"), new BnGoodbyeService());
/* 循环体 */
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
a.打开驱动, mmap
sp<ProcessState> proc(ProcessState::self());
和0x03.a是一样的,不再分析
b.获得BpServiceManager
sp<IServiceManager> sm = defaultServiceManager();
和0x03.b是一样的,不再分析
c.addService
sm->addService(String16("hello"), new BnHelloService(sockets[1]));
d.循环体
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
先看startThreadPool
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());
}
}
调用了t->run,最终调用了
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
所以这两个语句都是最终调用了joinThreadPool方法,下面分析这个方法
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
// This thread may have been spawned by a thread that was in the background
// scheduling group, so first we will make sure it is in the foreground
// one to avoid performing an initial transaction in the background.
set_sched_policy(mMyThreadId, SP_FOREGROUND);
status_t result;
do {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand();
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
abort();
}
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",
(void*)pthread_self(), getpid(), (void*)result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
可见,最主要的是调用了getAndExecuteCommand
getAndExecuteCommand-->executeCommand-->const status_t error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);
reinterpret_cast<类型说明符>(表达式)
所以reinterpret_cast<BBinder*>(tr.cookie)的意思就是把tr.cookie强转成BBinder*类型的指针
很明显,这句的意思就是调用BBinder类的transact方法
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
接着调用onTransact方法
再来看BnHelloService类,他是BnInterface的子类,BnInterface又是BBinder的子类,而BnHelloService重写了onTransact方法
所以这里的onTransact方法应该是BnHelloService::onTransact。BnHelloService::onTransact根据code值,最终调用到了BnHelloService类里提供的具体方法
这样,从Client端到Server端的调用流程,我们就分析完了。当然里面的分析有很多不完善的地方,欢迎大家指正
参考:
<1>https://zhuanlan.zhihu.com/p/35519585
<2>http://gityuan.com/2016/09/04/binder-start-service/ 彻底理解Android Binder通信架构
<3>http://zhoujinjian.cc/2018/01/01/Android-7-1-2-Android-N-Android-Binder%E7%B3%BB%E7%BB%9F%E5%88%86%E6%9E%90/index.html Android 7.1.2 (Android N) Android Binder 系统 分析
<4>韦东山Binder系统视频