美文网首页
binder(四) 服务注册过程

binder(四) 服务注册过程

作者: 曾大稳丶 | 来源:发表于2021-06-09 16:44 被阅读0次

    应用层主要逻辑

    //1. 打开驱动,mmap映射
    binder_open
    //2. 构造binder_write_read通过ioctl和驱动交互添加server到servicemanager
     ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
    
    //3. looper解析接受到的数据,server_handler_func是具体执行的函数
    binder_loop(bs, server_handler_func);
    
    
    1. 打开驱动,mmap映射,binder_open,和servicemanager启动一样流程
    1. 构造binder_write_read通过ioctl和驱动交互添加server到servicemanager,svcmgr_publish , binder_call
    // target = BINDER_SERVICE_MANAGER =0,代表servicemanager的handle, ptr代表收到消息处理的函数 
    int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
    {
        int status;
        unsigned iodata[512/4];
        struct binder_io msg, reply;
        //构造binder_io
        bio_init(&msg, iodata, sizeof(iodata), 4);
        bio_put_uint32(&msg, 0);  // strict mode header
        bio_put_string16_x(&msg, SVC_MGR_NAME);
        bio_put_string16_x(&msg, name);
        //构建flat_binder_object
        bio_put_obj(&msg, ptr);
        // 构造binder_transation_data 和iocol交互 ,code是SVC_MGR_ADD_SERVICE
        if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
            return -1;
    
        status = bio_get_uint32(&reply);
    
        binder_done(bs, &msg, &reply);
    
        return status;
    }
    
    
    
    int binder_call(struct binder_state *bs,
                    struct binder_io *msg, struct binder_io *reply,
                    uint32_t target, uint32_t code)
    {
        int res;
        struct binder_write_read bwr;
        struct {
            uint32_t cmd;
            struct binder_transaction_data txn;
        } __attribute__((packed)) writebuf;
        unsigned readbuf[32];
        
        // 驱动层消息为 BC_TRANSACTION
        writebuf.cmd = BC_TRANSACTION;
        writebuf.txn.target.handle = target;
        writebuf.txn.code = code;
        writebuf.txn.flags = 0;
        writebuf.txn.data_size = msg->data - msg->data0;
        writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
        writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
        writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
    
        bwr.write_size = sizeof(writebuf);
        bwr.write_consumed = 0;
        bwr.write_buffer = (uintptr_t) &writebuf;
    
        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
            
            //消息反馈 这里write有数据,驱动层进入 binder_thread_write, 见 --> 2.1
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    
            //消息解析
            res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
            if (res == 0) return 0;
            if (res < 0) goto fail;
        }
    
    fail:
        memset(reply, 0, sizeof(*reply));
        reply->flags |= BIO_F_IOERROR;
        return -1;
    }
    
    
    

    2.1 ioctl(bs->fd, BINDER_WRITE_READ, &bwr),进入binder驱动,由于这里write有数据,就进入
    binder_thread_write,binder_thread_write里面根据cmd=BC_TRANSACTION进入把bindr_transaction_data从用户控件拷贝到内核控件,在调用binder_transaction,主要作用是根据当前server的

    static void binder_transaction(struct binder_proc *proc,
                       struct binder_thread *thread,
                       struct binder_transaction_data *tr, int reply)
    {   
    
        struct binder_transaction *t;
        //目标进程
        struct binder_proc *target_proc;
        //目标线程
        struct binder_thread *target_thread = NULL;
        //目标binder节点
        struct binder_node *target_node = NULL;
        //目标todo链表
        struct list_head *target_list;
        //目标等待链表
        wait_queue_head_t *target_wait;
        //reply
        struct binder_transaction *in_reply_to = NULL;
        //...
        //这里为0,代表servermanager
        if (tr->target.handle) {
                //...
            } else {
                //指定targer_node 为servermanager的binder_node 
                target_node = binder_context_mgr_node;
                //...
            }
            //...
            //根据binder_node找到binder_proc
            target_proc = target_node->proc;
            //... 
            if (target_thread) {
                //...
            } else {
                //根据binder_proc获取todo链表,和wait链表
                target_list = &target_proc->todo;
                target_wait = &target_proc->wait;
            }
            //...
            //在内核分配binder_transation
            t = kzalloc(sizeof(*t), GFP_KERNEL);
            t->to_proc = target_proc;
            t->to_thread = target_thread;
            //SVC_MGR_ADD_SERVICE
            t->code = tr->code;
            //分配内存
            t->buffer = binder_alloc_buf(target_proc, tr->data_size,
            tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
            //...
            t->buffer->transaction = t;
            t->buffer->target_node = target_node;
            offp = (binder_size_t *)(t->buffer->data +
                     ALIGN(tr->data_size, sizeof(void *)));
            //把数据copy过来
            copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
                   tr->data.ptr.buffer, tr->data_size)
            //offp copy
            copy_from_user(offp, (const void __user *)(uintptr_t)
                   tr->data.ptr.offsets, tr->offsets_size)  
                   
            for (; offp < off_end; offp++) {
                   // binder实体还是handle
                   struct flat_binder_object *fp;
                   //...
                   fp = (struct flat_binder_object *)(t->buffer->data + *offp);
                   switch (fp->type) {
                       //这里是service段传递,是binder实体,对应这里
                        case BINDER_TYPE_BINDER:
                        case BINDER_TYPE_WEAK_BINDER: {
                            //... 
                            struct binder_ref *ref;
                            //根据当前binder_proc获取当前服务的binder_node
                            struct binder_node *node = binder_get_node(proc, fp->binder);
                            // 
                            if (node == NULL) {
                                //创建binder_node
                                node = binder_new_node(proc, fp->binder, fp->cookie);
                                 //...
                            }
                            //根据目标的binder_proc和当前binder_node获取binder_ref
                            ref = binder_get_ref_for_node(target_proc, node);    
                            //...
                            //赋值
                            fp->handle = ref->desc;
                            //更新计数,赋值type = BINDER_TYPE_HANDLE
                            binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
                              &thread->todo);
                             
                             break;
                        }
                        //这里是handle引用
                        case BINDER_TYPE_HANDLE:
                        case BINDER_TYPE_WEAK_HANDLE: {
                            //...
                            break;
                            }
                            
                        }
                        
                   }
                   //...
                   //work类型指定为 BINDER_WORK_TRANSACTION
                   t->work.type = BINDER_WORK_TRANSACTION;
                   //添加到todo链表
                   list_add_tail(&t->work.entry, target_list);
                   //...
                   //等待
                   if (target_wait)
                        wake_up_interruptible(target_wait);
                   
            }
    }
    
    

    主要作用是根据当前serverbinder实体创建flat_binder_object结构体,构造出binder_write_read与驱动交互,驱动层根据flat_binder_object构建出binder_node,根据 target_proc创建binder_ref,这个binder_refnode指向这个binder_node,然后构造binder_transaction,并对flat_binder_object结构进行重新赋值,加入目标进程的todo队列。

    servermanager进程收到唤醒的消息之后开始接收消息,进入binder_thread_read

    static int binder_thread_read(struct binder_proc *proc,
                      struct binder_thread *thread,
                      binder_uintptr_t binder_buffer, size_t size,
                      binder_size_t *consumed, int non_block)
    {
                          
        //...
        
        while (1) {
            uint32_t cmd;
            struct binder_transaction_data tr;
            struct binder_work *w;
            struct binder_transaction *t = NULL;
            //...
            //从todo队列获取数据
            if (!list_empty(&thread->todo)) {
                w = list_first_entry(&thread->todo, struct binder_work,
                             entry);
            } else if (!list_empty(&proc->todo) && wait_for_proc_work) {
                w = list_first_entry(&proc->todo, struct binder_work,
                             entry);
            }
            //...
            switch (w->type) {
                case BINDER_WORK_TRANSACTION: {
                    t = container_of(w, struct binder_transaction, work);
                    break;
                }
                //...
            }
            //...
            if (t->buffer->target_node) {
               struct binder_node *target_node = t->buffer->target_node;
               //根据target_node给binder_transaction_data赋值
               tr.target.ptr = target_node->ptr;
               //...
               //设置cmd
               cmd = BR_TRANSACTION;
            }
            //...
            //code赋值 add_service
            tr.code = t->code;
            
            tr.flags = t->flags;
            tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
           // 给binder_transaction_data赋值
            if (t->from) {
                struct task_struct *sender = t->from->proc->tsk;
    
                tr.sender_pid = task_tgid_nr_ns(sender,
                                task_active_pid_ns(current));
           } else {
                    tr.sender_pid = 0;
           }
    
            tr.data_size = t->buffer->data_size;
            tr.offsets_size = t->buffer->offsets_size;
            tr.data.ptr.buffer = (binder_uintptr_t)(
                        (uintptr_t)t->buffer->data +
                        proc->user_buffer_offset);
            tr.data.ptr.offsets = tr.data.ptr.buffer +
                        ALIGN(t->buffer->data_size,
                            sizeof(void *));
            //把cmd copy到用户空间
            if (put_user(cmd, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            //把binder_transaction_data copy到用户空间
            if (copy_to_user(ptr, &tr, sizeof(tr)))
                return -EFAULT;
            ptr += sizeof(tr);
        }
                          
    }
    
    
    
    

    这时候servermanager通过binder_loop传入的read_buffer有值了,执行到了对应的binder_parse解析函数里面

    
    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_TRANSACTION: {
                    struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
                //func 对应servicemanager的 svcmgr_handler函数       
                if (func) {
                    unsigned rdata[256/4];
                    struct binder_io msg;
                    struct binder_io reply;
                    int res;
                    //构造binder_io
                    bio_init(&reply, rdata, sizeof(rdata), 4);
                    bio_init_from_txn(&msg, txn);
                    res = func(bs, txn, &msg, &reply);
                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
                }
                    ptr += sizeof(*txn);
                 break;
                }
            
            }
        }
        //...
    }
    
    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        //..
       switch(txn->code) {
            //将handle和name加入到 svclist
           case SVC_MGR_ADD_SERVICE:
                s = bio_get_string16(msg, &len);
                if (s == NULL) {
                    return -1;
                }
                handle = bio_get_ref(msg);
                allow_isolated = bio_get_uint32(msg) ? 1 : 0;
                //添加到svclist
                if (do_add_service(bs, s, len, handle, txn->sender_euid,
                    allow_isolated, txn->sender_pid))
                    return -1;
                break;
        }
        //..
    }
    
    
    1. binder_loop(bs, server_handler_func);servermanager一样,开启循环,有数据了出发server_handler_func函数,server_handler_func就是自己的业务处理逻辑。

    总结:

    1. server进程生成对应服务的flat_binder_object,构造binder_write_read结构体和驱动层进行交互。
    2. 驱动根据flat_binder_object生成binder_node结构体,在为目标进程servermanager的binder_proc创建binder_ref,这个binder_refnode指向这个服务的binder_node,在构造binder_transaction_data结构体并更改flat_binder_object的部分数据(比如type更改为BINDER_TYPE_HANDLE),在把binder_transaction_data加入servermanagertodo队列并唤醒。
    3. servermanager进程唤醒后收到binder_transaction_data并进行解析,把相关数据copy到用户空间,用户空间收到后进行binder_parse,然后调用自己的处理函数svcmgr_handler
    4. svcmgr_handler根据code = SVC_MGR_ADD_SERVICEname,handle添加到svcinfo
    5. reply后续在说。
    6. 开启自己的服务looper接受。

    相关文章

      网友评论

          本文标题:binder(四) 服务注册过程

          本文链接:https://www.haomeiwen.com/subject/awhbsltx.html