Binder驱动的使用

Binder驱动创建:

static const struct file_operations binder_fops = {
	.owner = THIS_MODULE,
	.poll = binder_poll,
	.unlocked_ioctl = binder_ioctl,
	.compat_ioctl = binder_ioctl,
	.mmap = binder_mmap,
	.open = binder_open,
	.flush = binder_flush,
	.release = binder_release,
};

static struct miscdevice binder_miscdev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "binder",
	.fops = &binder_fops
};
复制代码

Binder驱动初始化:

  • static int __init binder_init(void)
  • 注册binder设备驱动ret = misc_register(&binder_miscdev);
  • 注册设备驱动的操作binder_open、binder_mmap、binder_ioctl、binder_release

Binder主要结构体:

struct binder_work {
    struct list_head entry;
    enum {
        BINDER_WORK_TRANSACTION = 1,
        BINDER_WORK_TRANSACTION_COMPLETE,
        BINDER_WORK_NODE
        BINDER_WORK_DEAD_BINDER,
        BINDER_WORK_DEAD_BINDER_AND_CLEAR,
        BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
    } type;
} 

struct binder_node {
    int debug_id;
    struct binder_work work;
    struct rb_node rb_node;
    struct hlist_node dead_node;

    struct binder_proc *proc;
    struct hlist_head refs;
    int internal_strong_refs;
    int local_weak_refs;
    int local_strong_refs;

    binder_unitptr_t ptr;
    binder_unitptr_t cookie;

    unsigned has_strong_ref:1;
    unsigned pending_strong_ref:1;
    unsigned has_weak_ref:1;
    unsigned pending_weak_ref:1;
    unsigned has_async_transaction:1;
    unsigned accept_fds:1;
    unsigned min_priority:8;

    struct list_head async_todo;
} 

struct binder_ref_death {
    struct binder_work work;
    binder_unitptr_t cookie;
}

struct binder_ref {
    int debug_id;
    struct rb_node rb_node_desc;
    struct rb_node rb_node_node;
    struct hlist_node node_entry;
    struct binder_proc *proc;
    struct binder_node *node;
    unit32_t desc;
    int strong;
    int weak;
    struct binder_ref_death *death;
}

struct binder_buffer {
    struct list_head entry;
    struct rb_node rb_node;

    unsigned free:1;
    unsigned allow_user_free:1;
    unsigned async_transaction:1;
    unsigned debug_id:29;

    struct binder_transaction *transaction;
    struct binder_node *target_node;
    
    size_t data_size;
    size_t offsets_size;
    unit8_t data[0];
}

struct binder_proc {
    struct hlist_node proc_node;
    struct rb_root threads;
    struct rb_root nodes;
    struct rb_root refs_by_desc;
    struct rb_root refs_by_node;

    int pid;
    struct vm_area_struct *vma;
    struct mm_struct *vma_vm_mm;
    struct task_struct *files;
    struct hlist_node deferred_work_node;
    int deferred_work;
    void *buffer;
    ptrdiff_t user_buffer_offset;

    struct list_head buffers;
    struct rb_root free_buffers;
    struct rb_root allocated_buffers;
    size_t free_async_space;

    struct page **pages;
    size_t buffer_size;
    unit32_t buffer_free;
    struct list_head todo;
    wait_queue_head_t wait;
    struct binder_stats stats;
    struct list_head delivered_death;
    int max_threads;
    int requested_threads;
    int requested_hreads_started;
    int ready_threads;
    long default_priority;
    struct dentry *debugfs_entry;
}

struct binder_proc {
    int debug_id;
    struct binder_work work;
    struct binder_thread *from;
    struct binder_transction *from_parent;
    struct binder_proc *to_proc;
    struct binder_thread *to_thread;
    struct binder_transation *to_parent;
    unsigned need_reply:1;
    
    struct binder_buffer *buffer;
    unsigned int code;
    unsighed int flags;
    long priority;
    long saved_priority;
    kuid_t sender_euid;
}
复制代码

先看看C++层怎么用:

androidxref.com/6.0.0_r1/xr…

1.源码路径:

C++: /android/frameworks/native/cmds/servicemanager/

Java: /android/frameworks/base/core/java/android/os/

2.servicemanager的启动:

Android在init进程启动以后,通过脚本init.rc,启动ServiceManager:

    service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart keystore
复制代码
3.主要入口:
int main(int argc, char **argv)
{
    struct binder_state *bs;
    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

    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();
        }
    }

    union selinux_callback cb;
    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;
}
复制代码
4.binder操作函数
binder_open
复制代码
  1. 打开设备驱动/dev/binder,文件描述符存储到bs->fd当中
  2. 映射128k内存到bs->mmaped
binder_loop
复制代码
  1. 发起 BINDER_WRITE_READ操作 命令BC_ENTER_LOOPER
  2. 发起 BINDER_WRITE_READ操作 一直等待有数据返回
  3. 开始解析返回的bind_transaction_data
binder_write
复制代码
  1. 发起操作 BINDER_WRITE_READ操作 (bs->fd, data, len)
binder_parse
复制代码
  1. 解析出命令:BR_TRANSACTION、BR_REPLY等
  2. 解析出数据:binder_transaction_data
5.业务函数:
find_svc()   
复制代码

查找svcinfo

svcinfo_death()  
复制代码

binder驱动通过handle找到bind_ref释放

do_find_service()  
复制代码

查找svcinfo并返回binder句柄

do_add_service()   
复制代码

调用binder_acquire向binder驱动中添加一个node、鉴定death通知

svcmgr_handler()  
复制代码

接收客户端发来的消息

  1. 获取服务 得到根据名字得到句柄handle,并写入flat_binder_object到reply中,最后回传reply
  2. 添加服务 将handle加入到svclist中,binder_acquire注册handle到驱动中,监听death通知
  3. 列出所有服务 将所有服务命令写入到reply中

总结一下:

  • server_manager在init进程解析init.rc时被启动,在入口函数main中首先打开/dev/binder驱动,将自己设为CONTEXT_MGR在内核中成为0号句柄的Binder、进入Binder消息循环读取消息(返回服务、添加服务、列出所有服务),所有的消息都记录在了svcinfo list结构体中,服务在添加时会发送命令注册到/dev/binder驱动中。
  • binder驱动的使用方法即:打开设备驱动/dev/binder,ioctl监控驱动消息,处理驱动消息(也可以回发消息)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值