美文网首页
Android Framework—启动ServiceManag

Android Framework—启动ServiceManag

作者: Peakmain | 来源:发表于2021-03-22 13:09 被阅读0次

上篇文章我们知道系统服务会注册到ServiceManager,而客户端会通过ServiceManager去获取服务进行通信,那么ServiceManager是如何启动的呢

启动ServiceManager

ServiceManager是init进程解析init.rc文件而创建的

service servicemanager /system/bin/servicemanager
    class core
      //用户是system身份
    user system
    group system
   
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm

critical:说明servicemanager进程执行的是关键服务,关键服务不会退出,如果退出就会重启服务

实际是servicemanager.main方法

int main(int argc, char **argv)
{
    struct binder_state *bs;
     //打开binder驱动
    bs = binder_open(128*1024);
    //成为上下文管理者
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    selinux_enabled = is_selinux_enabled();
    sehandle = selinux_android_service_context_handle();
    selinux_status_open(true);

    if (selinux_enabled > 0) {
        if (sehandle == NULL) {
            ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
            abort();
        }

        if (getcon(&service_manager_context) != 0) {
            ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
            abort();
        }
    }
     //进入循环,等待客户端发送请求
    binder_loop(bs, svcmgr_handler);
    return 0;
}

main函数主要做了三件事情
1、打开binder驱动设备,并申请128kb字节大小的内存空间
2、binder_become_context_manager:将servicemanager注册成为Binder机制的上下文管理者。
3、binder_loop:循环等待和处理client发来的请求

打开binder驱动

binder.c源码

struct binder_state
{
     //binder文件描述符
    int fd;
      //mmap的内存地址
    void *mapped;
     //分配的内存大小
    size_t mapsize;
};
struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;

    bs = malloc(sizeof(*bs));
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }
      //打开binder驱动
    bs->fd = open("/dev/binder", O_RDWR);
    //获取驱动版本,并判断版本是否一致
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        fprintf(stderr,
                "binder: kernel driver version (%d) differs from user space version (%d)\n",
                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
        goto fail_open;
    }

    bs->mapsize = mapsize;
   //映射一块内存为128mb
    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;
    }

    return bs;
 //失败释放资源
fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return NULL;
}

binder_become_context_manager

告诉binder驱动,serviceManager已经就绪了

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

icotl实际调用的binder_ioctl,也就是kernel/xref/drivers/staging/android/binder.c

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
    int ret;
    struct binder_proc *proc = filp->private_data;
    struct binder_thread *thread;
    unsigned int size = _IOC_SIZE(cmd);
    void __user *ubuf = (void __user *)arg;
    proc->pid, current->pid, cmd, arg);*/

    trace_binder_ioctl(cmd, arg);

    ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
    if (ret)
        goto err_unlocked;

    binder_lock(__func__);
       //查找binder_Thread,如果查询不到会创建一个新的binder_thread并返回
    thread = binder_get_thread(proc);
    if (thread == NULL) {
        ret = -ENOMEM;
        goto err;
    }

    switch (cmd) {
    case BINDER_SET_CONTEXT_MGR:
              //创建上下文管理者
        ret = binder_ioctl_set_ctx_mgr(filp);
               //binder上下文者只能被创建一次
        if (ret)
            goto err;
        ret = security_binder_set_context_mgr(proc->tsk);
        if (ret < 0)
            goto err;
        break;
    }
    default:
        ret = -EINVAL;
        goto err;
    }
    ret = 0;
err:
    return ret;
}

binder_looper源码

void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];

    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;
     // BC_ENTER_LOOPER 写入驱动,告诉驱动当前进程进入循环
    //客户端都是BC开头,服务端都是BR
    readbuf[0] = BC_ENTER_LOOPER;
  //当前线程(ServiceManager的主线程)此时变成Binde线程
    binder_write(bs, readbuf, sizeof(uint32_t));

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
       //不断读取binder驱动的数据,判断是否有新的请求,有就走到binder_parse
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }
         //解析远程binder信息
        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}
int binder_write(struct binder_state *bs, void *data, size_t len)
{
    struct binder_write_read bwr;
    int res;

    bwr.write_size = len;
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) data;
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    if (res < 0) {
        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
                strerror(errno));
    }
    return res;
}
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
    int ret;
    switch (cmd) {
    case BINDER_WRITE_READ:
        ret = binder_ioctl_write_read(filp, cmd, arg, thread);
        if (ret)
            goto err;
        break;
    default:
        ret = -EINVAL;
        goto err;
    }
    ret = 0;
err:
    return ret;
}
static int binder_ioctl_write_read(struct file *filp,
                        unsigned int cmd, unsigned long arg,
                        struct binder_thread *thread)
        {
            int ret = 0;
            struct binder_proc *proc = filp->private_data;
            
            struct binder_write_read bwr;
                 .....
                //将用户空间拷贝到内核数据
            if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
                ret = -EFAULT;
                goto out;
            }
            binder_debug(BINDER_DEBUG_READ_WRITE,
                     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
                     proc->pid, thread->pid,
                     (u64)bwr.write_size, (u64)bwr.write_buffer,
                     (u64)bwr.read_size, (u64)bwr.read_buffer);
        
            if (bwr.write_size > 0) {
                          //如果缓存区有数据的时候
                ret = binder_thread_write(proc, thread,
                              bwr.write_buffer,
                              bwr.write_size,
                              &bwr.write_consumed);
                trace_binder_write_done(ret);
                if (ret < 0) {
                    bwr.read_consumed = 0;
                    if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                        ret = -EFAULT;
                    goto out;
                }
            }

    binder_debug(BINDER_DEBUG_READ_WRITE,
                     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
                     proc->pid, thread->pid,
                     (u64)bwr.write_consumed, (u64)bwr.write_size,
                     (u64)bwr.read_consumed, (u64)bwr.read_size);
                   //内核空间拷贝到  用户控件
            if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
                ret = -EFAULT;
                goto out;
            }
        out:
            return ret;
        }
