Binder就是Android中的血管,在Android中我们所使用的的Activity,Service等组件都需要和AMS通信,这种跨进程的通信都是通过Binder完成的。
机制:Binder是一种通信机制
驱动:Binder是一个虚拟物理设备驱动
应用层:Binder是一个能发起通信的Java类
多进程的使用及优势
虚拟机分配给各个进程的运行内存是有限制的,LMK也会优先回收对系统资源占用多的进程
1、突破进程内存限制:如有些功能占据内存过多,可以考虑给一个单独的进程
2、功能稳定性:独立的通讯进程保持长连接的稳定性,一般用于通讯
3、规避系统内存泄漏:独立的WebView进程组个内存泄漏导致的问题
4、隔离风险:对于不稳定、危险的功能放入独立进程,避免导致主进程崩溃
...........
Binder是如何做到一次性拷贝的
Linux进程间通讯有哪些?
传统的IPC:Socket、内存共享等
Binder与传统IPC对比:
内存划分:
内存被操作系统划分为两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方。为了安全它们是隔离的。即使用户的程序崩溃了,内核也不受影响。
传统IPC两次拷贝:
一次是把用户空间的数据copy到内核空间中,一次是从内核空间中copy到用户空间中。
传统内存共享:
内存共享就是用户直接在内核空间操作,这样就不需要从用户空间copy到内核空间或者从内核空间copy到用户空间了。这中间用到了mmap(),通过mmap(),用户空间和内核空间建立两个映射。
Binder实现:
Binder就在服务端直接操作内核空间,也是通过mmap(),用户端还是需要从用户空间copy到内核空间,所以是一次copy。这么做的原因是内存共享不好控制,所以为了方便使用客户端不使用内存共享;而服务端的内存共享是由Google工程师完成的。这样做即做到性能优化,有具有易用性。
MMAP的原理:
Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射(memory mapping)。
所有的系统资源管理都是在内核空间中完成的,比如读写磁盘文件,分配回收内存,从网络接口读写数据等等。用户空间通过系统调用让内核空间完成这些功能。
比如我的写文件流程:
1、调用write,告诉内核需要写入数据的开始地址和长度
2、内核将数据copy到内核缓存
3、由操作系统调用,将数据copy到磁盘,完成写入
demon:
#include <jni.h>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <android/log.h>
int8_t *m_ptr;
int32_t m_size;
int m_fd;
extern "C"
JNIEXPORT void JNICALL
Java_com_enjoy_leo_1binder_MainActivity_writeTest(JNIEnv *env, jobject thiz) {
std::string file = "/storage/a.txt";
//打开文件
m_fd = open(file.c_str(), O_RDWR | O_CREAT, S_IRWXU);
//获得一页内存大小
//Linux采用了分页来管理内存,即内存的管理中,内存是以页为单位,一般的32位系统一页为 4096个字节
m_size = getpagesize();
//将文件设置为 m_size这么大
ftruncate(m_fd, m_size); // 100 1000 10000
// m_size:映射区的长度。 需要是整数页个字节 byte[]
m_ptr = (int8_t *) mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd,
0);
std::string data("test刚刚写入的数据");
memcpy(m_ptr, data.data(), data.size());
__android_log_print(ANDROID_LOG_ERROR, "test", "写入数据:%s", data.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_com_enjoy_leo_1binder_MainActivity_readTest(JNIEnv *env, jobject thiz) {
//申请内存
char *buf = static_cast<char *>(malloc(100));
memcpy(buf, m_ptr, 100);
std::string result(buf);
__android_log_print(ANDROID_LOG_ERROR, "test", "读取数据:%s", result.c_str());
//取消映射
munmap(m_ptr, m_size);
//关闭文件
close(m_fd);
}