转载请注明出处: http://blog.csdn.net/evan_man/article/details/51519754
注意:以下内容中出现的类和部分类的方法只能在Android源码中或者通过反射机制才能使用,在SDK中编译是通不过的!!如Android.os.Service; MemeoryFile.getParcelFileDescriptor()等你在SDK中无法使用!这里的内容只是帮助我们去了解Service、ContentProvider等功能为何能实现跨进程间的通信;它们无非就是通过Binder机制和虚拟内存实现的!!
简介
传统Linux系统的IPC方式 VS Android
- 传统的管道(Pipe)、信号(Signal)和跟踪(Trace),这三项通信手段只能用于父进程与子进程之间,或者兄弟进程之间;
- 报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore),插口(Socket)的进程间通信机制;
- Android系统没有采用上述提到的各种进程间通信机制,而是采用Binder机制,只需要复制一次效率更高。
Binder组件:
- 核心组件是Binder驱动程序,运行内核空间;
- Client、Server和Service Manager运行在用户空间
- Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力;
- Client和Server在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信;
- Service Manager和Binder驱动已经在Android平台中实现好,开发者只要按照规范实现自己的Client和Server组件;(依然很困难)
- 具体结构如下
实例(Java层应用)
用户定义了一个aidl文件(如 MyServe.aidl (interface MyServe))
随后编译后我们得到了一个对应的java类(如MyServe.java)。Activity通过bindService方法获得一个远程Service的IBinder对象;通过调用com.yq.MyServe.Stub.asInterface(iBinder);获得一个MyServe接口的对象,方法内部会判断返回给你一个继承自Stub的类——与Acitivity在同一个进程,还是一个Proxy(将远程调用另一个进程的继承自Stub的类,通过Parcel传递数据)对象。具体aidl编译后的文件内容为
MyServe.java文件内容如下:
public interface MyServe extends android.os.IInterface
- public static abstract class Stub extends android.os.Binder implements MyServe //服务端跑的代码
- private static final java.lang.String DESCRIPTOR = "com.yq.MyServe";
- public static MyServe asInterface(android.os.IBinder obj)
- {
- if ((obj==null)) { return null; }
- android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
- if (((iin!=null)&&(iin instanceof com.yq.MyServe))) return ((com.yq.MyServe)iin); //客户端是本地的一个进程;返回本地的MyServe对象
- return new com.yq.MyServe.Stub.Proxy(obj); //客户端是另外一个进程;创建一个MyServe.Stub.Proxy对象返回
- }
- public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
- {//code对应方法的签名;data对应参数;reply对应返回值
- switch (code)
- {
- case INTERFACE_TRANSACTION: xx
- //调用相关方法,从data获取数据,向reply写入数据;
- }
- }
- private static class Proxy implements com.yq.MyServe //另外一个进程,客户端跑的代码
- private android.os.IBinder mRemote;
- Proxy(android.os.IBinder remote) { mRemote = remote; } //获得外部类Stub的一个对象
- public int getxx() throws android.os.RemoteException //比如客户端调用了这个方法,内部其实走的是这样的
- {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- int _result;
- try {
- _data.writeInterfaceToken(DESCRIPTOR); //写入参数
- mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);
- //调用Stub对象的transact方法,其实最后是会调用上面的onTransact方法;最核心的东西
- //Stub.TRANSACTION_getPid对应onTransact方法的code
- //_data对应onTransact方法的data
- //_reply对应onTransact方法的reply
- _reply.readException();
- _result = _reply.readInt(); //从reply中读出数据
- }
- finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result; //返回结果,客户端最后获得这个结果
- }
注意:如果要利用Binder在进程之间传递对象,那么需要实现Parcelable接口:如果通过Bundle传递该对象(putParcelable),当通过getParcelable获取该对象的时候需要先给Bundle设置类加载(setClassLoader),这在跨进程之间通信显得尤为重要。
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
底层源码分析
在正式的分析之前首先做出如下约定:
- Binder机制中进行如下的分层:用户层、Binder层、IPCThreadState层、Binder驱动层
- 本文中使用的“Binder层协议”关键字表示该协议主要在Binder程序中出现。
- 这类协议常用的有:ADD_SERVICE_TRANSACTION、CHECK_SERVICE_TRANSACTION
- 本文中使用的“IPCThreadState层协议”关键字表示该协议主要在IPCThreadState程序中出现。
- 这类协议常用的有:BC_TRANSACTION、BR_TRANSACTON、BR_TRANSACTON_COMPLETE、BC_REPLY
- 本文中使用的“Binder驱动协议”关键字表示该协议主要在Binder驱动程序中出现。
- 这类协议常用的有:BINDER_SET_CONTEXT_MGR、BINDER_WRITE_READ、
Client端通信流程:
- Client进程在用户层将通信数据封装成Parcelable对象;
- Client进程将第一步获得的Parcelable对象交给Binder层处理(通过调用IBinder的transact方法进入Binder层)。Binder层在对数据进行必要的处理之后,将处理后得到的数据加上一个相关的Binder层协议头交给IPCThreadState层处理(调用IPCThreadState的Transact方法进入IPCThreadState层);【涉及的Binder层协议有:CHECK_SERVICE_TRANSACTION、GET_SERVICE_TRANSACTION、ADD_SERVICE_TRANSACTION、LIST_SERVICES_TRANSACTION】
- Client进程的IPCThreadState层也会对数据进行必要的处理之后,并将处理后得到的数据加上一个相关的IPCThreadState层协议头交给Binder驱动层进行处理(调用ioctl方法进入Bidner驱动层)。同时IPCThreadState层会一直等待来自Binder驱动层返回的数据,如果Client的请求需要有返回值那么IPCThreadState层只需要接收两条数据才可以返回,否则一般情况接收到一条数据就可以结束这次的进程间通信。【涉及的IPCThreadState层协议有:BC_TRANSACTION、BR_TRANSACTION_COMPLETE、BR_REPLY、BR_TRANSACTION、BC_REPLY】
Server端通信流程:
- Service通过IPCThreadState::joinThreadPool方法进入循环体中;
- Server进程的IPCThreadState层不断跟Binder驱动层进行交互(icotl方法根据参数的不同可能会导致阻塞),一旦获取到数据就交给IPCThreadState层的executeCommand方法进行处理,根据接收到的数据所属IPCThreadState层的哪个协议进行对应的处理。如接收到BR_TRANSACTION协议报文表明这是一个Binder发送来的请求Service处理的协议报文,IPCThreadState层会将得到的数据擦去IPCThreadState层协议头,然后交给Binder层处理处理(通过调用BBinder的transact方法,BBinder是通过发送来的BR_TRANSACTION协议报文得到的对象)。Binder层对数据处理完毕后,IPCThreadState层将Binder层处理后的数据加上一个BR_REPLY协议头,发送给Binder驱动层,同时等待Binder驱动层返回一条BR_TRANSACTON_COMPLETE协议报文结束这次进程间通信。
- BBinder的transact方法内部会调用其子类(对应Server端的BnXXX)的onTransact方法处理。onTransact方法内部根据接收到的数据所属哪个Binder层协议,对数据进行不同的处理,这里可以调用用户层的相关业务。方法执行完毕后回将到IPCThreadState层,调用IPCThreadState的sendReply方法返回处理后的数据给Binder驱动层。
Client&Server通信流程
(IPCThreadState层)——任何进程间通信都是下面的固定步骤
- Client进程将通信数据封装成Parcelable对象;
- Client进程向Binder驱动程序发送一个BC_TRANSACTION命令协议。Binder驱动根据协议内容找到目标Server进程后,向Client发送一个BR_TRANSACTON_COMPLETE返回协议,表示它的进程间请求已经被接受。Client对返回的BR_TRANSACTON_COMPLETE协议进行处理过后,就会再次进入Binder驱动程序中等待目标Server进程返回进程间通信结果。(这个过程Binder会将Client端数据拷贝到Service通过mmap申请得到的那块物理空间、Binder驱动将前面得到的物理空间对应的虚拟地址传递给Service的用户空间;Binder对数据的拷贝只会发生在这一个地方)
- Binder驱动程序在向Client发送BR_TRANSACTON_COMPLETE的同时会向Server发送一个BR_TRANSACTON协议,请求目标Server进程处理进程间通信请求。
- Server进程接收到Binder驱动程序发来的BR_TRANSACTON协议,并对它处理之后就会向Binder驱动程序发送一个BC_REPLY命令协议。Binder驱动程序根据BC_REPLY协议内容找到目标Client目标后,会向Server进程发送一个BR_TRANSACTON_COMPLETE协议,表示 它返回的通信结果已经收到。Server对BR_TRANSACTON_COMPLETE协议内容处理过后,一次进程间通信就结束了。接着再次进入驱动程序等待下一次进程间通信请求。
- Binder驱动程序在向Server进程发送一个BR_TRANSACTON_COMPLETE协议的同时会向Client发送BR_REPLY返回协议,并且将结果返回给Client。
正式对源码进行分析之前,首先对Binder机制中经常出现的几个类和接口进行简单的说明:
{ binder / IInterface.h}
class IInterface : public virtual RefBase
template //INTERFACE为自定义的一个接口继承IInterface
class BnInterface : public INTERFACE, public BBinder
template ///INTERFACE为自定义的一个接口继承IInterface
class BpInterface : public INTERFACE, public BpRefBase
INTERFACE是进程自定义的Service组件接口、BBinder为Binder本地对象提供了抽象的进程间通信接口、BpRefBase为Binder代理对象提供了抽象的进程间通信接口。
BnInterface为Binder本地对象, Service端使用,对应Binder驱动程序中的Binder实体对象;BpInterface为Binder代理对象,Client端使用,对应Binder驱动程序中的Binder引用对象。
用户需要编写一个BnXXXX实现BnInterface和
一个BpXXXX实现BpInterface<INTERFACE>的类,前者Service端使用,后者Client端使用。
BBinder@{ binder / Binder.h}
class BBinder : public IBinder{
public: ``````````````
virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
//IPCThreadState就会代用BBinder子类的该方法,该方法内部会调用BnXXXX对onTransact方法的实现。
protected: ````````````
virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
//BnXXXX实现BnInterface时就会定义该方法
};
BpRefBase@{ binde
r / Binder.h}
class BpRefBase : public virtual RefBase {
protected: ·······
BpRefBase(const sp& o);
inline IBinder* remote(){ return mRemote; }
private: ······
BpRefBase(const BpRefBase& o);
IBinder* const mRemote; //note1
};
1、指向一个BpBinder对象
BpBinder@{ binder / BpBinder.h}
class BpBinder : public IBinder {
public: ·········
inline int32_t handle() const { return mHandle; }
virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); //note2
private: ·······
const int32_t mHandle; //note1
};
1、该整数表示一个Client组件的句柄值。每一个Client组件在驱动程序对应一个Binder引用对象。
2、BpBinder的transact方法会把自己的mHandler和进程间通信数据发送给Binder驱动程序。Binder驱动程序根据mHandler找到对应的Binder引用对象,
进而找到Binder实体对象(Binder驱动层能够完成BpBinder到BBinder之间的映射),最后将通信数据发送给Service组件。(对于如何通过BpBinder找到BBBinder推荐查阅 博文,搜索关键字sp b((BBinder*)tr.cookie)即可
)
BBinder和BpBinder都是通过IPCThreadSate来和Binder驱动程序交互。
IPCThreadState @{ binder / IPCThreadState.h }
class IPCThreadState {
public: ········
static IPCThreadState* self();
//当前线程是Binder线程,通过它获取一个IPCThreadState对象,该对象可以跟Binder驱动层通信。
status_t transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
//与Binder驱动程序交互,底层通过talkWithDriver实现
private:············
status_t sendReply(const Parcel& reply, uint32_t flags);
status_t waitForResponse(Parcel *reply, status_t *acquireResult=NULL);
status_t talkWithDriver(bool doReceive=true); //向Binder驱动发送数据也从Binder驱动接收数据
status_t writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle,
uint32_t code,
const Parcel& data,
status_t* statusBuffer);
status_t executeCommand(int32_t command);
const sp mProcess; //初始化Binder设备
};
对于每个Binder线程池中它都有一个IPCThreadState对象
Service组件结构图
Client组件结构图
上面的分析我们可以简单的获得以下几个结论:
- Server端:BnXXX.cpp需要实现IXX的自定义方法和BBinder的onTransact方法;BBinder自己实现了transact方法,但是transact方法内部会调用onTransact方法。
- Client端:BpXXX.cpp需要实现IXX的自定义方法,方法内部是将数据包装之后利用BpRefBase的remote方法获得一个BpBinder,随后调用BpBinder的tranact方法将数据发送给Binder驱动程序。
- BBinder和BpBinder跟Binder驱动的通信都是通过IPCThreadState来实现的,通过IPCThreadState:self()方法获取该对象,注意通信的前提Client和Server端的主线程已经注册为Binder线程。
要知道Service、Client、Service Manager等用户态都是通过open、mmap、ioctl访问Binder驱动程序的。而open对应binder_open、mmap对应binder_mmap、ioctl对应binder_ioctl定义在android / binder.c文件中。下面重点分析一下ServiceManager的注册和相关重要方法!
service_manager.c
Binder通信机制使用句柄来代表远程接口,Service Manager在充当守护进程的同时,它充当Server的角色,当它作为远程接口使用时,它的句柄值便为0,这就是它的特殊之处,其余的Server的远程接口句柄值都是一个大于0 而且由Binder驱动程序自动进行分配的。
init进程负责启动ServiceManager,init进程是在系统启动时启动,因此ServiceManager在系统启动的时候跟随系统一同启动。
main()@{servicemanager / service_manager.c}
void *svcmgr_handle; //ServerManager.c的一个局部变量
int main(int argc, char **argv)
{
struct binder_state *bs; //note 1
void *svcmgr = BINDER_SERVICE_MANAGER; //note2
bs = binder_open(128*1024); //note3
if (binder_become_context_manager(bs)) { //note4
return -1;
}
svcmgr_handle = svcmgr; //note5
binder_loop(bs, svcmgr_handler); //note6
return 0;
}
1、
struct binder_state{
int fd; //设备描述符
void *mmaped; //映射空间起始地址
unsigned mapsize; //映射空间大小
//映射是将设备文件映射到进程的地址空间,用于缓存进程间通信的数据
}
2、#define BINDER_SERVICE_MANAGER ((void*) 0) //句柄值为0的宏定义
3、打开Binder设备文件;open("/dev/binder", O_RDWR);(建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);)
4、告诉Binder驱动程序自己是Binder上下文管理者,即我们前面所说的守护进程;binder_become_context_manager(bs);
5、保存到全局变量中,一个与ServiceManager对应的虚拟Binder本地对象
6、是进入一个无穷循环,充当Server的角色,等待Client的请求。binder_loop(bs, svcmgr_handler);
下面是对binder_open、binder_become_context_manager、binder_loop进行介绍
binder_open()@{ servicemanager / binder.c}
struct binder_state *binder_open(unsigned mapsize)
{
struct binder_state *bs;
bs = malloc(sizeof(*bs));
if (!bs) { errno = ENOMEM; return 0; }
bs->fd = open("/dev/binder", O_RDWR); //note1
if (bs->fd < 0) { fprintf(stderr,"binder: cannot open device (%s)\n",strerror(errno)); goto fail_open; }
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); //note2
if (bs->mapped == MAP_FAILED) {fprintf(stderr,"binder: cannot map device (%s)\n", strerror(errno)); goto fail_map;}
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return 0;
}
1、该方法最终导致Binder驱动程序的binder_open方法被调用
binder_become_context_manager()@{ servicemanager / binder.c}
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); //note1
}
1、该方法会导致Binder驱动的binder_ioctl方法被调用。binder_ioctl方法多次被使用到,已经贴在后面的附录一中。
通过向Binder驱动层发送BINDER_SET_CONTEXT_MGR协议将自己注册到Binder驱动程序中。ioctl中最后一个参数,表示当前Service Manager对应的本地Binder对象的地址值,Service Manager对应Binder本地对象值为0;
binder_loop()@{ servicemanager / binder.c}
BC_ENTER_LOOPER = _IO('c', 12),
BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
void binder_loop(struct binder_state *bs, binder_handler func){
int res;
struct binder_write_read bwr;
unsigned readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));//note1
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //note2
if (res < 0) { LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; }
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); //note3
if (res == 0) { LOGE("binder_loop: unexpected reply?!\n"); break;}
if (res < 0) { LOGE("binder_loop: io error %d %s\n", res, strerror(errno)); break; }
}
}
1、该方法用于将当前线程注册到Binder驱动程序中,成为Binder线程,Binder驱动程序随后可以将进程间通信请求交付给该线程进行处理
int binder_write(struct binder_state *bs, void *data, unsigned len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (unsigned) data;
bwr.read_size = 0; //输出缓存区为空,则一旦完成注册,就会退回到用户空间中。
bwr.read_consumed = 0;
bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //note1
if (res < 0) {
fprintf(stderr,"binder_write: ioctl failed (%s)\n", strerror(errno));
}
return res;
}
1、向Binder驱动层发送一个BINDER_WRITE_READ协议报文
2、该方法的bwr参数的输出缓存区长度为readbuf大小,输入缓存区长度等于0,因此只会调用函数binder_thread_read。如果ServiceManager进程的主线程没有待处理的工作项,它将会睡眠在Binder驱动程序的binder_thread_read中,等待其它Service和Client向它发送进程间通信请求。
3、解析获得的readbuf数据,使用binder_handler func处理
binder_parse()@{ servicemanager / binder.c}
int binder_parse(struct binder_state *bs, struct binder_io *bio, uintptr_t ptr, size_t size, binder_handler func) {
int r = 1;
uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end) {
uint32_t cmd = *(uint32_t *) ptr;
ptr += sizeof(uint32_t);
switch(cmd) {
case BR_NOOP:
break;
case BR_TRANSACTION_COMPLETE:
break;
case BR_INCREFS:
case BR_ACQUIRE:
case BR_RELEASE:
case BR_DECREFS:
ptr += sizeof(struct binder_ptr_cookie);
break;
case BR_TRANSACTION: { //note1
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
if ((end - ptr) < sizeof(*txn)) { return -1; }
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
res = func(bs, txn, &msg, &reply); //note2
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); //note3
}
ptr += sizeof(*txn);
break;
}
case BR_REPLY: {
......
break;
}
case BR_DEAD_BINDER: {
........
break;
}
case BR_FAILED_REPLY:
r = -1;
break;
case BR_DEAD_REPLY:
r = -1;
break;
default:
return -1;
}
}
return r;
}
1、接收到一个IPCThreadState层协议——BR_TRANSACTION;
2、调用func处理,func等于servicemanager / service_manager.c的svcmgr_handle对象。
3、向Binder驱动器发送BC_REPLY协议报文
svcmgr_handler()@{ servicemanager / service_manager.c}
int svcmgr_handler(struct binder_state *bs, struct binder_txn *txn, struct binder_io *msg, struct binder_io *reply) {
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
if (txn->target != svcmgr_handle) return -1;
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len); //从列表中查找服务
if (!ptr) break;
bio_put_ref(reply, ptr); //这里是{servicemanager / binder.c}中的方法;ptr是句柄号,将内容写入到reply中。
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
if (do_add_service(bs, s, len, ptr, txn->sender_euid)) return -1;
break;
case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);
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;
}
binder_send_reply()@{ servicemanager / binder.c}
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;
data.buffer = buffer_to_free;
data.cmd_reply = BC_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_write(bs, &data, sizeof(data)); //在binder_loop()已经介绍过会
}
这里需要特别注意的是ServiceManager跟普通Service的不同之处还在于。对于普通XXService,Client获取到一个BpXXService,然后调用它的一个方法,最终通过Binder机制会将数据交给BnXXService的同名方法处理。然而对于ServiceManager,Client获取到一个BpServiceManager,然后调用它的一个方法,如getService,最终通过Binder机制会将数据交给svcmgr_handler()@{ servicemanager / service_manager.c}处理,而不是交给BnServiceManage处理!!!详细参考链接
ServiceManager注册:
- 调用binder_open(128*1024)方法打开文件描述符和在当前进程给/dev/binder设备描述符映射一个块空间。
- 调用binder_become_context_manager方法注册自己成为Bidner机制的上下文管理者。方法内部通过ioct方法进入到Binder驱动层,发送一条BINDER_SET_CONTEXT_MGR的Binder驱动层协议的报文。
- 调用binder_loop方法进入循环,向Binder驱动器协议发送一条BC_ENTER_LOOPER的IPCThreadState层协议报文,使得当前主线程注册成为Binder线程;随后与Binder驱动层交互获得请求数据交给binder_parse()方法处理。
- 根据不同的IPCThreadState层协议报文进行不同处理。如得到BR_TRANSACTION的IPCThreadState层协议报文,会将报文数据解析出来交由svcmgr_handler()方法处理,该方法会解析Binder层协议报文类型,如SVC_MGR_ADD_SERVICE则调用自身的do_add_service方法进行处理,方法执行结束后调用binder_write向IPCThreadState层写入一个BC_REPLY协议报文。
下面分析一下获取ServiceManager代理的getDefaultServiceManager方法底层实现。
getDefaultServiceManager方法的实现
getDefaultServiceManager@{binder/IServiceManager.cpp}
对于一个一般的Service组件,Client首先需要通过Binder驱动程序获得它的一个句柄值,然后才可以根据这个句柄创建一个Binder代理对象(BpBinder),最后再将这个BpBinder转换成一个实现了特定接口的代理对象。ServiceManager句柄值为0,因此获取ServiceManager组件就没有获取BpBinder的过程。
sp defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast(
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
Binder库中定义了一个gDefaultServiceManager全局变量,而且采用了单例的模式进行实现,getDefaultServiceManager方法获得的就是该全局变量。在第一次请求该变量的时候会通过如下的方式获取一个ServiceManager代理。interface_casr (ProcessState:self()->getContextObject(NULL));
- ProcessState:self()获得的是一个ProcessState(是一个单例模式)
- 构造器中调用open_driver方法;
- int fd = open("/dev/binder", O_RDWR); //打开/dev/binder设备描述符,将获取到的文件描述符存储到ProcessState对象中的一个域中
- result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); //告知Binder,其最多可以请求15条线程处理进程间通信
- mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); //使用mmap将/dev/binder映射进进程的地址空间中,映射大小为1016KB;
- ProcessState:self()->getContextObject(NULL)创建一个句柄为0的Binder代理(BpBinder)
- 直接调用getStrongProxyForHandle(0) //表示要创建的Binder代理对象的句柄为0
- interface_casr (const sp& obj)利用第二步得到的Binder代理构建一个ServiceManager代理
- 等价于new BpServiceManager(obj)
getDefaultServiceManager方法调用结束后,我们首先获得一个ProcessState对象——单列模式(该对象有打开了/dev/binder描述符,设备描述符向进程映射了一段地址空间)、通过ProcessState的getContextObject方法获得一个句柄为0的BpBinder对象(该Binder代理构造器中创建了一个IPCThreadState对象——单例模式),最后利用BpBinder创建一个BpServiceManager对象。
getDefaultServiceManager方法让我们获得了一个sp对象,之后就可以调用该对象的addService、getService方法添加和获取指定的Service代理了,下面依次介绍这两个方法。
ServerManager——addService
下面方法是用户添加服务的方法
addService@{binder/IServiceManager.cpp}
virtual status_t addService(const String16& name, const sp& service){
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
前面已经介绍Remote方法获取的是一个BpBinder对象,调用BpBinder对象的transact方法将数据和当前BpBinder对应的句柄发送给Binder驱动层处理。数据封装成一个ADD_SERVICE_TRANSACTION的协议报文交给Binder层处理。
BpBinder::transact()@{ binder / BpBinder.cpp}
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) //最后一个参数为0表示同步进程间请求,否则异步;默认为0
{
if (mAlive) {
status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
Binder层的数据继续包装成一个IPCThreadState层的BC_TRANSACTION协议报文交给IPCThreadState层处理,调用IPCThreadState对象的transact方法
IPCThreadState::transact()@{ binder / IPCThreadState.cpp}
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; //flag设置标志位
if (err == NO_ERROR) {
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); //note1
}
if ((flags & TF_ONE_WAY) == 0) { //同步请求
if (reply) { err = waitForResponse(reply); }
else {
Parcel fakeReply;
err = waitForResponse(&fakeReply); //等待Service的返回数据
}
}
else { err = waitForResponse(NULL, NULL); } //不等待Service的返回数据
return err;
}
1、 将BC_TRANSACTION协议报文数据写入到binder_transaction_data结构体中。 再将该对象写入到IPCThreadState中的一个Parcel输出缓冲区中
IPCThreadState::waitForResponse()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
int32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break; //note1
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = mIn.readInt32(); //note2
switch (cmd) {
case BR_TRANSACTION_COMPLETE: //note3
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:
```````
goto finish;
case BR_REPLY: { //note4
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
if (err != NO_ERROR) goto finish;
if (reply) { //reply不为空则给它设值
if ((tr.flags & TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t),
freeBuffer, this);
} .....
}
} else {
......
continue;
}
}
goto finish;
default:
err = executeCommand(cmd);
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;
}
1、与Binder驱动程序交互,将前面IPCThreadState::transact()方法中向Parcel输出缓冲区中写入的数据传给Binder驱动
2、读取Binder驱动返回的协议报文
3、收到来自Binder驱动器层的BR_TRANSACTION_COMPLETE协议报文,如果 if (!reply && !acquireResult)为真则退出giant方法,否则继续等待下一个协议报文
4、收到来自Binder驱动器层的BR_REPLY:协议报文,读取报文中的数据交给Parcel *reply。随后用户就可以读取其中的数据了
IPCThreadState::talkWithDriver()@{ bind
er / IPCThreadState.cpp}
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 = (long unsigned int)mOut.data(); //即将写入到Binder驱动的数据
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsigned int)mIn.data(); //获得Binder驱动返回的数据
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) ///note1
....
}
1、将获取到的数据封装成一个Binder驱动层的BINDER_WRITE_READ协议报文,交给Binder启动层处理。
使用ioctl方法向Binder驱动层传输数据,
IPCThreadState的mProcess变量的mDriverFD即/dev/driver文件描述符。
综上addService方法首先将参数String16& name, sp包装成一个Binder层的ADD_SERVICE_TRANSACTION协议报文,传给Binder层处理。之后数据包装成 IPCThreadState层的BC_TRANSACTION协议报文。最后数据又被包装成Binder驱动层的BINDER_WRITE_READ协议报文交给Binder驱动层处理。
ServerManager——getService
getService()@{binder/IServiceManager.cpp}
virtual sp getService(const String16& name) const {
unsigned n;
for (n = 0; n < 5; n++){
sp svc = checkService(name);
if (svc != NULL) return svc;
sleep(1);
}
return NULL;
}
checkService()@{binder/IServiceManager.cpp}
virtual sp 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();
}
与addService方法类似,getService方法首先将参数String16& name包装成一个Binder层的CHECK_SERVICE_TRANSACTION协议报文,传给Binder层处理。之后数据包装成 IPCThreadState层的BC_TRANSACTION协议报文。最后数据又被包装成Binder驱动层的BINDER_WRITE_READ协议报文交给Binder驱动层处理。
Service——注册(以mediaServer为例)
main()@{ mediaserver / main_mediaserver.cpp}
int main(int argc, char** argv){
//获得一个ProcessState实例,前面已经介绍过
sp proc(ProcessState::self());
//得到一个ServiceManager对象,前面已经介绍过
sp sm = defaultServiceManager();
MediaPlayerService::instantiate();//note1
ProcessState::self()->startThreadPool();//note2
IPCThreadState::self()->joinThreadPool();//note3
}
1、MediaPlayerService 实例化,该方法内部为defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService())方法。
service_manager
收到
addService
的请求,然后把对应信息放到自己保存的一个服务
list
中。具体内容参见前面的addService说明。
2、启动一个Binder线程池
3、将当前主线程添加到这个Binder线程池中去等待和处理Client进程的通信请求。一旦收到一个请求就调用executeCommand去处理这个命令,
startThreadPool()@{ binder / ProcessState.cpp}
void ProcessState::startThreadPool() {
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
spawnPooledThread()@{ binder / ProcessState.cpp}
void ProcessState::spawnPooledThread(bool isMain) {
if (mThreadPoolStarted) {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
char buf[32];
sprintf(buf, "Binder Thread #%d", s);
sp t = new PoolThread(isMain); //创建PoolThread对象
t->run(buf); //启动该线程池
}
}
joinThreadPool()@{ binder / IPCThreadState.cpp}
void IPCThreadState::joinThreadPool(bool isMain) { //默认参数为ture
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); //note1
status_t result;
do {
int32_t cmd;
......
result = talkWithDriver(); //note2
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) continue;
cmd = mIn.readInt32();
result = executeCommand(cmd); //处理从Binder驱动返回回来的协议数据
}
....
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
1、
形成一个BC_ENTER_LOOPER 协议报文,将报文写入mOut的Parcel输出缓冲区中。
isMain == true表示进入到Looper,否则为注册到Looper;
2、将mOut缓冲区中的数据传给Binder驱动,上面我们知道这里会将数据包装成一个Binder驱动层的BINDER_WRITE_READ协议报文交给Binder驱动层处理
executeCommand()@{ binder / IPCThreadState.cpp}
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();
obj->incStrong(mProcess.get());
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();
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();
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());
mOut.writeInt32(BC_ACQUIRE_RESULT);
mOut.writeInt32((int32_t)success);
}
break;
case BR_TRANSACTION:{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast(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;
mOrigCallingUid = tr.sender_euid;
int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
Parcel reply;
if (tr.target.ptr) {
sp b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags); //调用BBinder的transact方法处理,实则底层就是调用具体服务的onTransact方法!
if (error < NO_ERROR) reply.setError(error);
} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
sendReply(reply, 0); //发送一个IPCThreadState层的BC_REPLY协议报文给Binder驱动层
} else { }
mCallingPid = origPid;
mCallingUid = origUid;
mOrigCallingUid = origUid;
}
break;
case BR_DEAD_BINDER:
{
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:
mProcess->spawnPooledThread(false);
break;
default:
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
BBinder::transact()
status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
err = onTransact(code, data, reply, flags); //就是调用自己的onTransact函数嘛
return err;
}
sendReply()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
{
status_t err;
status_t statusBuffer;
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
return waitForResponse(NULL, NULL);
}
Service注册:
- 创建一个ProcessState对象,该对象会打开文件描述符和在当前进程给/dev/binder设备描述符映射一个块空间。
- 利用ProcessState的getContextObject(NULL)方法获取一个句柄为0的IBinder对象,该IBinder对象的创建过程中会创建一个IPCThreadState对象。
- 利用IBinder对象创建一个IServerManager对象。
- 创建一个当前服务的实例,并调用IServerManager的addService方法,将自己注册到ServiceMaanger列表中。addService的过程是一个"Client端通信流程",具体后文还会再讲
- 启动一个Binder线程池和并将当前主线程加入到Binder线程池中,最终进入到“Server端通信流程”
Service循环:
IPCThreadState的joinThreadPool方法开启了一个循环,不断与Binder驱动进行通信,当获取到信息就调用executeCommand( cmd )方法对消息进行处理。比如cmd为BR_TRANSACTION,即表明是Binder发送过来的期望Service处理的数据,首先从得到的数据中得到sp
对象,随后调用该对象的transact方法,方法内部会调用BBinder绑定的Service(其实就是当前Service)的onTransact的方法进行处理,处理过后将结果以BC_REPLY协议报文返回Binder,然后调用waitForResponse方法等待Binder返回一个BR_TRANSACTION_COMPLETED协议报文,最后结束这一次的服务。
注意:
startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。为什么要这么做呢?他们参数isMain都是true。不知道google搞什么。难道是怕一个线程工作量太多,所以搞两个线程来工作?这种解释应该也是合理的。网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程提出了,程序还能不退出吗?这个...管它的,反正知道有两个线程在那处理就行了。
Client情景分析(以mediaServer为例)
使用MediaPlayerService的时候,先要创建它的BpMediaPlayerService,一个描述了实现IMediePlayService接口的组件。
defaultServiceManager()->getService(String16(MEDIA_SERVICE));该方法在前面的ServiceManager已经介绍过了,获得了一个IBinder对象。之后又利用该IBinder包装成一个IServiceManager对象。当我们调用IServiceManager的一个方法的时候实则调用IBinder的transact方法,首先写入Binder层的协议报文再通过调用IPCThreadState的transact方法处理,IPCThreadState又会将报文加一个文件
头
如BC_TRANSACTION头,通过ioctl发送到Binder驱动程序,Binder将该报文发给对应的服务端的时候就会返回一个BR_TRANSACTION_COMPLETED协议,Client继续等待直到Binder发送BR_REPLY,这时候CLIEN读取该协议的数据返回Client用户空间,这样一次进程间通信就结束了。
总结:
虽然说这是Binder机制——初探,但是内容一点也不少,不过这真的只是Binder的冰山一角。本文只是在open、mmap、ioctl基础之上对Binder机制进行分析,而对于具体的binder驱动层没有进行介绍。想了解Binder机制还是需要有一个切入点比较好,如果你还很迷茫不知道何从下手,那么个人建议按照ServiceManager的注册、具体Service的注册、Client对Service的访问三个步骤来了解Binder机制。
而针对上面的三个步骤又可以细分如下
- ServiceManager注册:binder_open() 、binder_become_context_manager() 、binder_loop(){该部分细分:ioctl()、 ioctl、binder_parse}
- Service注册:getDefaultServiceManager(){底层实现细分:ProcessState、IPCThreadState、BpBinder、BpServiceManager}、addService(){底层在进程间通信时分析} 、Binder线程池、 IPCThreadState线程注册为Biinder线程并进入循环{该部分细分: talkWithDriver、executeCommand}
- Client对Service的访问:getDefaultServiceManager()、getService(){底层在进程间通信时分析} 、进程间通信{该部分细分如下: BpBinder.transact() 、IPCThreadState.transact() 、 IPCThreadState.waitForResponse(){ 该部分细分: IPCThreadState.talkWithDriver() 、等待Binder驱动层返回协议报文} }
附录一:binder驱动层
binder_ioctl@{ android / binder.c}
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret;
struct binder_proc *proc = filp->private_data;
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret)
goto err_unlocked;
binder_lock(__func__);
thread = binder_get_thread(proc);
if (thread == NULL) {
ret = -ENOMEM;
goto err;
}
switch (cmd) {
case BINDER_WRITE_READ: {
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto err;
}
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { //获取用户态的binder_write_read对象
ret = -EFAULT;
goto err;
}
if (bwr.write_size > 0) {//如果输入缓冲区长度大于0则调用binder_thread_write方法
ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
trace_binder_write_done(ret);
if (ret < 0) {
bwr.read_consumed = 0;
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto err;
}
}
if (bwr.read_size > 0) {//如果输出缓冲区长度大于0则调用binder_thread_read方法
ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
trace_binder_read_done(ret);
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
if (ret < 0) {
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
ret = -EFAULT;
goto err;
}
}
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
ret = -EFAULT;
goto err;
}
break;
}
case BINDER_SET_MAX_THREADS:
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
ret = -EINVAL;
goto err;
}
break;
case BINDER_SET_CONTEXT_MGR:
if (binder_context_mgr_node != NULL) {
printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
goto err;
}
ret = security_binder_set_context_mgr(proc->tsk);
if (ret < 0)
goto err;
if (binder_context_mgr_uid != -1) {
if (binder_context_mgr_uid != current->cred->euid) {
printk(KERN_ERR "binder: BINDER_SET_"
"CONTEXT_MGR bad uid %d != %d\n",
current->cred->euid,
binder_context_mgr_uid);
ret = -EPERM;
goto err;
}
} else
binder_context_mgr_uid = current->cred->euid;
binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
if (binder_context_mgr_node == NULL) {
ret = -ENOMEM;
goto err;
}
binder_context_mgr_node->local_weak_refs++;
binder_context_mgr_node->local_strong_refs++;
binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1;
break;
case BINDER_THREAD_EXIT:
binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n",
proc->pid, thread->pid);
binder_free_thread(proc, thread);
thread = NULL;
break;
case BINDER_VERSION:
if (size != sizeof(struct binder_version)) {
ret = -EINVAL;
goto err;
}
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
ret = -EINVAL;
goto err;
}
break;
default:
ret = -EINVAL;
goto err;
}
ret = 0;
err:
if (thread)
thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
binder_unlock(__func__);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
trace_binder_ioctl_done(ret);
return ret;
}
reference:
【1】 http://blog.csdn.net/luoshengyang/article/details/6618363
【2】 http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html
(内容比较乱,但是讲的不错)
【3】《Android源码系统情景分析》 罗升阳
【4】《深入理解android 卷I/卷II》 邓凡平
【5】《Android内核剖析》柯元旦
【】http://blog.csdn.net/evan_man/article/details/51519754