我的进阶曲线之八

Android Binder

什么是Binder?

http://blog.csdn.net/luoshengyang/article/details/6618363


Android 为什么选择Binder?

l轻量级

目前linux支持的IPC包括传统的管道,System V IPC,即消息队列/共享内存/信号量,以及socket。只有socket支持Client-Server的通信方式。当然也可以在这些底层机制上架设一套协议来实现Client-Server通信,但这样增加了系统的复杂性,在手机这种条件复杂,资源稀缺的环境下可靠性也难以保证。

l安全性

使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加。

l传输性能

http://blog.csdn.net/universus/article/details/6211589/

共享内存虽然无需拷贝,但控制复杂,难以使用。

即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程

binder传输过程只需一次拷贝,为发送发添加UID/PID身份


核心优势:内存拷贝一次

核心代码:

  if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {


案例:注册MediaPlayerService服务

•1 创建服务进程
•2 获取ServiceManager引用
•3 在ServiceManager中注册服务


在Android系统中,提供了多媒体播放的功能,这个功能是以服务的形式来提供的。

 sp<ProcessState> proc(ProcessState::self());

        sp<IServiceManager> sm =defaultServiceManager();

       ALOGI("ServiceManager: %p", sm.get());

        AudioFlinger::instantiate();

        MediaPlayerService::instantiate();


创建服务进程(1)

MediaPlayerService服务启动代码

framework\base\Media\MediaServer\Main_mediaserver.cpp

intmain(int argc,char** argv)

{

        sp<ProcessState> proc(ProcessState::self());

        sp<IServiceManager> sm = defaultServiceManager();

       ALOGI("ServiceManager: %p", sm.get());

        AudioFlinger::instantiate();

        MediaPlayerService::instantiate();

        CameraService::instantiate();

//获得一个ProcessState实例

//得到一个ServiceManager引用

/初始化MediaPlayerService服务


创建服务进程(2)

获得一个ProcessState实例,并打开binder设备

framework\native\libs\binder\ProcessState.cpp

ProcessState::ProcessState()

    : mDriverFD(open_driver())

打开/dev/binder设备

framework\native\libs\binder\ProcessState.cpp

intfd = open("/dev/binder",O_RDWR);

设备内存映射

framework\native\libs\binder\ProcessState.cpp

 mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

http://blog.csdn.net/luoshengyang/article/details/6627260


创建服务进程(3)

深入理解设备内存映射:binder mmap

framework\native\libs\binder\ProcessState.cpp

mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

kernel\common\drivers\staging\android\binder.c

static intbinder_mmap(struct file *filp, structvm_area_struct *vma)

第一次只申请一页的物理内存,后续按需申请。

kernel\common\drivers\staging\android\binder.c

binder_update_page_range(proc, 1,proc->buffer, proc->buffer + PAGE_SIZE, vma)

http://blog.csdn.net/luoshengyang/article/details/6621566

 这里为什么会同时使用进程虚拟地址空间和内核虚拟地址空间来映射同一个物理页面呢?这就是Binder进程间通信机制的精髓所在了,同一个物理页面,一方映射到进程虚拟地址空间,一方面映射到内核虚拟地址空间,这样,进程和内核之间就可以减少一次内存拷贝了,提到了进程间通信效率。


创建服务进程(4)

深入理解设备内存映射:binder mmap

分配一个物理页面

kernel\common\drivers\staging\android\binder.c

*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM |__GFP_ZERO);

将这个物理页面插入到进程内核空间

kernel\common\drivers\staging\android\binder.c

ret = map_vm_area(&tmp_area, PAGE_KERNEL,&page_array_ptr);

进程虚拟空间地址

kernel\common\drivers\staging\android\binder.c 

user_page_addr = (uintptr_t)page_addr + proc->user_buffer_offset;


创建服务进程(5)

http://blog.csdn.net/luoshengyang/article/details/6627260


创建服务进程(6)

http://www.cnblogs.com/zhangxinyan/archive/2013/12/27/3487909.html

一个process里有个实体对象,就有多少个binder_node;一个process有多少个代理对象指向远端,就有多少个binder_ref.


•2 获取ServiceManager引用

defaultServiceManager模板代入

frameworks\native\libs\binder\IServiceManager.cpp

framework\native\libs\binder\ProcessState.cpp

gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0)); 

