Binder – 2、servicemanager的初始化

一、前言

两个进程之间想要通信,就必须要知道对方的地址才行,这样的话,就必须要有一个“中间人”来做注册才行,servicemanager正是做这个事的,那又涉及到一个问题,应用进程怎么知道servicemanager的地址?看起来是一个“先有鸡还是先有蛋”的问题。我们知道,一般这种情况,我们可以将中间人设置一个大家都知道的公用地址,这样就都可以进行访问了。

二、servicemanager进程

既然是中间人,那么servicemanager就应该有一个“中立的”进程。

2.1 进程启动

servicemanager是通过.rc初始化的,在系统初始化的时候,.rc文件会被解析:

frameworks/native/cmds/servicemanager/servicemanager.rc












service servicemanager /system/bin/servicemanager











    class core animation









    user system








    group system readproc








    critical






    onrestart restart apexd






    onrestart restart audioserver





    onrestart restart gatekeeperd





    onrestart class_restart main





    onrestart class_restart hal





    onrestart class_restart early_hal





    writepid /dev/cpuset/system-background/tasks




    shutdown critical




关于.rc的语法,我们不需要过多了解,等解析完之后,系统会将/system/bin/servicemanager文件启动为servicemanager进程,通过ps也可以看到该进程:












$ adb shell "ps -A | grep servicemanager"











system         216     1 10865356  4284 0                   0 S servicemanager









2.2 入口

servicemanager的入口是main.cpp,位置是frameworks\native\cmds\servicemanager\main.cppmain函数我们再熟悉不过了,看下代码:












int main(int argc, char** argv) {











    //获取binder驱动名









    const char* driver = argc == 2 ? argv[1] : "/dev/binder";








    //初始化Binder驱动








    sp<ProcessState> ps = ProcessState::initWithDriver(driver);






    //设置最大线程数量






    ps->setThreadPoolMaxThreadCount(0);





    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);





    //新建ServiceManager对象





    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());





    if (!manager->addService("manager", manager, false /*allowIsolated*/)





    //将ServiceManager设置到IPCThreadState




    IPCThreadState::self()->setTheContextObject(manager);




    // !!成为ContextManager



    ps->becomeContextManager();


    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);


    //开启事件循环


    BinderCallback::setupTo(looper);


    ClientCallbackCallback::setupTo(looper, manager);


    while(true) {


        looper->pollAll(-1);

    }

    return EXIT_FAILURE;

}

进程启动之后,做这几件事情:

  • 1、初始化Binder驱动

  • 2、新建ServiceManager对象,并执行addService方法

  • 3、将ServiceManager设置到IPCThreadState

  • 4、成为ContextManager

  • 5、开启事件循环

2.2.1 initWithDriver

initWithDriver与我们上一次分析的init方法实际上区别不大

2.2.2 ServiceManager初始化












ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access))











平平无奇,下一个

2.2.3 addService












  












Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {

    auto ctx = mAccess->getCallingContext();

    //异常逻辑,省略



    // Overwrite the old service if it exists



    mNameToService[name] = Service {



        .binder = binder,



        .allowIsolated = allowIsolated,



        .dumpPriority = dumpPriority,



        .debugPid = ctx.debugPid,



    };



}



异常逻辑省略,主要是存到mNameToService中,方面后面获取

2.2.4 becomeContextManager












bool ProcessState::becomeContextManager()











{











    AutoMutex _l(mLock);








  












    flat_binder_object obj {



        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,



    };



    //只看这个



    int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);



    // fallback to original method



    if (result != 0) {



        android_errorWriteLog(0x534e4554, "121035042");



        int unused = 0;


        result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);


    }


    return result == 0;


}


我们只关注第一个ioctl,这里调用到Binder驱动中,关键字为BINDER_SET_CONTEXT_MGR_EXT












case BINDER_SET_CONTEXT_MGR_EXT:











{











    struct flat_binder_object fbo;








  












    if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {



        ret = -EINVAL;



        goto err;



    }



    ret = binder_ioctl_set_ctx_mgr(filp, &fbo);



    if (ret)



        goto err;



    break;



}


看一下binder_ioctl_set_ctx_mgr












static int binder_ioctl_set_ctx_mgr(struct file *filp,











                    struct flat_binder_object *fbo)









{








    int ret = 0;








    struct binder_proc *proc = filp->private_data;






    struct binder_context *context = proc->context;






    struct binder_node *new_node;





    kuid_t curr_euid = current_euid();





    //创建Binder节点





    new_node = binder_new_node(proc, fbo);





    //修改引用计数





    new_node->local_weak_refs++;




    new_node->local_strong_refs++;




    new_node->has_strong_ref = 1;



    new_node->has_weak_ref = 1;


    //将new_node设置为binder_context_mgr_node


    context->binder_context_mgr_node = new_node;


    binder_put_node(new_node);


    return ret;


}


  • 1、创建Binder节点

  • 2、修改节点的引用计数

  • 3、设置该节点为binder_context_mgr_node,后续其他进程正是用这个来访问servicemanager

在这里我们又看到两个数据结构binder_nodebinder_context

图2.1 – binder_node的结构












struct binder_context {











    struct binder_node *binder_context_mgr_node;









    struct mutex context_mgr_node_lock;








    kuid_t binder_context_mgr_uid;








    const char *name;






};






binder_context结构相对比较简单。主要是保存binder_context_mgr_node的地址,也就是servicemanager

至此,我们将servicemanager设置给了驱动层,后面的操作就可以通过引用binder_context_mgr_node来完成了。

2.2.5 BinderCallback::setupTo

说完了becomeContextManager,我们回头看下最后一段逻辑,首先是创建一个LooperLooper我们知道是消息循环机制,然后看BinderCallback::setupTo:












static sp<BinderCallback> setupTo(const sp<Looper>& looper) {











    sp<BinderCallback> cb = sp<BinderCallback>::make();









    int binder_fd = -1;








    //获取Binder驱动的fd








    IPCThreadState::self()->setupPolling(&binder_fd);






    //添加对Binder驱动fd的监听






    int ret = looper->addFd(binder_fd,





                            Looper::POLL_CALLBACK,





                            Looper::EVENT_INPUT,





                            cb,





                            nullptr /*data*/);





    return cb;




}




  





int handleEvent(int /* fd */, int /* events */, void* /* data */) override {


    IPCThreadState::self()->handlePolledCommands();


    return 1;  // Continue receiving callbacks.


}

我们知道looper使用的是epoll机制,在收到事件的时候,就会触发这里的handleEvent,最终进入handlePolledCommands:












status_t IPCThreadState::handlePolledCommands()











{











    status_t result;








    do {








        //循环与Binder驱动通信






        result = getAndExecuteCommand();






    } while (mIn.dataPosition() < mIn.dataSize());





    processPendingDerefs();





    flushCommands();





    return result;





}





在没有事情做的时候,这个线程就会睡眠,等有事件过来,线程就被唤醒,然后开始从Binder驱动中读取数据,具体的交互逻辑我们在后面分析。

三、总结

servicemanager作为一个单独的进程存在,为其他的进程提供服务,servicemanager在启动之后,将创建出来的对象地址设置到Binder驱动层,然后进入循环,等待Binder驱动的唤醒,servicemanager初始化完毕。

图3.1 – ServiceManager初始化时序图

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYmeMCHo' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片