文章目录
-
-
- hlist_node: linux 内核哈希表
- binder_work: binder工作类型
- binder_node: binder实体
- binder_ref_death: binder 死亡结构体
- binder_ref: binder引用
- binder_proc: 在驱动中记录着进程的信息
- binder_context:记录ServiceManager信息
- binder_alloc:管理和分配、映射buffer
- binder_thread:在内核中表示线程
- binder_transaction: 事务项
- flat_binder_object: 将binder扁平化,可以在进程间传递
- binder_fd_object: 文件描述符
- binder_buffer_object:用于描述用户空间下的缓存
- binder_write_read:用户向驱动ioctl的交互数据
- binder_transaction_data:表示传输内容,是用户层和 binder 驱动传递数据的数据结构
- binder_buffer:缓存
- 四个驱动动作
-
翻看2019年的自己整理的文章,才发现学习的东西都好肤浅,很多东西都不思其解。以此为契机,回来重新学习binder。2020加油!
binder驱动中的重要的数据结构
hlist_node: linux 内核哈希表
// hash桶的头结点
struct hlist_head {
struct hlist_node *first;//指向每一个hash桶的第一个结点的指针
};
//hash桶的普通结点
struct hlist_node {
struct hlist_node *next;//指向下一个结点的指针
struct hlist_node **pprev;//指向上一个结点的next指针的地址
}
binder_work: binder工作类型
struct binder_work {
struct list_head entry; // binder_work双向列表,存储所有binder_work
enum {
// binder_work类型
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
BINDER_WORK_RETURN_ERROR,
BINDER_WORK_NODE,
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
} type;
};
binder_node: binder实体
struct binder_node {
int debug_id; // 调试使用的创建时分派的id
spinlock_t lock;
struct binder_work work; // 工作类型
union {
struct rb_node rb_node; // 正常使用的binder节点,会被链接到proc->nodes
struct hlist_node dead_node; // 已死的binder节点,但被其他proc引用,该实体会被通过dead_node存放在哈希表binder_dead_nodes
};
struct binder_proc *proc; // binder所在进程
struct hlist_head refs; // Binder实体的所有Binder引用的链表
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
int tmp_refs;
binder_uintptr_t ptr; // binder实体的对应用户空间的server端的内存地址
binder_uintptr_t cookie; // binder实体的对应用户空间的server端的其他数据的内存地址
struct {
u8 has_strong_ref:1;
u8 pending_strong_ref:1;
u8 has_weak_ref:1;
u8 pending_weak_ref:1;
};
struct {
u8 accept_fds:1;
u8 txn_security_ctx:1;
u8 min_priority;
};
bool has_async_transaction; // 是否有异步的事务
struct list_head async_todo; // 异步的todo队列
};
binder_ref_death: binder 死亡结构体
binder server死亡时候,通知client端
struct binder_ref_death {
struct binder_work work; // binder死亡类型
binder_uintptr_t cookie; // 监听死亡通知的对象地址
};
binder_ref: binder引用
struct binder_ref_data {
int debug_id; // 调试id
uint32_t desc; // Binder引用的句柄值
int strong; // 强引用计数
int weak; // 弱引用计数
};
struct binder_ref {
struct binder_ref_data data; // binder_ref具体数据
struct rb_node rb_node_desc; // binder_proc->refs_by_desc 红黑树,记录着binder_ref的desc句柄,方便寻找binder_ref
struct rb_node rb_node_node; // binder_proc->refs_by_node 红黑树,记录着binder_ref
struct hlist_node node_entry; // 关联到binder_node->ref
struct binder_proc *proc; // binder 节点引用所在的进程
struct binder_node *node; // binder 实体
struct binder_ref_death *death; // 注册死亡通知
}
/* Lookups needed: */
/* node + proc => ref (transaction) */
/* desc + proc => ref (transaction, inc/dec ref) */
/* node => refs + procs (proc exit) */
binder_proc: 在驱动中记录着进程的信息
struct binder_proc {
struct hlist_node proc_node; // 在全局binder_proc哈希表中的位置
struct rb_root threads; // 红黑树,存储该进程下所有请求的线程
struct rb_root nodes; // 红黑树,存储所有binder节点
struct rb_root refs_by_desc; // 红黑树,存储binder引用的句柄
struct rb_root refs_by_node; // 红黑树,存储binder应用
struct list_head waiting_threads; // 等待的线程队列
int pid; // 进程id
struct task_struct *tsk; // 描述进程的数据结构
struct hlist_node deferred_work_node;
int deferred_work;
bool is_dead; // 进程是否已死
struct list_head todo;// 该进程的待处理事务队列
struct binder_stats stats;
struct list_head delivered_death;
int max_threads;
int requested_threads; // 未运行的binder thread数量
int requested_threads_started; // 已经运行的binder thread数量
int tmp_ref;
long default_priority; // 默认优先级
struct dentry *debugfs_entry;
struct binder_alloc alloc; // mmap映射到用户空间的内存结构
struct binder_context *context; // binder_context,全局静态
spinlock_t inner_lock;
spinlock_t outer_lock;
struct dentry *binderfs_entry;
};
binder_context:记录ServiceManager信息
struct binder_context {
struct binder_node *binder_context_mgr_node; // ServiceManager 的binder_node
struct mutex context_mgr_node_lock;
kuid_t binder_context_mgr_uid; // ServiceManager进程的uid
const char *name;
};
binder_alloc:管理和分配、映射buffer
struct binder_alloc {
struct mutex mutex;
struct vm_area_struct *vma;
struct mm_struct *vma_vm_mm;
void __user *buffer; // mmap内存,指向用户空间的地 struct list_head buffers; // 所有
struct rb_root free_buffers; // 空闲buffer
struct rb_root allocated_buffers; // 已分配的buffer
size_t free_async_space; // 用于异步请求空间
struct binder_lru_page *pages; // 所有的page页
size_t buffer_size; // buffer大小
uint32_t buffer_free; // buffer 空闲
int pid; //进程id
size_t pages_high;
};
binder_thread:在内核中表示线程
struct binder_thread {
struct binder_proc *proc; // 所属的进程
struct rb_node rb_node; // proc->thread红黑树的节点
struct list_head waiting_thread_node; // proc->waiting_hreads 列表的节点
int pid;
int looper; // 线程状态,仅当前线程可以修改
bool looper_need_return; /* can be written by other thread */
struct binder_transaction *transaction_stack; // 正在处理的事务栈
struct list_head todo; // 待处理的事务栈
bool process_todo;
struct binder_error return_error; // 返回错误码
struct binder_error reply_error;// 返回的错误码
wait_queue_head_t wait; // 等待队列
struct binder_stats stats;
atomic_t tmp_ref;
bool is_dead; // 是否已死
};
binder_transaction: 事务项
struct binder_transaction {
int debug_id;
struct binder_work work; // 工作类型
struct binder_thread *from; // 发起处理的线程
struct binder_transaction *from_parent; // 上个事务
struct binder_proc *to_proc; // 接收的进程
struct binder_thread *to_thread; // 接收的线程
struct binder_transaction *to_parent; // 下个事务
unsigned need_reply:1; // 是否需要回复
/* unsigned is_dead:1; */ /* not used at the moment */
struct binder_buffer *buffer; // 数据缓存
unsigned int code; // 通信方法
unsigned int flags; // 标志: oneway
long priority; // 优先级
long saved_priority; // 保存的优先级
kuid_t sender_euid; // 发送的uid
struct list_head fd_fixups;
binder_uintptr_t security_ctx;
/**
* @lock: protects @from, @to_proc, and @to_thread
*
* @from, @to_proc, and @to_thread can be set to NULL
* during thread teardown
*/
spinlock_t lock;
};
// binder.h
struct binder_object_header {
__u32 type;
};
enum {
//强类型Binder实体对象
BINDER_TYPE_BINDER
//弱类型Binder实体对象
BINDER_TYPE_WEAK_BINDER
// 强类型引用对象
BINDER_TYPE_HANDLE
// 弱类型引用对象
BINDER_TYPE_WEAK_HANDLE
// 文件描述符
BINDER_TYPE_FD
BINDER_TYPE_FDA
BINDER_TYPE_PTR
};
flat_binder_object: 将binder扁平化,可以在进程间传递
struct flat_binder_object {
struct binder_object_header hdr; // 头部数据,表示数据类型
__u32 flags;
union {
binder_uintptr_t binder; // 本进程下的binder,记录binder_node地址
__u32 handle; // 非本进程下的binder,记录binder_ref的句柄
};
binder_uintptr_t cookie; // 用户进程空间下的额外数据
};
binder_fd_object: 文件描述符
struct binder_fd_object {
struct binder_object_header hdr; // 头部数据,表示数据类型
__u32 pad_flags; // 兼容旧的代码
union {
binder_uintptr_t pad_binder; // 兼容旧的代码
__u32 fd; // 文件描述符
};
binder_uintptr_t cookie; // 用户进程空间下的额外数据
};
binder_buffer_object:用于描述用户空间下的缓存
struct binder_buffer_object {
struct binder_object_header hdr; // 头部数据,表示数据类型
__u32 flags;
binder_uintptr_t buffer;
binder_size_t length;
binder_size_t parent;
binder_size_t parent_offset;
};
binder_write_read:用户向驱动ioctl的交互数据
struct binder_write_read {
binder_size_t write_size; // 写操作的字节数
binder_size_t write_consumed; // binder驱动已写完的字节数
binder_uintptr_t write_buffer; // 写缓存
binder_size_t read_size; // 读操作的字节数
binder_size_t read_consumed; // binder驱动已读完的字节数
binder_uintptr_t read_buffer; // 读缓存
};
这个是很重要的数据结构,用户进程通过binder_ioctl(binder_write_read)交互数据
binder_transaction_data:表示传输内容,是用户层和 binder 驱动传递数据的数据结构
struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
*/
union {
__u32 handle; // binder_ref 句柄
binder_uintptr_t ptr; // binder_node 地址
} target; // 对于BpBinder则使用handle,对于BBinder则使用ptr
binder_uintptr_t cookie; // 在处于binder进程下才有意义,指向BBinder对象
__u32 code; // 事务编码,请求以BC_开头;回复则以BR_开头
__u32 flags; // 标志位:one_way
pid_t sender_pid; // 发送端pid
uid_t sender_euid; // 发送端uid
binder_size_t data_size; //data数据的总大小
binder_size_t offsets_size; // 缓存位移
/* If this transaction is inline, the data immediately
* follows here; otherwise, it ends with a pointer to
* the data buffer.
*/
// 如果该transaction传递普通数据,data会指向具体的数据,如果是Binder实体或者Binder引用,传递的是flat_binder_object,
union {
struct {
/* transaction data */
binder_uintptr_t buffer;
/* offsets from buffer to flat_binder_object structs */
binder_uintptr_t offsets;
} ptr;
__u8 buf[8];
} data;
};
binder_buffer:缓存
表示binder利用mmap创建的内存,在用户空间和内核空间通用的,因此会跟对应的进程
binder_proc相关联
空闲的挂在binder_proc->free_buffers,已分配的挂在binder_proc->allocated_buffers
struct binder_buffer {
struct list_head entry; // /* free and allocated entries by address */
struct rb_node rb_node; /* free entry by size or allocated entry */
unsigned free:1; // 是否是空闲的buffer
unsigned allow_user_free:1; /// 是否允许用户释放
unsigned async_transaction:1; // 异步事务
unsigned debug_id:29; // 调试id
struct binder_transaction *transaction; // 指向binder_transaction事务
struct binder_node *target_node; // 指向binder_node
size_t data_size; // 数据大小
size_t offsets_size; // 数据偏移量
size_t extra_buffers_size; // 剩余的大小
void __user *user_data; // 缓存数据地址
};
四个驱动动作
- binder_init:初始化字符设备
- binder_open:打开驱动设备
- binder_mmap:申请内存空间
- binder_ioctl:执行相应的ioctl操作
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/6244.html