Binder 是 Android 系统的进程间通信机制,是了解 Android 运行机制必须要掌握的一个知识点,更是一线企业面试必问的知识点!比如:
- binder 有什么优势?(字节)
- binder 一次拷贝原理?(腾讯)
- Intent 传递大数据限制?(阿里)
- AIDL 原理?(字节)
- 谈谈你对 binder 驱动的了解?(字节)
你都能回答上来吗!?
到底怎样才能彻底掌握 binder 机制、游刃有余的应对 binder 面试问题,让面试官对你刮目相看,斩获高薪 offer 呢?
没有捷径,「Read The Fucking Source Code!」,这句话绝对是至理名言。
要达到彻底掌握,不能死记别人对 binder 的概括描述,而是要自己深入源码去看它到底是个什么东西,有了自己的理解,才能胸有成竹的应对相关面试问题。
本文主要来分析下 binder 驱动源码中的三个关键函数,binder_open()、binder_mmap() 及 binder_ioctl()。
上层调用陷入内核
分析这三个关键函数前,先来看下它们是如何被上层调用的,这样对 binder 机制有整体的了解,才不至于对 binder 驱动的理解太过孤立。
binder 驱动在系统内核中,从用户空间应用程序到内核空间 binder 驱动,会经过一些 ProcessState、IPCThreadState 等中间的操作封装类,然后通过系统调用陷入系统内核。
ProcessState 是进程单例,主要负责打开 binder 驱动设备及 mmap。binder 驱动的 binder_open()、binder_mmap() 函数在 ProcessState 的构造函数中被调用,如下:
ProcessState::ProcessState()
: mDriverFD(open_driver()) //打开 binder 设备,binder_open()
, mVMStart(MAP_FAILED)
...
, mMaxThreads(DEFAULT_MAX_binder_THREADS)
, mThreadPoolSeq(1){
if (mDriverFD >= 0) {
// 将应用进程虚拟内存空间与 binder 驱动映射,binder_mmap()
mVMStart = mmap(0, binder_VM_SIZE, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
close(mDriverFD);
mDriverFD = -1;
}
}
}
IPCThreadState 为线程单例,负责与 binder 驱动进行具体的命令通信。在其 talkWithDriver() 方法中,调用了 binder 驱动的 binder_ioctl() 函数:
// binder_ioctl
ioctl(mProcess->mDriverFD, binder_WRITE_READ, &bwr)
binder 驱动注册
binder 驱动运行在内核态,向上层提供 /dev/binder 设备节点,并不对应真实的硬件设备。binder 驱动的注册逻辑在 Binder.c 中:
//drivers/staging/android/Binder.c
static init __init binder_init(void){
...
ret = misc_register(&binder_miscdev); //注册为 misc 驱动
}