Service Manager进程启动,睡眠等待在进程proc->wait

本文详细解析了Android Service Manager的启动过程,包括打开和映射Binder设备文件、注册为Binder上下文管理者以及循环等待客户端请求的步骤。通过分析`service_manager.c`和`binder.c`的源代码,揭示了Service Manager如何与Binder驱动进行交互并进入睡眠等待状态。
摘要由CSDN通过智能技术生成

本文参考《Android系统源代码情景分析》,作者罗升阳。

一、~/Android/frameworks/base/cmd/servicemanager

        -----binder.h

        -----binder.c

        -----service_manager.c

        ~/Android//kernel/goldfish/drivers/staging/android

        -----binder.c

        -----binder.h


二、源码分析

       1、从service_manager.c的main开始执行。

        ----~/Android/frameworks/base/cmd/servicemanager/service_manager.c

int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;

    bs = binder_open(128*1024);

    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1; 
    }   

    svcmgr_handle = svcmgr;//注意svcmgr_handle与下面的svcmgr_handler不一样,svcmgr_handle为全局变量,目前为空的函数指针,((void*)0)
    binder_loop(bs, svcmgr_handler);//svcmgr_handler是一个函数指针,指向具体的函数
    return 0;
}
        ---- ~/Android/frameworks/base/cmd/servicemanager/binder.c

struct binder_state
{       
    int fd;
    void *mapped;
    unsigned mapsize;
};
       ---- ~/Android/frameworks/base/cmd/servicemanager/binder.h

#define BINDER_SERVICE_MANAGER ((void*) 0)

     Service Manager是一个特殊的Service组件,它的特殊之处就在于与Service Manager进程的Binder本地对象是一个虚拟的对象。这个虚拟的Binder本地对象的地址值等于0,并且在Binder驱动程序中引用了它的Binder引用对象的句柄值也等于0。

     ServiceManager的启动过程由三个步骤组成:第一是调用函数binder_open打开设备文件/dev/binder,以及将它映射到本进程地址空间;第二是调用binder_become_context_manager将自己注册为Binder进程间通信机制的上下文管理者;第三步是调用函数binder_loop来循环等待和处理Client进程的通信要求。


      2、打开和映射Binder设备文件

      ----~/Android/frameworks/base/cmd/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);//文件描述符保存在fd中
    if (bs->fd < 0) {
        fprintf(stderr,"binder: cannot open device (%s)\n",
                strerror(errno));
        goto fail_open;
    }
        
    bs->mapsize = mapsize;//128*1024
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);//映射到本进程地址空间
    if (bs->mapped == MAP_FAILED) {
        fprintf(stderr,"binder: cannot map device (%s)\n",
                strerror(errno));
        goto fail_map;
    }

        /* TODO: check version */

    return bs;

fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return 0;
} 
      其中open("/dev/binder", O_RDWR)映射到binder驱动程序binder_open方法。

      binder_open方法位于~/Android/kernel/goldfish/drivers/staging/android/binder.c

static int binder_open(struct inode *nodp, struct file *filp)
{
        struct binder_proc *proc;      

        if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
                printk(KERN_INFO "binder_open: %d:%d\n", current->group_leader->pid, current->pid);

        proc = kzalloc(sizeof(*proc), GFP_KERNEL);//创建binder_proc结构体
        if (proc == NULL)     
                return -ENOMEM;                
        get_task_struct(current);      
        proc->tsk = current;  //初始化各个参数
        INIT_LIST_HEAD(&proc->todo);   
        init_waitqueue_head(&proc->wait);
        proc->default_priority = task_nice(current);
        mutex_lock(&binder_lock);      
        binder_stats.obj_created[BINDER_STAT_PROC]++;
        hlist_add_head(&proc->proc_node, &binder_procs);//将binder_proc结构体proc加入到一个全局hash队列binder_procs中
        proc->pid = current->group_leader->pid;//进程的pid
        INIT_LIST_HEAD(&proc->delivered_death);
        filp->private_data = proc;//将binder_proc结构体proc保存在参数filp的成员变量private_data中  
        mutex_unlock(&binder_lock);    

        if (binder_proc_dir_entry_proc) {//如果存在/proc/binder/proc目录
                char strbuf[11];
                snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
                r
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值