日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )

發布時間:2025/6/17 编程问答 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【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); ;
int main(int argc, char** argv) {// 開啟 Binder , 獲取 Binder 驅動 , 并且申請了 128 KB 的內存映射地址bs = binder_open(driver, 128*1024);// 將自己注冊成 Binder 進程的上下文if (binder_become_context_manager(bs)) {ALOGE("cannot become context manager (%s)\n", strerror(errno));return -1;}// 開啟 Binder 循環 binder_loop(bs, svcmgr_handler);return 0; }

完整代碼參考 /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 方法 ;

static int binder_ioctl_write_read(struct file *filp,unsigned int cmd, unsigned long arg,struct binder_thread *thread) {int ret = 0;struct binder_proc *proc = filp->private_data;unsigned int size = _IOC_SIZE(cmd);void __user *ubuf = (void __user *)arg;struct binder_write_read bwr;if (size != sizeof(struct binder_write_read)) {ret = -EINVAL;goto out;}// 從用戶空間的進程緩沖區中讀取到內核空間緩沖區 if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {ret = -EFAULT;goto out;}binder_debug(BINDER_DEBUG_READ_WRITE,"%d:%d write %lld at %016llx, read %lld at %016llx\n",proc->pid, thread->pid,(u64)bwr.write_size, (u64)bwr.write_buffer,(u64)bwr.read_size, (u64)bwr.read_buffer);// 如果寫出的數據大于 0 if (bwr.write_size > 0) {ret = binder_thread_write(proc, thread,bwr.write_buffer,bwr.write_size,&bwr.write_consumed);trace_binder_write_done(ret);if (ret < 0) {bwr.read_consumed = 0;if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto out;}}// 如果讀取的數據大于 0 if (bwr.read_size > 0) {ret = binder_thread_read(proc, thread, bwr.read_buffer,bwr.read_size,&bwr.read_consumed,filp->f_flags & O_NONBLOCK);trace_binder_read_done(ret);binder_inner_proc_lock(proc);if (!binder_worklist_empty_ilocked(&proc->todo))binder_wakeup_proc_ilocked(proc);binder_inner_proc_unlock(proc);if (ret < 0) {if (copy_to_user(ubuf, &bwr, sizeof(bwr)))ret = -EFAULT;goto out;}}binder_debug(BINDER_DEBUG_READ_WRITE,"%d:%d wrote %lld of %lld, read return %lld of %lld\n",proc->pid, thread->pid,(u64)bwr.write_consumed, (u64)bwr.write_size,(u64)bwr.read_consumed, (u64)bwr.read_size);// 從內核空間寫出到用戶空間進程中 if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {ret = -EFAULT;goto out;} out:return ret; }

完整代碼參考 https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/binder.c ;

總結

以上是生活随笔為你收集整理的【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。