Binder通信机制(一)

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);
}

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值