ServiceManager与binder驱动的交互

ServiceManager负责binder的查询和注册,由init进程通过解析init.rc文件而创建的

  • do_add_service()函数:注册服务
  • do_find_service()函数:查找服务
  • binder_link_to_death()函数:结束服务
  • binder_send_reply()函数:将注册结果返回给Binder驱动

ServiceManger 的初始化

// frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char** argv)
{
   
    struct binder_state *bs;
    union selinux_callback cb;
    char *driver;

    if (argc > 1) {
   
        driver = argv[1];
    } else {
   
        driver = "/dev/binder";
    }
    // 打开binder驱动,申请分配内存
    bs = binder_open(driver, 128*1024);

    // 注册ServiceManager服务
    if (binder_become_context_manager(bs)) {
   
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);
    cb.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);

    binder_loop(bs, svcmgr_handler);

    return 0;
}

binder_open

这里的binder_open 不是内核binder驱动的binder_open,而是在用户进程下。

// frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(const char* driver, size_t mapsize)
{
   
    struct binder_state *bs;
    struct binder_version vers;

    bs = malloc(sizeof(*bs));

    // 打开内核驱动,会调用到驱动的binder_open,返回一个文件句柄
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);

    // 查询binder版本,会调用到驱动的binder_ioctl,类型是BINDER_VERSION
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
   
    // 比较当前binder版本与预期的是否一致
        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;
    // 向内核申请mapSize大小的内存,并映射到内核空间,会调用到驱动的binder_mmap
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    return bs;

流程:

  1. ServiceManager进程打开binder驱动,驱动调用了binder_open(),binder内核会创建一个对应的binder_proc,初始化之后加入全局的红黑树。
  2. ServiceManager进程查询binder版本,驱动调用了binder_ioctl(),type是BINDER_VERSION
  3. ServiceManager进程mmap申请内核内存,驱动调用了binder_mmap(),binder驱动只为进程分配了一个buffer,但还没将内核虚拟空间和进程虚拟空间、物理内存映射
struct binder_state {
    
    int fd; // binder文件描述符 
    void *mapped; //指向mmap的内存地址
    size_t mapsize; //分配的内存大小,默认为128KB
};

binder驱动的BINDER_VERSION命令

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;
    binder_selftest_alloc(&proc->alloc);
    ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
    thread = binder_get_thread(proc);
    
    switch (cmd) {
   ...
        case BINDER_VERSION: {
   
            struct binder_version __user *ver = ubuf;
            // 将BINDER_CURRENT_PROTOCOL_VERSION拷贝到用户空间
            if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,&ver->protocol_version)) {
   
                ret = -EINVAL; 
                goto err;
            }
            break;...
    }
    return ret;
}

ioctl(bs->fd, BINDER_VERSION, &vers) 的第三个

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值