image.png

解析binder_parse源码

int binder_parse(struct binder_state *bs, struct binder_io *bio,
                 uintptr_t ptr, size_t size, binder_handler func)
{

        switch(cmd) {
        //没有循环则直接退出
        case BR_NOOP:
            break;
        case BR_TRANSACTION_COMPLETE:
            break;
        case BR_INCREFS:
        case BR_ACQUIRE:
        case BR_RELEASE:
        case BR_DECREFS:
#if TRACE
            fprintf(stderr,"  %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
#endif
            ptr += sizeof(struct binder_ptr_cookie);
            break;
        case BR_TRANSACTION: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            binder_dump_txn(txn);
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
                struct binder_io reply;
                int res;

                bio_init(&reply, rdata, sizeof(rdata), 4);
                bio_init_from_txn(&msg, txn);
            //回调函数 svcmgr_handler 
                res = func(bs, txn, &msg, &reply);
          //向binder发送回复
                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
            }
            ptr += sizeof(*txn);
            break;
        }
    }
   case BR_REPLY: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            binder_dump_txn(txn);
            if (bio) {
                bio_init_from_txn(bio, txn);
                bio = 0;
            } else {
           
            }
            ptr += sizeof(*txn);
            r = 0;
            break;
        }
    return r;
}

binder_loop最终实际执行了svcmgr_handler方法

binder_loop(bs, svcmgr_handler);
int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    struct svcinfo *si;
    uint16_t *s;
    size_t len;
    uint32_t handle;
    uint32_t strict_policy;
    int allow_isolated;

    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
        return -1;

    if (txn->code == PING_TRANSACTION)
        return 0;
   //查找code
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        // 要查询的服务名称
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        // 从服务列表中寻找 handle 值
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
          // 把 handle 值写入回复数据
        bio_put_ref(reply, handle);
        return 0;
  // 添加服务到列表
    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;
         //添加到服务
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
        break;
    default:
        ALOGE("unknown code %d\n", txn->code);
        return -1;
    }

    bio_put_uint32(reply, 0);
    return 0;
}
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
       //根据名字通过svclist查找服务信息
    struct svcinfo *si = find_svc(s, len);

    if (!si || !si->handle) {
        return 0;
    }
....
   //返回服务的handle
    return si->handle;
}
struct svcinfo *find_svc(const uint16_t *s16, size_t len)
{
    struct svcinfo *si;

    for (si = svclist; si; si = si->next) {
           //判断名字是否一致
        if ((len == si->len) &&
            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
            return si;
        }
    }
    return NULL;
}
int do_add_service(struct binder_state *bs,
                   const uint16_t *s, size_t len,
                   uint32_t handle, uid_t uid, int allow_isolated,
                   pid_t spid)
{
    struct svcinfo *si;
 
    if (!handle || (len == 0) || (len > 127))
        return -1;
     //判断能否被注册
    if (!svc_can_register(s, len, spid)) {
        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
             str8(s, len), handle, uid);
        return -1;
    }
    //查找服务
    si = find_svc(s, len);
    if (si) {
        if (si->handle) {
            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
                 str8(s, len), handle, uid);
            //服务已经被注册了就释放之前添加的服务
            svcinfo_death(bs, si);
        }
        si->handle = handle;
    } else {
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
                 str8(s, len), handle, uid);
            return -1;
        }
         //指定handle
        si->handle = handle;
        si->len = len;
        // // 指定当前添加服务的名称
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        // svclist保存所有已注册的服务
        si->next = svclist;
        svclist = si;
    }
    binder_acquire(bs, handle);
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

binder_send_reply源码分析


void binder_send_reply(struct binder_state *bs,
                       struct binder_io *reply,
                       binder_uintptr_t buffer_to_free,
                       int status)
{
    struct {
        uint32_t cmd_free;
        binder_uintptr_t buffer;
        uint32_t cmd_reply;
        struct binder_transaction_data txn;
    } __attribute__((packed)) data;

    data.cmd_free = BC_FREE_BUFFER;
    data.buffer = buffer_to_free;
     //向binder发送BC_REPLY   
    data.cmd_reply = BC_REPLY;
    data.txn.target.ptr = 0;
    data.txn.cookie = 0;
    data.txn.code = 0;
    if (status) {
        data.txn.flags = TF_STATUS_CODE;
        data.txn.data_size = sizeof(int);
        data.txn.offsets_size = 0;
        data.txn.data.ptr.buffer = (uintptr_t)&status;
        data.txn.data.ptr.offsets = 0;
    } else {
        data.txn.flags = 0;
        data.txn.data_size = reply->data - reply->data0;
        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
    }
       //向binder写入数据
    binder_write(bs, &data, sizeof(data));
}
网上的图片.jpg

相关文章

网友评论

      本文标题:Android Framework—启动ServiceManag

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