1. Binder体系
模型:
Client/ Server / ServerManager -> 用户空间
驱动 -> 内核空间
2. 内存划分(重要):
- 用户空间+内核空间(两者都是虚拟内存, 虚拟地址, 指向物理地址),
- 虚拟内存技术:应用申请内存时,分配的是虚拟内存?? 使用到时才加载到物理内存??
它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片
-内核空间是共享的
内存划分通信例子
这里需要拷贝两次! (对比mmap 只拷贝一次)
3.Binder 与传统IPC 对比
4. Binder传输数据(如何做到一次拷贝)
原理: 有一块物理内存是 共享内存, 接收方从共享内存里读取
类似于现在的快递蜜蜂箱 .
Linux 内核实际上没有用一个用户空间到另一个用户空间直接拷贝的函数,
需要先用copy_from_user() 拷贝到内核空间,
再用copy_to_user()拷贝到另一个用户空间。
为了实现用户空间到用户空间的拷贝,
mmap()分配的内存除了映射进接收方的进程里, 还映射进内核空间。
所以copy_from_user()将数据拷贝仅内核空间,也就相当于拷贝进接收方的用户空间,即一次拷贝
m5. MMAP 的原理 (memory mapping)
5.1 概念
mmap 就是一个api : binder_mmap, 定义在binder驱动的源码里
java - native -> 驱动层 binder_mmmp
5.2 mmap 写文件例子
5.3 mmap 源码 (写入指针指向的物理地址)
6. Binder 机制是如何跨进程的
实际上是对:Binder传输数据(如何做到一次拷贝) 和 MMAP 的原理 的总结
7. AIDL 生成Java类的细节
AIDL 黄牛,中介
binder -- 模板 -- AIDL
其中模板可以将AIDL 转成java 语言, 可以自己实现的。
8. 四大组件底层的通信机制
9. 为什么Intent不能传输大数据
限制: 具体值为:1M - 8K , mmap 创建共享空间时开辟的空间
为什么实际小于 1M - 8K, 因为数据还需要打包,例如网络通信数据打包额外由包头、命令等。
//(1) app_main.cpp APP启动时
//https://github.com/aosp-mirror/platform_frameworks_base/blob/master/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
//(2 ) ProcessState.cpp ?? 分配共享内存空间
//https://github.com/xdtianyu/android-6.0.0_r1/blob/master/frameworks/native/libs/binder/ProcessState.cpp
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
ProcessState::ProcessState()
: mDriverFD(open_driver())
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
异步的情况下是 (1M - 8K) /2
TODO: 下载binder驱动的代码
另 binder 在各层次的对象
driver 层: binder_node 结构体 (c++)
native 层 binder 对象类: BBinder JavaBBinder
Java层 Binder.java
Android Binder 机制好文参考: