binder系统——驱动情景分析_IPC数据交互过程

进程 service_manager test_server test_client
引用 1 hello服务 2
2 goodbye服务 1

总结: handle是进程A对进程B提供的服务的引用

struct binder_ref {
/* Lookups needed: */
/* node + proc => ref (transaction) */
/* desc + proc => ref (transaction, inc/dec ref) */
/* node => refs + procs (proc exit) */
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;
uint32_t desc;
int strong;
int weak;
struct binder_ref_death *death;
};
struct binder_node
{
int debug_id;
struct binder_work work;
union {
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;
void __user *ptr;
void __user *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_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 *tsk;
struct files_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;
uint32_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_threads_started;
int ready_threads;
long default_priority;
struct dentry *debugfs_entry;
}

struct binder_thread {
struct binder_proc *proc;
struct rb_node rb_node;
int pid;
int looper;
struct binder_transaction *transaction_stack;
struct list_head todo;
uint32_t return_error; /* Write failed, return error code in read buf */
uint32_t return_error2; /* Write failed, return error code in read */
/* buffer. Used when sending a reply to a dead process that */
/* we are also waiting on */
wait_queue_head_t wait;
struct binder_stats stats;
}

binder结点:
a.在内核驱动态里,为每个服务创建binder_node
server传入一个flat_binder_object给驱动
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
b.在service_manager在驱动中创建binder_ref,引用binder_node
ref = binder_get_ref(proc, tr->target.handle);
target_node = ref->node;
c.client向service_manager查询服务,传name
handle = svcmgr_lookup(bs, svcmgr, argv[1]);
d.service_manager返回handle给驱动程序
e.驱动程序在service_manager的binder_ref红黑树中根据handle找到binder_ref,
再根据binder_ref,找到binder_node, 最后给client创建新的binder_ref,它的
desc从1开始,驱动返回desc给client,它即为handle
f. client=》handle,驱动根据handle找到binder_ref,
根据binder_ref找到binder_node,根据binder_node找到server进程
ref = binder_get_ref(proc, tr->target.handle);
target_node = ref->node;
target_proc = target_node->proc;



数据传输过程:
client-->server
先写后读
a.client构造数据
调用ioctl发数据
b.驱动里,根据handle找到server进程
c. 把数据放到进程的binder_proc.todo
target_list = &target_proc->todo;
list_add_tail(&t->work.entry, target_list);
d. 休眠
wake_up_interruptible(target_wait);
e. 被唤醒
f. 从todo链表中取数据数据,返回用户空间

server
先读后写
a.读,休眠
b.被唤醒
c. 从todo链表中取数据数据,返回用户空间
d. 处理
e.把结果写给client,也是放入client的binder_proc.todo
唤醒client

数据如何复制:
一般方法:需要复制两次
a.client构造数据
b.驱动:copy_from_user
server:驱动:
copyto_user,用户态处理

binder的方法:只需复制1次
可以直接访问驱动中的某块内存
a.server mmap 用户态可以直接访问驱动中某块内存
b.client 构造数据 ,驱动copy_from_user
c.server 可以在用户态直接使用数据

posted @ 2021-05-13 19:21  zhudaheng123  阅读(98)  评论(0)    收藏  举报