android servicemanager与binder源码分析二(暂时做废,后面会从新整理)

抱歉,此文暂时做废,不会使用segmentfault的删除功能。我会在后面从新整理后再继续写下去。node

继续上篇的文,这篇打算进入到android的内核世界,真正接触到binder。
binder是android内部的一个机制,经过设备驱动的协助可以起到进程间通信的(ipc)的做用。那么binder的设备驱动的源码在/drivers/staging/android/binder.c这个路径下。
先看下定义:linux

3632static const struct file_operations binder_fops = {
3633    .owner = THIS_MODULE,
3634    .poll = binder_poll,
3635    .unlocked_ioctl = binder_ioctl,
3636    .compat_ioctl = binder_ioctl,
3637    .mmap = binder_mmap,
3638    .open = binder_open,
3639    .flush = binder_flush,
3640    .release = binder_release,
3641};

这里说明了设备的各项操做对应的函数。
设备驱动是在系统刚开始的时候就初始化好的,初始化的过程看binder_init,不是重点,所以不在这里累述。这个初始化的过程若是进入的以及怎么发展的,有机会再其余文中叙述吧。
上文的servicemanager的main函数中首先就是open设备,所以先从open开始:android

2941static int binder_open(struct inode *nodp, struct file *filp)
2942{
2943    struct binder_proc *proc;
2944
2945    binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
2946             current->group_leader->pid, current->pid);
2947
2948    proc = kzalloc(sizeof(*proc), GFP_KERNEL);
2949    if (proc == NULL)
2950        return -ENOMEM;
2951    get_task_struct(current);
2952    proc->tsk = current;
2953    INIT_LIST_HEAD(&proc->todo);
2954    init_waitqueue_head(&proc->wait);
2955    proc->default_priority = task_nice(current);
2956
2957    binder_lock(__func__);
2958
2959    binder_stats_created(BINDER_STAT_PROC);
2960    hlist_add_head(&proc->proc_node, &binder_procs);
2961    proc->pid = current->group_leader->pid;
2962    INIT_LIST_HEAD(&proc->delivered_death);
2963    filp->private_data = proc;
2964
2965    binder_unlock(__func__);
2966
2967    if (binder_debugfs_dir_entry_proc) {
2968        char strbuf[11];
2969
2970        snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
2971        proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO,
2972            binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
2973    }
2974
2975    return 0;
2976}

1.建立binder_proc结构;
2.各类维护性的链表及结构的添加;
3.存储proc到私有数据内;segmentfault

先说下,内核开空间都是使用kzalloc与应用层的malloc相似。
这里用到一个current结构,是linux的一个指针,指向当前正在运行的进程结构task_struct,这里仍是先不深究,大致意思了解不影响后续便可。后面就是INIT_LIST_HEAD(&proc->todo);初始化链表头,这个链表是怎么回事儿呢?先看下proc的结构吧:网络

292struct binder_proc {
293    struct hlist_node proc_node;
294    struct rb_root threads;
295    struct rb_root nodes;
296    struct rb_root refs_by_desc;
297    struct rb_root refs_by_node;
298    int pid;
299    struct vm_area_struct *vma;
300    struct mm_struct *vma_vm_mm;
301    struct task_struct *tsk;
302    struct files_struct *files;
303    struct hlist_node deferred_work_node;
304    int deferred_work;
305    void *buffer;
306    ptrdiff_t user_buffer_offset;
307
308    struct list_head buffers;
309    struct rb_root free_buffers;
310    struct rb_root allocated_buffers;
311    size_t free_async_space;
312
313    struct page **pages;
314    size_t buffer_size;
315    uint32_t buffer_free;
316    struct list_head todo;
317    wait_queue_head_t wait;
318    struct binder_stats stats;
319    struct list_head delivered_death;
320    int max_threads;
321    int requested_threads;
322    int requested_threads_started;
323    int ready_threads;
324    long default_priority;
325    struct dentry *debugfs_entry;
326};

这个结构的写法很c很linux,能够看到可能会有不少个proc结构被贯穿成为一个链表统一管理,那么结合以前的内容猜想,binder_proc结构能够支持多个每一个对应一个进程,而后经过链表来维护,那么进一步思考,自己binder就是为了支持跨进程通信的,那么这些通信之间的binder衔接就是在这个链表结构中维护。
下面,init_waitqueue_head(&proc->wait);初始化linux的等待队列。又是个宏,内容以下:async

71#define init_waitqueue_head(q)                \
72    do {                        \
73        static struct lock_class_key __key;    \
74                            \
75        __init_waitqueue_head((q), #q, &__key);    \
76    } while (0)
77
78#ifdef CONFIG_LOCKDEP
79# define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
80    ({ init_waitqueue_head(&name); name; })
81# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) \
82    wait_queue_head_t name = __WAIT_QUEUE_HEAD_INIT_ONSTACK(name)
83#else
84# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name)
85#endif
86

带入的参数是proc结构中的一个成员wait,感受这里也是个队列(链表),用来维护等待处理的binder_proc结构。那么大胆猜想下,系统利用这个来创建等待通信处理的binder进程队列,可在这基础上进行各类策略调配来管理binder通信的过程,不能放着驱动自个人承载力来决定(可能带来稳定性隐患)。
再日后看,proc->default_priority = task_nice(current); 记录当前进程的优先级。看吧,以前的策略这里就会体现。
而后hlist_add_head(&proc->proc_node, &binder_procs);又一个,真linux真c,不得不说:看系统源码就必须习惯各类链表的这种方式,其实很好,不用额外维护什么东西,这种原始的方式其实有时候是最适合的,因此说,机制不是多复杂就牛逼的,而是看是否符合当前的体系当前的场景。这个应该是个全局hash表,统计全部binder_proc结构。函数

借用一张网络上的图说明下proc结构:
162056116463138.jpgui

最后保存这个proc倒private_data里,这个私有数据中。而后完了。
再回顾一下吧,每次打开设备就建立一个binder_proc结构,并将当前进程的信息保存在这里,而后将其挂接在系统的各个链表或红黑树或hash表中,为了便于往后的策略和维护。以后再将这个proc结构保留到私有数据中。其实是保存在打开的设备文件的结构中。目前还未涉及到其余操做,只是binder_open。spa

相关文章
相关标签/搜索