【Binder系列课】一、Binder请求的主要流程梳理

这里仅仅梳理了主要的流程信息,方便大家查找。详细流程请参考:https://blog.csdn.net/tkwxty/category_9437770.html

1、servicesmanager进程binder进入等待

1.1 服务端进程:

//service_manager.c main();
open("/dev/binder", O_RDWR | O_CLOEXEC);
ioctl(bs->fd, BINDER_VERSION, &vers)
mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
binder_become_context_manager(struct binder_state *bs)
    ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); //驱动层 将全局变量binder_context_mgr_uid binder_context_mgr_node 赋值,创建binder_thread
binder_loop(bs, svcmgr_handler)
    //循环调用,先设置BC_ENTER_LOOPER,告诉Kernel binder驱动,我(ServiceManager进程)要进入消息循环状态了,请做好相关准备
    //然后再从kernel读取消息反馈
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 

1.2 进入驱动:

//bwr.write_size=0,而bwr.read_size不为0。
binder_ioctl()
    binder_thread_read()
        // 由于目前没有事务,servicemanger进程进入等待中
        // 阻塞式的读取,则阻塞等待事务的发生。
        wait_event_freezable_exclusive()

由此servicesmanager阻塞在main()–>binder_loop()–>binder_ioctl()–>binder_thread_read()–>wait_event_freezable_exclusive()

2、MediaPlayerService请求addService流程。

在这里插入图片描述

2.1 客户端侧:

remote->transact() --> 
BpBinder::transact() --> 
IPCThreadState::transact --> 
    IPCThreadState::writeTransactionData() 数据打包为 binder_transaction_data--> 
    IPCThreadState::waitForResponse //等待数据的返回--> 
        IPCThreadState::talkWithDriver() 数据打包为binder_write_read  --ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)发送数据 --

2.2 ioctl进入驱动侧:

 binder_ioctl() 将binder_write_read从“用户空间”拷贝到“内核空间”--binder_thread_write()  将binder_transaction_data 从“用户空间”拷贝到“内核空间”--//分配事务给服务端侧
    //分配待完成工作给客服端侧
    //通过binder_alloc_buf,在service内核空间开辟内存t->buffer,内存和用户空间存在映射。
    //<mark>将"用户空间的数据"拷贝到内核中binder_alloc_buf开辟的地址,将binder对象copy到内核中</mark>
    //解析flat_binder_object 修改type BINDER_TYPE_BINDER为BINDER_TYPE_BINDER
    //唤醒目标进程wake_up_interruptible
    binder_transaction() 
    binder_thread_read() 将 BR_NOOP 、 BINDER_WORK_TRANSACTION_COMPLETE拷贝到用户空间,意味着"Binder驱动已经将请求的内容都处理完毕了"

2.3 ioctl完毕 重回客户端侧:

        IPCThreadState::talkWithDriver() 释放mOut的内存,将bwr.read_consumed数据赋值给mIn.准备读取返回。——》
    IPCThreadState::waitForResponse //mIn中的数据就是Binder驱动返回的"BR_NOOP和BR_TRANSACTION_COMPLETE两个指令",BR_NOOP不执行任何操作,重新开始while循环,执行talkWithDriver()。--> 
        IPCThreadState::talkWithDriver() 由于 bwr.write_size和bwr.read_size都为0,因此直接返回NO_ERROR。再次返回waitForResp-->
    IPCThreadState::waitForResponse 读取到BR_TRANSACTION_COMPLETE--》
        IPCThreadState::talkWithDriver() binder线程进入等待请求的状态。--ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)发送数据 --

2.4 ioctl进入驱动侧:

此时bwr.write_size=0,因此只读不写,不会执行binder_thread_write()。而此时bwr.read_size>0,因此会调用binder_thread_read()进行读取动作。
(1) 此时,bwr.read_consumed=0,意味着*consumed=0。因此,还是会先将BR_NOOP写入到bwr.read_buffer中。
(2) 此时,当前线程的事务栈和待处理事务队列都是空,因此wait_for_proc_work=true。
(3) 在调用binder_set_nice()设置当前线程的优先级之后,就会调用wait_event_interruptible()。而此时binder_has_proc_work()为false,因此当前线程会进入中断等待状态。当Service Manager处理完MediaPlayerService的请求之后,就会将其唤醒。

由此客户端暂时等待servicemanger的处理。等待在流程图的第5步

三、servicemanager获取到请求

3.1 驱动侧

