Binder驅動建立:
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};
static struct miscdevice binder_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "binder",
.fops = &binder_fops
};
複製程式碼
Binder驅動初始化:
- static int __init binder_init(void)
- 註冊binder裝置驅動ret = misc_register(&binder_miscdev);
- 註冊裝置驅動的操作binder_open、binder_mmap、binder_ioctl、binder_release
Binder主要結構體:
struct binder_work {
struct list_head entry;
enum {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
BINDER_WORK_NODE
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
} type;
}
struct binder_node {
int debug_id;
struct binder_work work;
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;
binder_unitptr_t ptr;
binder_unitptr_t 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_ref_death {
struct binder_work work;
binder_unitptr_t cookie;
}
struct binder_ref {
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;
unit32_t desc;
int strong;
int weak;
struct binder_ref_death *death;
}
struct binder_buffer {
struct list_head entry;
struct rb_node rb_node;
unsigned free:1;
unsigned allow_user_free:1;
unsigned async_transaction:1;
unsigned debug_id:29;
struct binder_transaction *transaction;
struct binder_node *target_node;
size_t data_size;
size_t offsets_size;
unit8_t data[0];
}
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 *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;
unit32_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_hreads_started;
int ready_threads;
long default_priority;
struct dentry *debugfs_entry;
}
struct binder_proc {
int debug_id;
struct binder_work work;
struct binder_thread *from;
struct binder_transction *from_parent;
struct binder_proc *to_proc;
struct binder_thread *to_thread;
struct binder_transation *to_parent;
unsigned need_reply:1;
struct binder_buffer *buffer;
unsigned int code;
unsighed int flags;
long priority;
long saved_priority;
kuid_t sender_euid;
}
複製程式碼
先看看C++層怎麼用:
1.原始碼路徑:
C++: /android/frameworks/native/cmds/servicemanager/
Java: /android/frameworks/base/core/java/android/os/
2.servicemanager的啟動:
Android在init程式啟動以後,通過指令碼init.rc,啟動ServiceManager:
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart keystore
複製程式碼
3.主要入口:
int main(int argc, char **argv)
{
struct binder_state *bs;
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
abort();
}
if (getcon(&service_manager_context) != 0) {
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
abort();
}
}
union selinux_callback cb;
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
binder_loop(bs, svcmgr_handler);
return 0;
}
複製程式碼
4.binder操作函式
binder_open
複製程式碼
- 開啟裝置驅動/dev/binder,檔案描述符儲存到bs->fd當中
- 對映128k記憶體到bs->mmaped
binder_loop
複製程式碼
- 發起 BINDER_WRITE_READ操作 命令BC_ENTER_LOOPER
- 發起 BINDER_WRITE_READ操作 一直等待有資料返回
- 開始解析返回的bind_transaction_data
binder_write
複製程式碼
- 發起操作 BINDER_WRITE_READ操作 (bs->fd, data, len)
binder_parse
複製程式碼
- 解析出命令:BR_TRANSACTION、BR_REPLY等
- 解析出資料:binder_transaction_data
5.業務函式:
find_svc()
複製程式碼
查詢svcinfo
svcinfo_death()
複製程式碼
binder驅動通過handle找到bind_ref釋放
do_find_service()
複製程式碼
查詢svcinfo並返回binder控制程式碼
do_add_service()
複製程式碼
呼叫binder_acquire向binder驅動中新增一個node、鑑定death通知
svcmgr_handler()
複製程式碼
接收客戶端發來的訊息
- 獲取服務 得到根據名字得到控制程式碼handle,並寫入flat_binder_object到reply中,最後回傳reply
- 新增服務 將handle加入到svclist中,binder_acquire註冊handle到驅動中,監聽death通知
- 列出所有服務 將所有服務命令寫入到reply中
總結一下:
- server_manager在init程式解析init.rc時被啟動,在入口函式main中首先開啟/dev/binder驅動,將自己設為CONTEXT_MGR在核心中成為0號控制程式碼的Binder、進入Binder訊息迴圈讀取訊息(返回服務、新增服務、列出所有服務),所有的訊息都記錄在了svcinfo list結構體中,服務在新增時會傳送命令註冊到/dev/binder驅動中。
- binder驅動的使用方法即:開啟裝置驅動/dev/binder,ioctl監控驅動訊息,處理驅動訊息(也可以回發訊息)。