frameworks\native\libs\binder\IServiceManager.cpp

gDefaultServiceManager = new BpServiceManager(new BpBinder(0));  

http://blog.csdn.net/luoshengyang/article/details/6627260

l         ProcessState有了。

l         IPCThreadState有了,而且是主线程的。

l         BpBinder有了,内部handle值为0


BpServiceManager UML

http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html

返回的实际是BpServiceManager,它的remote对象是BpBinder,传入的那个handle参数是0。

BpRefBase::BpRefBase(const sp<IBinder>& o)

    :mRemote(o.get()), mRefs(NULL), mState(0)

//o.get(),这个是sp类的获取实际数据指针的一个方法,你只要知道

//它返回的是sp<xxxx>中xxx* 指针就行

{

//mRemote就是刚才的BpBinder(0)


•3 在ServiceManager中注册服务

调用ServiceManager方法:addservice

frameworks\av\media\libmediaplayerservice\ MediaPlayerService.cpp

void MediaPlayerService::instantiate() {

    defaultServiceManager()->addService(

            String16("media.player"), new MediaPlayerService());

}

frameworks\native\libs\binder\IServiceManager.cpp:

BpServiceManager : addService

status_t err =remote()->transact(ADD_SERVICE_TRANSACTION, data,

&reply);

mso-color-index:1;mso-font-kerning:12.0pt;language:en-US'>)) {

framework\base\libs\binder\BpBinder.cpp

status_t status = IPCThreadState::self()->transact(

            mHandle, code, data, reply, flags);


http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html

IPCThreadState 对象是在创建 BpBinder对象时候创建的。 (framework\base\libs\binder\IPCThreadState.cpp)

基类BpInterface的构造函数(经过兑现后)

inline BpInterface< IServiceManager >::BpInterface(const sp<IBinder>& remote)

    :BpRefBase(remote)

{

}

frameworks\native\libs\binder\binder.cpp

BpRefBase::BpRefBase(const sp<IBinder>& o)

    :mRemote(o.get()), mRefs(NULL), mState(0)

//o.get(),这个是sp类的获取实际数据指针的一个方法,你只要知道

//它返回的是sp<xxxx>中xxx* 指针就行

{

//mRemote就是刚才的BpBinder(0)


通过IPCThreadState对象来和binder驱动交互

frameworks\native\libs\binder\IPCThreadState.cpp

IPCThreadState::transact

err = waitForResponse(reply);

frameworks\native\libs\binder\IPCThreadState.cpp

if ((err=talkWithDriver()) < NO_ERROR) break;

frameworks\native\libs\binder\IPCThreadState.cpp

if (ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr) >= 0)


在ServiceManager中注册服务(3)

IPCThreadState 对象是在创建 BpBinder对象时候创建的。 (framework\base\libs\binder\IPCThreadState.cpp)

终于来到了内核空间:binder驱动

kernel/common/drivers/staging/android/binder.c

static long binder_ioctl(struct file *filp, unsigned intcmd, unsigned long arg)

switch (cmd) {

case BINDER_WRITE_READ: {

if (bwr.write_size > 0) {

ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);

http://blog.csdn.net/luoshengyang/article/details/6629298


binder事务


kernel/common/drivers/staging/android/binder.c

binder_thread_write

target_proc = target_node->proc;


注意,这里传进来的参数reply为0,tr->target.handle也为0。

case BC_TRANSACTION:

binder_transaction(proc, thread,&tr, cmd == BC_REPLY);

kernel/common/drivers/staging/android/binder.c

binder_transaction

if (tr->target.handle) {

} else {

target_node = binder_context_mgr_node;

http://blog.csdn.net/luoshengyang/article/details/6629298


核心动作:直接复制请求数据到目标进程空间


kernel/common/drivers/staging/android/binder.c

binder_transaction


t->buffer = binder_alloc_buf(target_proc, tr->data_size,

  tr->offsets_size, !reply && (t->flags &TF_ONE_WAY));

.0pt;language:zh-CN'>mso-color-index:1;mso-font-kerning:12.0pt;language:en-US'>)) {

kernel/common/drivers/staging/android/binder.c

binder_transaction


if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {


if (target_wait)

  wake_up_interruptible(target_wait);

在ServiceManager中注册服务(7)

http://my.oschina.net/youranhongcha/blog/152963

核心代码:

  if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值