Binder 驱动流程:

Binder设备是基于linux的设备驱动模型,binder是一个misc设备。下面来看看具体misc设备的流程:

binder驱动相关的文件路径:

kernel/drivers/staging/android/binder.c

kernel/drivers/staging/android/binder.h

device_initcall(binder_init);//在系统启动的时候加载,下面看看加载的时候做了哪些操作。

static int __init binder_init(void)

{

.......

binder_deferred_workqueue = create_singlethread_workqueue("binder");

binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);

ret = misc_register(&binder_miscdev);

   binder_deferred_task=kthread_run(binder_deferred_thread,NULL,"binder_deferred_thread");

.......

}

1)创建一个单线程工作队列,binder来处理一些可以稍后执行的工作

2)创建一个bind/proc binder目录,以及其属性操作。

3)注册一个misc设备,主设备号为10,次设备号动态生成

其次就是binder_fops操作函数,主要就是对他的填充。一个个分析下这些函数是怎么实现的。

static const struct file_operations binder_fops = {

.owner = THIS_MODULE,

.poll = binder_poll,

.unlocked_ioctl = binder_ioctl,

.mmap = binder_mmap,

.open = binder_open,

.flush = binder_flush,

.release = binder_release,

};

首先,分析binder_open函数

proc = kzalloc(sizeof(*proc), GFP_KERNEL);//分配binder proc记录空间

get_task_struct(current);//增加当前引用计数

proc->tsk = current;// 记录当前进程的地址

INIT_LIST_HEAD(&proc->todo);//初始化链表头进程全局todo任务链表

init_waitqueue_head(&proc->wait);//初始化等待队列头

proc->default_priority = task_nice(current);//获取当前进程优先级

//添加binder_proc 哈希表 将创建的binder proc 赋值给全局的binder_proc 

hlist_add_head(&proc->proc_node, &binder_procs);

proc->pid = current->group_leader->pid;//保存pid和私有数据

INIT_LIST_HEAD(&proc->delivered_death);

filp->private_data = proc;

mutex_unlock(&binder_lock);

分析binder_release函数

    获得当前进程/线程的pid

    调用remove_proc_entry()删除pid命名的只读文件。

调用binder_defer_work()释放binder_proc对象;此处使用workqueue来提高系统性能。

分析binder_mmap函数

//binder 设备最大能映射4M 内存

if ((vma->vm_end - vma->vm_start) > SZ_4M)

vma->vm_end = vma->vm_start + SZ_4M;

// binder 不能映射具有写权限的内存块

if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {

ret = -EPERM;

failure_string = "bad vm_flags";

goto err_bad_arg;

}

vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;

//判断是否已经mmap过了

//申请虚拟内存

area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);

//赋值地址和偏移量

proc->buffer = area->addr;

proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;

   //分配page空间

proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);

if (proc->pages == NULL) {

ret = -ENOMEM;

failure_string = "alloc page array";

goto err_alloc_pages_failed;

}

proc->buffer_size = vma->vm_end - vma->vm_start;

  //binder 内存操作函数

vma->vm_ops = &binder_vm_ops;

vma->vm_private_data = proc;

//分配物理内存

buffer = proc->buffer;

INIT_LIST_HEAD(&proc->buffers);

list_add(&buffer->entry, &proc->buffers);

buffer->free = 1;

binder_insert_free_buffer(proc, buffer);

proc->free_async_space = proc->buffer_size / 2;

     proc->files = get_files_struct(current);

proc->vma = vma;

分析binder_poll函数

binder_get_thread(proc)获得当前进程信息。

如果是进程,调用proc_work();如果是线程,调用thread_work()

调用binder_has_x_work检测,来判断所要采用的等待方式

队列是否为空;

线程/进程的循环状态;

返回信息;

调用poll_wait实现poll操作。

thread = binder_get_thread(proc);//获取binder proc 中的线程信息

wait_for_proc_work = thread->transaction_stack == NULL &&

list_empty(&thread->todo) && thread->return_error == BR_OK;//proc 状态

    //判断到底是proc work 还是 thread work

if (wait_for_proc_work) {

if (binder_has_proc_work(proc, thread))

return POLLIN;

poll_wait(filp, &proc->wait, wait);

if (binder_has_proc_work(proc, thread))

return POLLIN;

} else {

if (binder_has_thread_work(thread))

return POLLIN;

poll_wait(filp, &thread->wait, wait);

if (binder_has_thread_work(thread))

return POLLIN;

}

return 0;

}

分析最主要的函数指针binder_ioctl

Ioctllinux内核中最常用的,也是号称万能函数的一个,很多的linux子系统都用ioctl实现的功能

unsigned int size = _IOC_SIZE(cmd);//提取cmd命令

thread = binder_get_thread(proc);//获取此线程信息

总体关系图

Cmd:

BINDER_WRITE_READ

//读写函数里面有很多操作,后续再说

binder_thread_write

binder_thread_read 两个函数进行主要操作

BINDER_SET_MAX_THREADS

//设置最大线程

BINDER_SET_CONTEXT_MGR

//设置为守护进程service manage

BINDER_THREAD_EXIT

//设置线程退出

BINDER_VERSION

//设置binder版本

BinderDriverCommandProtocol:写操作命令协议

BinderDriverR eturnProtocol:读操作命令协议

    

更多相关文章

  1. android sqlite用法
  2. [置顶] Android(安卓)NDK中结合汇编分析Crash行为
  3. Android(安卓)Binder机制(3) 本地服务注册过程
  4. Android(安卓)Studio操作/问题积累
  5. Only the original thread that created a view hierarchy can t
  6. Android虚拟机,控制台Console报错几例及解决办法
  7. Android游戏框架AndEngine使用入门
  8. Android将InputStream转换为String和byte[]
  9. Android下AlarmManager完整调用流程

随机推荐

  1. MySQL中的redo log和undo log日志详解
  2. 为什么MySQL选择Repeatable Read作为默认
  3. 使用ORM新增数据在Mysql中的操作步骤
  4. mysql脏页是什么
  5. 为什么MySQL分页用limit会越来越慢
  6. MySQL深度分页(千万级数据量如何快速分页
  7. ORM模型框架操作mysql数据库的方法
  8. mysql 直接拷贝data 目录下文件还原数据
  9. MySQL 四种连接和多表查询详解
  10. MySQL索引是啥?不懂就问