当前 servicemanager阻塞在binder_thread_read()–>wait_event_freezable_exclusive(),客户端唤醒servicemanager,我们从binder_thread_read()开始分析

    //从&thread->todo取出待完成的工作binder_transaction。
    //将binder_transaction 数据提取为binder_transaction_data
    //将cmd指令和binder_transaction_data 复制到用户空间。binder_transaction_data包含了传输的数据指针地址。
    //删除已处理的事务
    //修改*consumed的值,即bwr.read_consumed的值,表示待读取内容的大小。
    binder_thread_read()
//执行copy_to_user()将bwr拷贝到用户空间
binder_ioctl()

此时ServiceManager进程已经从驱动层返回回来,进入用户空间中执行,即回到binder_loop()中,那么我们继续分析binder_loop()。

3.2 回到ServiceManager进程

//ioct返回数据
binder_loop()
    //将数据转换为binder_transaction_data
    //进行解析
    //将binder_transaction_data转换为私有对象binder_io,msg和reply
    binder_parse()
        //根据msg获取service name和 flat_binder_object 要添加的binder代理对象flat_binder_object ->handle,而该handle在Binder驱动中被赋值为"MediaPlayerService对应的Binder引用的描述,即binder_ref->desc"。根据该引用描述,可以在Binder驱动中找到MediaPlayerService对应的Binder实体以及MediaPlayerService对应的进程上下文信息,进而可以给MediaPlayerService发送消息。
        svcmgr_handler()     
            //创建svcinfo 注册到svclist
            //svcinfo包含了MediaPlayerService的name和binder handle等信息
            do_add_service()
            //0表示不写数据到reply
            bio_put_uint32(reply, 0);
        //组装数据BC_FREE_BUFFER和BC_REPLY BC_REPLY是告诉Binder驱动,这是回复,这里回复的内容是null
        binder_send_reply()
        //将上面组装的数据告诉驱动。
        binder_write()
            ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

3.3 在回驱动侧

此时bwr.write_size>0,而bwr.read_size=0

binder_ioctl()
    //BC_FREE_BUFFER 释放分配的数据内存
    //BC_REPLY 继续执行binder_transaction()
    //在收到BC_REPLY之后,得知ServiceManager已经处理完addService请求
    binder_thread_write()
        //从MediaPlayerService线程的事务栈中删除该事务。
        //BINDER_WORK_TRANSACTION添加到MediaPlayerService 待处理事务队列target_list中。目的是告诉MediaPlayerService,它已经处理完了addService请求。
        //BINDER_WORK_TRANSACTION_COMPLETE 添加到Service Manager 的待处理事务队列thread->todo中
        //wake_up_interruptible()唤醒MediaPlayerService进程。
        binder_transaction()
//将数据拷贝到用户空间
binder_ioctl()

3.4 再回servicemanger

返回到binder_loop()会再次开始循环
并通过binder_ioctl()调用到binder_thread_read()时
处理事务BINDER_WORK_TRANSACTION_COMPLETE
便取出该事务进行执行,执行完毕之后,将该事务从Service Manager的待处理事务队列中删除,并反馈cmd=BR_TRANSACTION_COMPLETE信息给ServiceManager守护进程。
serviceManager守护进程收到Binder驱动的反馈后,解析出BR_TRANSACTION_COMPLETE,该指令什么也不做;它的目的是让ServiceManager知道,此次addService的反馈已经顺利完成!

于是,ServiceManager继续它的循环;当它再次调用ioctl(),进而进入到Binder驱动中读取请求时;由于此时的待处理事务队列为空,因此,ServiceManager会再次进入中断等待状态,等待Client的请求。

四、MediaPlayerService 处理数据反馈第10步

MediaPlayerService在发送addService请求之后,会阻塞在Binder驱动wait_event_interruptible_exclusive等待被唤醒

4.1 驱动侧

//取出事务BINDER_WORK_TRANSACTION
//将binder_transaction_data copy到用户空间,
//共反馈了两个指令到用户空间,BR_NOOP和BR_REPLY。
binder_thread_read()

4.2 MediaPlayerService重回用户空间

IPCThreadState::waitForResponse


//解析BR_REPLY
//取出数据binder_transaction_data
waitForResponse()
    //重新初始化Parcel的数据和对象。
    //ServiceManager返回的是空,就是告诉它addService已经成功处理完毕!
    Parcel->ipcSetDataReference()

MediaPlayerService 初始化完成。addService的整个流程也算告一段落了

int main(int argc __unused, char **argv __unused)
{
	...
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm(defaultServiceManager());
	...
    MediaPlayerService::instantiate();
    ResourceManagerService::instantiate();
	...
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值