Binder系列1-Binder Driver
Posted xhBruce
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Binder系列1-Binder Driver相关的知识,希望对你有一定的参考价值。
Binder系列1-Binder Driver
1. android采用Binder
Linux Kernel是开源系统,所开放源代码许可协议GPL保护,
Binder Driver
运行在Linux Kernel是GPL协议。用户空间采用Apache-2.0协议,内核空间与用户空间(即在GPL协议与Apache-2.0协议)之间的Lib库中采用BSD证授权方法,GPL协议限定在Linux Kernel,有效隔断了GPL的传染性,仍有较大争议。开源与商业化共存的一个成功典范。Binder 是基于开源的OpenBinder实现的,而OpenBinder的作者在Google工作,直接采用 Binder 作为核心的IPC机制。
2. Binder Driver实现
Binder驱动是一个misc device,是虚拟字符设备,主设备号是10,其设备节点是
/dev/binder
(该节点并不对应真实的硬件设备)。misc类型驱动只需要调用misc_deregister
。
主要是驱动设备的初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)。
linux/drivers/android/binder.c
linux/include/uapi/linux/android/binder.h
binder_init
:初始化虚拟字符设备,init_binder_device()\\init_binderfs()
;binder_open
:打开Binder驱动设备, binder_procs_lock同步锁;binder_mmap
:申请内存空间, binder_alloc_mmap_lock同步锁;binder_ioctl
:执行相应的ioctl操作, binder_procs_lock同步锁;当处于binder_thread_read过程,read_buffer无数据则释放同步锁。
2.1 binder_init 注册misc设备节点/dev/binder
binder_init() -> init_binder_device(device_name) -> misc_register(&binder_device->miscdev)
注册misc设备节点CONFIG_ANDROID_BINDERFS
、binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES
在kernel/configs/xxx/android-base.config
配置
binder_fops
Binder驱动支持的文件操作,其中使用做多的binder_ioctl \\ binder_mmap \\ binder_open
init_binderfs()
注册register_filesystem(&binder_fs_type)
(linux/drivers/android/binderfs.c)
const struct file_operations binder_fops =
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
;
static int __init init_binder_device(const char *name)
// ... ...
binder_device->miscdev.fops = &binder_fops;
binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
binder_device->miscdev.name = name;
// ... ...
ret = misc_register(&binder_device->miscdev);
// ... ...
static int __init binder_init(void)
// ... ...
if (!IS_ENABLED(CONFIG_ANDROID_BINDERFS) &&
strcmp(binder_devices_param, "") != 0)
/*
* Copy the module_parameter string, because we don't want to
* tokenize it in-place.
*/
device_names = kstrdup(binder_devices_param, GFP_KERNEL);
if (!device_names)
ret = -ENOMEM;
goto err_alloc_device_names_failed;
device_tmp = device_names;
while ((device_name = strsep(&device_tmp, ",")))
ret = init_binder_device(device_name);
if (ret)
goto err_init_binder_device_failed;
ret = init_binderfs();
if (ret)
goto err_init_binder_device_failed;
return ret;
err_init_binder_device_failed:
// ... ...
err_alloc_device_names_failed:
// ... ...
device_initcall(binder_init);
2.2 binder_open 打开Binder驱动设备
binder_proc
binder进程,每个进程都有独立的记录;proc->todo
todo链表binder_stats_created(BINDER_STAT_PROC)
BINDER_PROC对象创建数加1,binder_stats
是binder中统计数据载体filp->private_data = proc
把binder_proc对象保存到文件指针filphlist_add_head(&proc->proc_node, &binder_procs)
把binder_proc加入到全局链表binder_procs
static int binder_open(struct inode *nodp, struct file *filp)
struct binder_proc *proc, *itr;
struct binder_device *binder_dev;
struct binderfs_info *info;
struct dentry *binder_binderfs_dir_entry_proc = NULL;
// ... ...
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
// ... ...
INIT_LIST_HEAD(&proc->todo);
init_waitqueue_head(&proc->freeze_wait);
proc->default_priority = task_nice(current);
// ... ...
binder_stats_created(BINDER_STAT_PROC);
proc->pid = current->group_leader->pid;
INIT_LIST_HEAD(&proc->delivered_death);
INIT_LIST_HEAD(&proc->waiting_threads);
filp->private_data = proc;
mutex_lock(&binder_procs_lock);
hlist_for_each_entry(itr, &binder_procs, proc_node)
if (itr->pid == proc->pid)
existing_pid = true;
break;
hlist_add_head(&proc->proc_node, &binder_procs);
mutex_unlock(&binder_procs_lock);
// ... ...
2.3 binder_mmap 申请内存空间
binder_alloc_mmap_handler
申请内存空间,linux/drivers/android/binder_alloc.c
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
struct binder_proc *proc = filp->private_data;
if (proc->tsk != current->group_leader)
return -EINVAL;
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\\n",
__func__, proc->pid, vma->vm_start, vma->vm_end,
(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
(unsigned long)pgprot_val(vma->vm_page_prot));
if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS)
pr_err("%s: %d %lx-%lx %s failed %d\\n", __func__,
proc->pid, vma->vm_start, vma->vm_end, "bad vm_flags", -EPERM);
return -EPERM;
vma->vm_flags |= VM_DONTCOPY | VM_MIXEDMAP;
vma->vm_flags &= ~VM_MAYWRITE;
vma->vm_ops = &binder_vm_ops;
vma->vm_private_data = proc;
return binder_alloc_mmap_handler(&proc->alloc, vma);
2.4 binder_ioctl 执行相应的ioctl操作
binder_ioctl
函数负责在两个进程间收发IPC数据和IPC reply数据处理- 核心方法
binder_ioctl_write_read() -> binder_thread_write()\\binder_thread_read()
- binder_thread_write() :
get_user(cmd, (uint32_t __user *)ptr)
获取IPC数据BC请求码 - binder_thread_read():根据
w->type
(即binder_work->type
)响应相应处理。
- binder_thread_write() :
ioctl命令cmd | 说明 |
---|---|
BINDER_WRITE_READ | 收发Binder IPC数据 |
BINDER_SET_MAX_THREADS | 设置Binder线程最大个数 |
BINDER_SET_CONTEXT_MGR | 设置Service Manager节点 |
BINDER_SET_CONTEXT_MGR_EXT | |
BINDER_THREAD_EXIT | 释放Binder线程 |
BINDER_VERSION | 获取Binder版本信息 |
… | … |
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);
// ... ...
trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
// ... ...
thread = binder_get_thread(proc);
// ... ...
switch (cmd)
case BINDER_WRITE_READ:
ret = binder_ioctl_write_read(filp, cmd, arg, thread);
if (ret)
goto err;
break;
case BINDER_SET_MAX_THREADS://......
case BINDER_SET_CONTEXT_MGR_EXT://......
case BINDER_SET_CONTEXT_MGR://......
case BINDER_THREAD_EXIT://......
case BINDER_VERSION://......
case BINDER_GET_NODE_INFO_FOR_REF://......
case BINDER_GET_NODE_DEBUG_INFO://......
case BINDER_FREEZE://......
case BINDER_GET_FROZEN_INFO://......
case BINDER_ENABLE_ONEWAY_SPAM_DETECTION://......
case BINDER_GET_EXTENDED_ERROR://......
default:
ret = -EINVAL;
goto err;
// ... ...
if (thread)
thread->looper_need_return = false;
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
// ... ...
3. Binder通信模型
Binder是基于C/S架构的,简单解释下C/S架构,是指客户端(Client)和服务端(Server)组成的架构,Client端有什么需求,直接发送给Server端去完成。Android系统中对外只暴露Client端,Client端将任务发送给Server端。
以上是关于Binder系列1-Binder Driver的主要内容,如果未能解决你的问题,请参考以下文章
Binder系列2—Binder Driver再探 - Gityuan博客
Android 跨进程通信-Binder机制传输数据限制—罪魁祸首Binder线程池