【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )
文章目錄
- 一、系統服務
- 二、系統服務主函數
- 三、開啟 Binder
- 四、注冊上下文
- 五、開啟 Binder 循環
- 六、binder_write 方法
- 七、binder_ioctl 內核方法
- 八、binder_ioctl_write_read 內核方法
一、系統服務
System Server 是由 Zygote 進程 fork() 出來的 ;
Init 進程 啟動 Zygote , Zygote 啟動 System Server 進程 ;
System Server 注冊服務時 , 會執行 service_manager.c 中的方法 ;
二、系統服務主函數
service_manager.c 從 int main(int argc, char** argv) 方法開始執行 , 在該 main 函數中 , 執行了 333 個重要操作 :
- ① 開啟 Binder : 獲取 Binder 驅動 , 并且申請了 128 KB 的內存映射地址 , bs = binder_open(driver, 128*1024); ;
- ② 注冊上下文 : 將自己注冊成 Binder 進程的上下文 , binder_become_context_manager(bs) ;
- ③ 開啟 Binder 循環 : 不停的輪詢 , 是否有消息發送 , binder_loop(bs, svcmgr_handler); ;
完整代碼參考 /frameworks/native/cmds/servicemanager/service_manager.c ;
三、開啟 Binder
通過調用 bs = binder_open(driver, 128*1024); 開啟 Binder 的方法 struct binder_state *binder_open(const char* driver, size_t mapsize) , 定義在 /frameworks/native/cmds/servicemanager/binder.c 中 ;
首先分析下 binder_state 結構體 , 其中有 333 個參數 ,
- int fd : Binder 驅動的文件描述
- void *mapped : 內存映射首地址
- size_t mapsize : 內存映射的大小 , 128 KB
方法最終返回一個 binder_state 結構體 ;
struct binder_state {int fd; // Binder 驅動的文件描述void *mapped; // 內存映射首地址size_t mapsize; // 內存映射的大小 , 128 KB };// 打開 Binder , 并獲取 Binder 的狀態描述 struct binder_state *binder_open(const char* driver, size_t mapsize) {struct binder_state *bs; // 返回的結構體struct binder_version vers;bs = malloc(sizeof(*bs)); // 為返回值申請內存if (!bs) {errno = ENOMEM;return NULL;}bs->fd = open(driver, O_RDWR | O_CLOEXEC);if (bs->fd < 0) {fprintf(stderr,"binder: cannot open %s (%s)\n",driver, strerror(errno));goto fail_open;}if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {fprintf(stderr,"binder: kernel driver version (%d) differs from user space version (%d)\n",vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);goto fail_open;}bs->mapsize = mapsize;bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);if (bs->mapped == MAP_FAILED) {fprintf(stderr,"binder: cannot map device (%s)\n",strerror(errno));goto fail_map;}return bs;fail_map:close(bs->fd); fail_open:free(bs);return NULL; }完整代碼參考 /frameworks/native/cmds/servicemanager/binder.c#97;
四、注冊上下文
通過調用 binder_become_context_manager(bs) , 將自己注冊成 Binder 進程的上下文 ; 其中調用的 ioctl 方法是內核中的方法 , 這是 IO Control 的簡稱 ; 這個代碼得去內核中查找 ;
int binder_become_context_manager(struct binder_state *bs) {return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }完整代碼參考 /frameworks/native/cmds/servicemanager/binder.c#147
在 【Binder 機制】分析 Android 內核源碼中的 Binder 驅動源碼 binder.c ( googlesource 中的 Android 內核源碼 | 內核源碼下載 ) 博客中分析了該 ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0) 方法對應的源碼 ;
五、開啟 Binder 循環
在 service_manager.c 的 main 函數中 , 調用 binder_loop(bs, svcmgr_handler) 開啟 Binder 循環 ;
binder_loop 方法定義在 /frameworks/native/cmds/servicemanager/binder.c 中 ;
在 binder_loop 方法中 , 先調用了 binder_write 方法 , 然后開啟了死循環 ;
void binder_loop(struct binder_state *bs, binder_handler func) {int res;struct binder_write_read bwr;uint32_t readbuf[32];bwr.write_size = 0;bwr.write_consumed = 0;bwr.write_buffer = 0;readbuf[0] = BC_ENTER_LOOPER;// binder_write(bs, readbuf, sizeof(uint32_t));// 開啟無限循環 for (;;) {bwr.read_size = sizeof(readbuf);bwr.read_consumed = 0;bwr.read_buffer = (uintptr_t) readbuf;res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);if (res < 0) {ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));break;}// 如果收到 Binder 讀寫消息信息 , 調用 binder_parse 方法處理 ;res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);if (res == 0) {ALOGE("binder_loop: unexpected reply?!\n");break;}if (res < 0) {ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));break;}} }完整代碼參考 /frameworks/native/cmds/servicemanager/binder.c ;
六、binder_write 方法
在 binder_write 方法中 , 調用了內核中的 ioctl(bs->fd, BINDER_WRITE_READ, &bwr) 方法 ; 具體方法參考 【Binder 機制】分析 Android 內核源碼中的 Binder 驅動源碼 binder.c ( googlesource 中的 Android 內核源碼 | 內核源碼下載 ) 博客進行分析 ;
int binder_write(struct binder_state *bs, void *data, size_t len) {struct binder_write_read bwr;int res;bwr.write_size = len;bwr.write_consumed = 0;bwr.write_buffer = (uintptr_t) data;bwr.read_size = 0;bwr.read_consumed = 0;bwr.read_buffer = 0;// 此處調用了內核方法 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);if (res < 0) {fprintf(stderr,"binder_write: ioctl failed (%s)\n",strerror(errno));}return res; }完整代碼參考 /frameworks/native/cmds/servicemanager/binder.c ;
七、binder_ioctl 內核方法
分析調用內核方法 ioctl(bs->fd, BINDER_WRITE_READ, &bwr) , 傳入 BINDER_WRITE_READ 常量 , 走如下分支代碼 ; 主要調用了 binder_ioctl_write_read 方法 ;
case BINDER_WRITE_READ:ret = binder_ioctl_write_read(filp, cmd, arg, thread);if (ret)goto err;break;android-mainline/drivers/android/binder.c 部分內核 Binder 驅動代碼 :
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {int ret;struct binder_proc *proc = filp->private_data;struct binder_thread *thread;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;/*pr_info("binder_ioctl: %d:%d %x %lx\n",proc->pid, current->pid, cmd, arg);*/binder_selftest_alloc(&proc->alloc);trace_binder_ioctl(cmd, arg);ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);if (ret)goto err_unlocked;thread = binder_get_thread(proc);if (thread == NULL) {ret = -ENOMEM;goto err;}switch (cmd) {case BINDER_WRITE_READ:ret = binder_ioctl_write_read(filp, cmd, arg, thread);if (ret)goto err;break;default:ret = -EINVAL;goto err;}ret = 0; err:if (thread)thread->looper_need_return = false;wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);if (ret && ret != -EINTR)pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); err_unlocked:trace_binder_ioctl_done(ret);return ret; }完整代碼參考 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/binder.c ;
八、binder_ioctl_write_read 內核方法
在 方法中 , 調用了 222 個重要的方法 , copy_from_user(&bwr, ubuf, sizeof(bwr)) 從用戶空間的進程緩沖區中讀取到內核空間緩沖區 , copy_to_user(ubuf, &bwr, sizeof(bwr)) 從內核空間寫出到用戶空間進程中 ;
如果寫出的數據大于 0 , 則調用 binder_thread_write 方法 ;
如果讀取的數據大于 0 , 則調用 binder_thread_read 方法 ;
完整代碼參考 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/binder.c ;
總結
以上是生活随笔為你收集整理的【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【开发环境】Java 文件生成 Wind
- 下一篇: 【Binder 机制】Native 层