Binder系统分析准备分两篇文章讲述,本篇文章主要分析Binder系统Native层的实现,具体如下图所示
以MediaServer(简称MS)为例,它是一个可执行程序,虽然Android的SDK提供Java层的API,但Android系统本身还是一个完整的基于Linux内核的操作系统,所以并非所有的程序都是用Java编写的,这里的MS就是一个用C++编写的可执行程序。
之所以选择MediaServer作为切入点,是因为这个Server是系统诸多重要Service的栖息地,它们包括:AudioFlinger:音频系统中的核心服务、AudioPolicyService:音频系统中关于音频策略的重要服务、MediaPlayerService:多媒体系统中的重要服务、CameraService:有关摄像/照相的重要服务,这里以其中的MediaPlayerService为主切入点进行分析。先来分析MediaServer本身。
MediaServer是在系统启动时,在init.rc中启动
service media /system/bin/mediaserver
user media
group system audio camera graphics inet net_bt net_bt_admin
MediaServer是一个可执行程序,入口函数是main,源码路径/frameworks/base/media/mediaserver/main_mediaserver.cpp
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());//获得一个ProcessState实例
sp<IServiceManager> sm = defaultServiceManager();//MediaServer需要向ServiceManager注册服务,defaultServiceManager()返回一个IServiceManager
LOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();//初始化音频系统AudioFlinger服务
MediaPlayerService::instantiate();//初始化多媒体系统MediaPlayerService服务,及我们研究的切入点
CameraService::instantiate();//初始化CameraService服务
AudioPolicyService::instantiate();//初始化音频系统AudioPolicyService服务
ProcessState::self()->startThreadPool();//创建一个线程池
IPCThreadState::self()->joinThreadPool();//加入刚创建的线程池
}
第一步:获得一个ProcessState实例
sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess;
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
gProcess首次为NULL,则会创建一个ProcessState对象,self函数采用了单例模式,每个进程只有一个ProcessState对象
再来看ProcessState的构造函数
ProcessState::ProcessState()
: mDriverFD(open_driver())//打开/dev/binder这个设备,它是Android在内核中为完成进程间通信而专门设置的一个虚拟设备
, 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*
LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
if (mDriverFD < 0) {
// Need to run without the driver, starting our own thread pool.
}
}
ProcessState的构造函数首先会打开Binder设备
static int open_driver()
{
if (gSingleProcess) {
return -1;
}
int fd = open("/dev/binder", O_RDWR);//打开/dev/binder设备
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers;
#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(fd, BINDER_VERSION, &vers);
#else
status_t result = -1;
errno = EPERM;
#endif
if (result == -1) {
LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
LOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
#if defined(HAVE_ANDROID_OS)
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//通过ioctl告诉Binder驱动,当前设备支持的最大线程数为15
if (result == -1) {
LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
#endif
} else {
LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
打开Binder设备后,会对返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据。
因此Process::self函数所做的工作可以概括为:
1、打开/dev/binder设备,相当于与内核的Binder驱动有了交互的通道。
2、对返回的fd使用mmap,这样Binder驱动就会分配一块内存来接收数据。
3、由于ProcessState具有唯一性,因此一个进程只打开设备一次。
多进程使用Binder时,Binder驱动就会为每一个进程分配一块内存来接收数据
扩展:上述描述中提到了设备/节点(/dev/binder),驱动(Binder驱动)等概念,也有诸如open()、ioctl()、mmap()方法,因此我们先开个小叉,介绍一下Linux的一些基本概念和原理
首先看下几个概念:内核空间和用户空间、进程隔离
内核空间和用户空间
为了保护用户进程不能直接操作内核,保证内核的安全,操作系统从逻辑上将虚拟空间划分为用户空间和内核空间。Linux 操作系统将最高的1GB字节供内核使用,称为内核空间,较低的3GB 字节供各进程使用,称为用户空间。
内核空间是Linux内核的运行空间,用户空间是用户程序的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不会受到影响。内核空间的数据是可以进程间共享的,而用户空间则不可以。
进程隔离 进程隔离指的是,一个进程不能直接操作或者访问另一个进程。也就是进程A不可以直接访问进程B的数据。
系统调用 用户空间需要访问内核空间,就需要借助系统调用来实现。系统调用是用户空间访问内核空间的唯一方式,保证了所有的资源访问都是在内核的控制下进行的,避免了用户程序对系统资源的越权访问,提升了系统安全性和稳定性。
进程A和进程B的用户空间可以通过如下系统函数和内核空间进行交互。
copy_from_user:将用户空间的数据拷贝到内核空间。
copy_to_user:将内核空间的数据拷贝到用户空间。
然后看下设备节点 Linux设备分成三种基本类型:字符设备、块设备、网络设备
设备驱动程序也分为对应的三类:字符设备驱动程序、块设备驱动程序和网络设备驱动程序。
在Linux中,所有设备都以文件的形式存放在/dev目录下(Binder设备节点即/dev/binder),都是通过文件的方式进行访问,设备节点是Linux内核对设备的抽象,是连接内核与用户层的枢纽(如下图所示,Binder设备节点是连接用户层和Binder驱动所在的内核间的枢纽),一个设备节点就是一个文件(即打开binder设备后返回的fd对象,就是一个文件描述符)。应用程序通过一组标准化的调用执行访问设备,这些调用独立于任何特定的驱动程序。而驱动程序负责将这些标准调用映射到实际硬件的特有操作。整体关系如下图所示:
应用程序可以打开、关闭和读写这些设备节点文件,完成对设备的操作,就像操作普通的数据文件一样。为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。应用程序通过名称访问设备,而设备号指定了对应的驱动程序和对应的设备。主设备号标识设备对应的驱动程序,次设备号由内核使用,用于确定设备节点所指设备。
接下来再看open()、ioctl()、mmap() 方法
open():打开驱动文件
ioctl():ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。如上述Binder驱动中就指定了最大线程数的命令:最大15个线程
说到mmap(),首先说下内存映射,由于应用程序不能直接操作硬件地址,所以操作系统提供了一种机制:内存映射,把硬件地址映射到进程虚拟内存区。内存映射全名为Memory Map,即将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间,反之亦然。内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。
举个例子,如果用户空间需要读取磁盘的文件,如果不采用内存映射,那么就需要在内核空间建立一个页缓存,页缓存去拷贝磁盘上的文件,然后用户空间拷贝页缓存的文件,这就需要两次拷贝。
采用内存映射,如下图所示。
由于新建了虚拟内存区域,那么磁盘文件和虚拟内存区域就可以直接映射,少了一次拷贝。
在Linux中通过系统调用函数mmap来实现内存映射。
mmap():返回该进程对驱动文件映射的地址,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存(即把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址)。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问(对文件的读写可以直接用指针来做),不必再调用read(),write()等操作。
当用户空间调用open()方法,最终会调用binder驱动的binder_open()方法;mmap()/ioctl()方法也是同理,从用户态进入内核态,都依赖于系统调用过程。
binder_init 注册misc设备,指定相应文件操作的方法。
binder_open 创建binder_proc对象,并把当前进程等信息保存到binder_proc对象,该对象管理IPC所需的各种信息并拥有其他结构体的根结构体;再把binder_proc对象保存到文件指针filp,以及把binder_proc加入到全局链表binder_procs。
binder_mmap 在内核虚拟地址空间,申请一块与用户虚拟内存相同大小的内存;然后再申请1个page大小的物理内存,再将同一块物理内存分别映射到内核虚拟地址空间和用户虚拟内存空间,从而实现了用户空间的Buffer和内核空间的Buffer同步操作的功能。
binder_ioctl 负责在两个进程间收发IPC数据和IPC reply数据
经过上述分析,我们可以看到binder进程间通信方式比传统的Linux IPC机制少一次内存拷贝,下面简单分析一下
先看下传统Linux IPC机制
内核程序在内核空间分配内存并开辟一块内核缓存区,发送进程通过copy_from_user函数将数据拷贝到到内核空间的缓冲区中。同样的,接收进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用 copy_to_user() 函数将数据从内核缓存区拷贝到接收进程。这样数据发送进程和数据接收进程完成了一次数据传输,也就是一次进程间通信。
Linux的IPC通信原理有两个问题:
1、一次数据传递需要经历:用户空间 –> 内核缓存区 –> 用户空间,需要2次数据拷贝,这样效率不高。
2、接收数据的缓存区由数据接收进程提供,但是接收进程并不知道需要多大的空间来存放将要传递过来的数据,因此只能开辟尽可能大的内存空间或者先调用API接收消息头来获取消息体的大小,浪费了空间或者时间。
再看下Binder进程间通信
Binder是基于内存映射来实现的,在前面我们知道内存映射通常是用在有物理介质的文件系统上的,Binder没有物理介质,它使用内存映射是为了跨进程传递数据。
1.Binder驱动在内核空间创建一个数据接收缓存区。
2.在内核空间开辟一块内核缓存区,建立内核缓存区和数据接收缓存区之间的映射关系,以及数据接收缓存区和接收进程用户空间地址的映射关系。
3.发送方进程通过copy_from_user()函数将数据拷贝 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
整个过程只使用了1次拷贝,不会因为不知道数据的大小而浪费空间或者时间,效率更高。
看完ProcessState后,看下第二步defaultServiceManager
在IServiceManager.cpp中,源码路径/frameworks/base/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
真正的创建在interface_cast方法中,该方法接收参数ProcessState::self()->getContextObject(NULL),即调用了ProcessState的getContextObject方法,传入参数NULL,接下来我们看下getContextObject方法,在ProcessState.cpp中
getContextObject方法最终会返回一个IBinder对象
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if (supportsProcesses()) {//该方法会根据openDriver()是否可成功打开设备来判断是否支持process,由于在第一步ProcessState构造方法中已打开Binder设备,所以会执行getStrongProxyForHandle(0)
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
然后接着看getStrongProxyForHandle()
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);//根据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)) {//新资源项的binder为空
b = new BpBinder(handle);//创建BpBinder对象,这里传入的是0
e->binder = b;//将BpBinder填充到资源项的binder字段
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;
}
getStrongProxyForHandle会创建一个BpBinder,接下来我们先来介绍下BpBinder,BpBinder和BBinder都是Android中与Binder通信相关的代表,它们都是从IBinder类中派生而来。
BpBinder是客户端用来与Server交互的代理类,p即Proxy的意思。
BBinder则是与proxy相对的一端,它是proxy交互的目的端。如果说Proxy代表客户端,那么BBinder则代表服务端。这里的BpBinder和BBinder是一一对应的,即某个BpBinder只能和对应的BBinder交互。我们当然不希望通过BpBinderA发送的请求,却由BBinderB来处理。
正是由于我们是ServiceManager的客户端,所以使用代理端与ServiceManager进行交互。因此getStrongProxyForHandle会创建一个BpBinder,而不是BBinder。
那么BpBinder如何标识它所对应的BBinder端呢?正是上述传参中的handle,我们给BpBinder构造函数传的参数handle的值是0。这个0在整个Binder系统中有重要含义—因为0代表的就是ServiceManager所对应的BBinder。
我们看下BpBinder的构造方法
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)//handle:0
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);//另一个重要对象IPCThreadState
}
暂时回到上边分析的逻辑,ProcessState::self()->getContextObject(NULL)返回BpBinder对象会传参给interface_cast方法,接下来看下interface_cast方法做了什么
在IInterface.h中,源码路径/frameworks/base/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
可以看到interface_cast仅仅是一个模板函数,所以interface_cast<IServiceManager>()等价于
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
这样就转到了IServiceManager中,IServiceManager定义了ServiceManager所提供的服务,在IServiceManager.h中,源码路径
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager);
/**
* Retrieve an existing service, blocking for a few seconds
* if it doesn't yet exist.
*/
virtual sp<IBinder> getService( const String16& name) const = 0;
/**
* Retrieve an existing service, non-blocking.
*/
virtual sp<IBinder> checkService( const String16& name) const = 0;
/**
* Register a service.
*/
virtual status_t addService( const String16& name,
const sp<IBinder>& service) = 0;
/**
* Return list of all existing services.
*/
virtual Vector<String16> listServices() = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
LIST_SERVICES_TRANSACTION,
};
};
先看DECLARE_META_INTERFACE,通过DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏,将业务和通信牢牢地钩在了一起。DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE这两个宏都定义在刚才的IInterface.h中
先看下DECLARE_META_INTERFACE宏定义
#define DECLARE_META_INTERFACE(INTERFACE) \
static const String16 descriptor; \
static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj); \
virtual const String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
DECLARE_META_INTERFACE(ServiceManager);替换后即如下代码
static const String16 descriptor;//定义描述字符串
static sp<IServiceManager> asInterface(const sp<IBinder>& obj);//定义asInterface函数
virtual const String16& getInterfaceDescriptor() const;//定义getInterfaceDescriptor,返回descriptor
IServiceManager();//定义IServiceManager的构造和析构函数
virtual ~IServiceManager();
DECLARE_META_INTERFACE宏声明了一些函数和一个变量,那么,IMPLEMENT_META_INTERFACE宏的作用肯定就是定义它们了。IMPLEMENT_META_INTERFACE的定义在IInterface.h中,IServiceManager是如何使用这个宏的呢?只有一行代码,在IServiceManager.cpp中,如下所示:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
看下IMPLEMENT_META_INTERFACE的定义
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const String16 I##INTERFACE::descriptor(NAME); \
const String16& I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj) \
{ \
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() { }
替换后如下
const String16 IServiceManager::descriptor("android.os.IServiceManager");
const String16& IServiceManager::getInterfaceDescriptor() const {//实现getInterfaceDescriptor()函数
return IServiceManager::descriptor;//返回descriptor,即android.os.IServiceManager
}
sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)
{//实现asInterface函数
sp<IServiceManager> intr;
if (obj != NULL) {
intr = static_cast<IServiceManager*>(
obj->queryLocalInterface(
IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);//obj是刚创建的BpBinder对象
}
}
return intr;
}
//实现构造和析构函数
IServiceManager::IServiceManager() { }
IServiceManager::~IServiceManager() { }
通过intr = new BpServiceManager(obj),interface_cast就把BpBinder指针转换成一个IServiceManager指针,interface_cast不是指针的转换,而是利用BpBinder对象作为参数新建了一个BpServiceManager对象,那么再看下BpServiceManager是个什么东东,那就要看下IServiceManager的家族图谱了
1、IServiceManager、BpServiceManager和BnServiceManager都与业务逻辑相关。
2、BnServiceManager同时从IServiceManager BBinder派生,表示它可以直接参与Binder通信。
3、BpServiceManager虽然从BpInterface中派生,但是这条分支似乎与BpBinder没有关系。
4、BnServiceManager是一个虚类,它的业务函数最终需要子类来实现。
以上这些关系很复杂,但ServiceManager并没有使用错综复杂的派生关系,它直接打开Binder设备并与之交互。BpServiceManager,既然不像它的兄弟BnServiceManager那样与Binder有直接的血缘关系,那么它又是如何与Binder交互的呢?简言之,BpRefBase中mRemote值就是BpBinder。我们可以看BpServiceManager左边派生分支树上的一系列代码,它们都在IServiceManager.cpp中,如下所示:
IServiceManager.cpp::BpServiceManager类
BpServiceManager(const sp<IBinder>& impl)//实际上是传入的BpBinder对象
: BpInterface<IServiceManager>(impl)//调用基类BpInterface的构造
{
}
然后看下BpInterface
IInterface.h::BpInterface类
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
然后再看Binder.cpp::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.
}
}
BpServiceManager的一个变量mRemote指向了BpBinder。
回想一下defaultServiceManager函数,可以得到以下两个关键对象:
1、有一个BpBinder对象,它的handle值是0。
2、有一个BpServiceManager对象,它的mRemote值是BpBinder。BpServiceManager对象实现了IServiceManager的业务函数,现在又有BpBinder作为通信的代表,接下来的工作就简单了。
下面进行第三步,分析MediaPlayerService的注册过程,进一步分析业务函数的内部是如何工作的。 即main方法中的MediaPlayerService::instantiate();
MediaPlayerService.cpp,源码路径/frameworks/base/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
根据前面的分析可知,defaultServiceManager()实际返回的对象是BpServiceManager,它是IServiceManager的后代,调用它的addService方法,然后就会调用到IServiceManager.cpp::BpServiceManager的addService()函数中
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);//remote就是BpBinder对象
return err == NO_ERROR ? reply.readInt32() : err;
}
调用BpServiceManager的addService是一个业务层的函数,在addService函数中把请求数据打包成data后,传给了BpBinder的transact函数,这就把通信的工作交给了BpBinder。至此,业务层的工作原理应该是很清晰了,它的作用就是将请求信息打包后,再交给通信层去处理。
下面分析BpBinder的transact函数。前面说过,在BpBinder中确实找不到任何与Binder设备交互的地方。那它是如何参与通信的呢?原来,秘密就在这个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);//这里又把工作交给了IPCThreadState
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
那么下面我们就着重分析下IPCThreadState
IPCThreadState.cpp,源码路径/frameworks/base/libs/binder/IPCThreadState.cpp
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对象,构造函数中会调用pthread_setspecific
}
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;
}
TLS(Thread Local Storage),即线程本地存储空间,每个线程独有,线程间不共享TLS,通过pthread_getspecific和pthread_setspecific函数可以获取或设置这些空间中的内容,有调用pthread_getspecific的地方,肯定也有调用pthread_setspecific的地方
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()), mMyThreadId(androidGetTid())
{
pthread_setspecific(gTLS, this);//把自己设置到TLS中去,可从TLS中获取保存在其中的IPCThreadState对象
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
}
每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn、一个mOut,把它们看成发送和接收命令的缓冲区即可。其中,mIn是用来接收来自Binder设备的数据的,而mOut则是用来存储发往Binder设备的数据的。
我们刚才看到BpBinder的transact调用了IPCThreadState的transact函数,这个函数实际完成了与Binder通信的工作
status_t IPCThreadState::transact(int32_t handle,//handle为0,代表了通信的目的地
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
<< handle << " / code " << TypeCode(code) << ": "
<< indent << data << dedent << endl;
}
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);//发送数据,BC_TRANSACTION是应用程序向Binder设备发送的消息码,反之Binder设备向应用程序回复的消息码以BR_开头
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
err = waitForResponse(reply);//等待结果
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
<< handle << ": ";
if (reply) alog << indent << *reply << dedent << endl;
else alog << "(none requested)" << endl;
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
接下来看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;//binder_transaction_data是用于和Binder设备通信的数据结构
tr.target.handle = handle;//handle值传给target,标识目的端,0代表ServiceManager
tr.code = code;//消息码
tr.flags = binderFlags;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = statusBuffer;
tr.offsets_size = 0;
tr.data.ptr.offsets = NULL;
} else {
return (mLastError = err);
}
mOut.writeInt32(cmd);//把命令写到mOut中,而并不是直接发出去
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
现在,已经把addService的请求信息写到mOut中了。接下来再看发送请求和接收回复部分的实现,代码在waitForResponse函数中
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;//正是通过talkwithDriver和Binder驱动交互的
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing waitForResponse Command: "
<< getReturnString(cmd) << endl;
}
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
const int32_t result = mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ? NO_ERROR : INVALID_OPERATION;
}
goto finish;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
LOG_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 size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t),
freeBuffer, this);
} else {
err = *static_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
continue;
}
}
goto finish;
default:
err = executeCommand(cmd);//收到回复,会在executeCommand函数中处理
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
看下talkWithDriver()
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened");
binder_write_read bwr;//binder_write_read用于和Binder设备交换数据的结构
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don't want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
//请求命令填充
bwr.write_size = outAvail;
bwr.write_buffer = (long unsigned int)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {//接收数据缓冲区信息的填充,如果以后收到数据,直接填在mIn中
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsigned int)mIn.data();
} else {
bwr.read_size = 0;
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
alog << "Sending commands to driver: " << indent;
const void* cmds = (const void*)bwr.write_buffer;
const void* end = ((const uint8_t*)cmds)+bwr.write_size;
alog << HexDump(cmds, bwr.write_size) << endl;
while (cmds < end) cmds = printCommand(alog, cmds);
alog << dedent;
}
alog << "Size of receive buffer: " << bwr.read_size
<< ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
}
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(HAVE_ANDROID_OS)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//通过ioctl函数来发送和接收请求
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
IF_LOG_COMMANDS() {
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
IF_LOG_COMMANDS() {
alog << "Our err: " << (void*)err << ", write consumed: "
<< bwr.write_consumed << " (of " << mOut.dataSize()
<< "), read consumed: " << bwr.read_consumed << endl;
}
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed < (ssize_t)mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
alog << "Remaining data size: " << mOut.dataSize() << endl;
alog << "Received commands from driver: " << indent;
const void* cmds = mIn.data();
const void* end = mIn.data() + mIn.dataSize();
alog << HexDump(cmds, mIn.dataSize()) << endl;
while (cmds < end) cmds = printReturnCommand(alog, cmds);
alog << dedent;
}
return NO_ERROR;
}
return err;
}
发送了请求数据,如果收到回复,会在executeCommand函数中处理,看下executeCommand
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
LOG_ASSERT(refs->refBase() == obj,
"BR_ACQUIRE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
obj->incStrong(mProcess.get());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj);
obj->printRefs();
}
mOut.writeInt32(BC_ACQUIRE_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_RELEASE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
LOG_ASSERT(refs->refBase() == obj,
"BR_RELEASE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj);
obj->printRefs();
}
mPendingStrongDerefs.push(obj);
break;
case BR_INCREFS:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
refs->incWeak(mProcess.get());
mOut.writeInt32(BC_INCREFS_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_DECREFS:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
// NOTE: This assertion is not valid, because the object may no
// longer exist (thus the (BBinder*)cast above resulting in a different
// memory address).
//LOG_ASSERT(refs->refBase() == obj,
// "BR_DECREFS: object %p does not match cookie %p (expected %p)",
// refs, obj, refs->refBase());
mPendingWeakDerefs.push(refs);
break;
case BR_ATTEMPT_ACQUIRE:
refs = (RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
{
const bool success = refs->attemptIncStrong(mProcess.get());
LOG_ASSERT(success && refs->refBase() == obj,
"BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)",
refs, obj, refs->refBase());
mOut.writeInt32(BC_ACQUIRE_RESULT);
mOut.writeInt32((int32_t)success);
}
break;
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
LOG_ASSERT(result == NO_ERROR,
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
// We have inherited a reduced priority from the caller, but do not
// want to run in that state in this process. The driver set our
// priority already (though not our scheduling class), so bounce
// it back to the default before invoking the transaction.
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// once this method returns after the transaction is complete.
androidSetThreadSchedulingGroup(mMyThreadId,
ANDROID_TGROUP_BG_NONINTERACT);
}
}
//LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
Parcel reply;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_TRANSACTION thr " << (void*)pthread_self()
<< " / obj " << tr.target.ptr << " / code "
<< TypeCode(tr.code) << ": " << indent << buffer
<< dedent << endl
<< "Data addr = "
<< reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
<< ", offsets addr="
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);//这里的b指的是BnServiceXXX对象,从BBinder派生而来
const status_t error = b->transact(tr.code, buffer, &reply, 0);
if (error < NO_ERROR) reply.setError(error);
} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);//the_context_object定义在IPCThreadState中的全局变量,可通过setTheContextObject()设置
if (error < NO_ERROR) reply.setError(error);
}
//LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
<< tr.target.ptr << ": " << indent << reply << dedent << endl;
}
}
break;
case BR_DEAD_BINDER://收到来自Binder驱动的service死掉的消息,只有Bp端可以收到
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writeInt32((int32_t)proxy);
} break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
{
BpBinder *proxy = (BpBinder*)mIn.readInt32();
proxy->getWeakRefs()->decWeak(proxy);
} break;
case BR_FINISHED:
result = TIMED_OUT;
break;
case BR_NOOP:
break;
case BR_SPAWN_LOOPER://收到来自Binder驱动的指示创建一个新线程,用于和Binder通信
mProcess->spawnPooledThread(false);
break;
default:
printf("*** BAD COMMAND %d received from Binder driver\n", cmd);
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
然后分析第四步startThreadPool() 在ProcessState.cpp中 ProcessState::self()->startThreadPool();//创建一个线程池
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {//没执行过startThreadPool()
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
接着看spawnPooledThread(),传入参数true
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
char buf[32];
sprintf(buf, "Binder Thread #%d", s);
LOGV("Spawning new pooled thread, name=%s\n", buf);
sp<Thread> t = new PoolThread(isMain);
t->run(buf);
}
}
PoolThread是在IPCThreadState中定义的一个Thread子类,实现如下:
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);//在新线程中又创建了一个IPCThreadState,每个线程都有一个IPCThreadState,然后调用joinThreadPool,传入true
return false;
}
const bool mIsMain;
};
然后分析第五步joinThreadPool() 在IPCThreadState.cpp中 IPCThreadState::self()->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);//isMain为true,需要循环处理,把请求信息写到mOut中,等待一起发送出去
// 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 default/foreground
// one to avoid performing an initial transaction in the background.
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
status_t result;
do {
int32_t cmd;
// When we've cleared the incoming command queue, process any pending derefs
if (mIn.dataPosition() >= mIn.dataSize()) {
size_t numPending = mPendingWeakDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
RefBase::weakref_type* refs = mPendingWeakDerefs[i];
refs->decWeak(mProcess.get());
}
mPendingWeakDerefs.clear();
}
numPending = mPendingStrongDerefs.size();
if (numPending > 0) {
for (size_t i = 0; i < numPending; i++) {
BBinder* obj = mPendingStrongDerefs[i];
obj->decStrong(mProcess.get());
}
mPendingStrongDerefs.clear();
}
}
// now get the next command to be processed, waiting if necessary
result = talkWithDriver();//发送命令,读取请求
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "Processing top-level Command: "
<< getReturnString(cmd) << endl;
}
result = executeCommand(cmd);//处理消息
}
// After executing the command, ensure that the thread is returned to the
// default cgroup before rejoining the pool. The driver takes care of
// restoring the priority, but doesn't do anything with cgroups so we
// need to take care of that here in userspace. Note that we do make
// sure to go in the foreground after executing a transaction, but
// there are other callbacks into user code that could have changed
// our group so we want to make absolutely sure it is put back.
androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
// 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);
}
可以看到startThreadPool中新启动的线程通过joinThreadPool读取binder设备,查看是否有请求。主线程(主线程是在zygote fork应用程序进程时,在AppRuntime的onZygoteInit函数中创建,代码如下所示)也会调用joinThreadPool读取binder设备,查看是否有请求。所以可以有多个线程在为Service服务,也就是binder设备是支持多线程操作的。
AppRuntime在app_main.cpp中实现,源码路径/frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
if (proc->supportsProcesses()) {
LOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
}
MediaServer这个进程一共注册了4个服务,AudioFlinger、MediaPlayerService、CameraService、AudioPolicyService,如果实现的服务负担不是很重,完全可以不调用startThreadPool创建新的线程,使用主线程即可胜任。