首页 > 其他分享 >一次Binder通信最大可以传输多大的数据?

一次Binder通信最大可以传输多大的数据?

时间:2023-11-08 15:00:10浏览次数:37  
标签:struct mmap 多大 binder vma 传输 Binder proc

前言

在第六章中,我通过匿名共享内存的方式解决Binder通信是无法传递大数据的问题,一次Binder通信最大可以传输是1MB-8KB(PS:8k是两个pagesize,一个pagesize是申请物理内存的最小单元)

但是这个答案对不对呢,我只能说不准确,接下来我们来仔细研究一下

1MB-8KB的限制来源于哪里

frameworks/native/libs/binder/ProcessState.cpp

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)//这里的限制是1MB-4KB*2

ProcessState::ProcessState(const char *driver)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        // 调用mmap接口向Binder驱动中申请内核空间的内存
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }
}

如果一个进程使用ProcessState这个类来初始化Binder服务,这个进程的Binder内核内存上限就是BINDER_VM_SIZE,也就是1MB-8KB。

frameworks/base/cmds/app_process/app_main.cpp

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

对于普通的APP来说,我们都是Zygote进程孵化出来的,Zygote进程的初始化Binder服务的时候提前调用了ProcessState这个类,所以普通的APP进程上限就是1MB-8KB。

问一下自己,能否不用ProcessState来初始化Binder服务,来突破1M-8KB的限制?

答案是当然可以了,Binder服务的初始化有两步,open打开Binder驱动,mmap在Binder驱动中申请内核空间内存,所以我们只要手写open,mmap就可以轻松突破这个限制。源码中已经给了类似的例子。

frameworks/native/cmds/servicemanager/bctest.c

int main(int argc, char **argv)
{
    struct binder_state *bs;
    uint32_t svcmgr = BINDER_SERVICE_MANAGER;
    uint32_t handle;

    bs = binder_open("/dev/binder", 128*1024);//我们可以把这个数值改成2*1024*1024就可以突破这个限制了
    if (!bs) {
        fprintf(stderr, "failed to open binder driver\n");
        return -1;
    }

frameworks/native/cmds/servicemanager/binder.c

struct binder_state *binder_open(const char* driver, size_t mapsize)
{
    ...//省略部分代码
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
    ....//省略部分代码
    bs->mapsize = mapsize;//这里mapsize=128*1024
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    ....//省略部分代码
}

难道Binder驱动不怕我们传递一个超级大的数字进去吗?

其实是我们想多了,在Binder驱动中mmap的具体实现中还有一个4M的限制
/drivers/staging/android/binder.c

static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
{
    int ret;
    struct vm_struct *area;
    struct binder_proc *proc = filp->private_data;
    const char *failure_string;
    struct binder_buffer *buffer;

    if (proc->tsk != current)
        return -EINVAL;

    if ((vma->vm_end - vma->vm_start) > SZ_4M)
        vma->vm_end = vma->vm_start + SZ_4M;//如果申请的size大于4MB了,会在驱动中被修改成4MB

    binder_debug(BINDER_DEBUG_OPEN_CLOSE,
             "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
             proc->pid, vma->vm_start, vma->vm_end,
             (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
             (unsigned long)pgprot_val(vma->vm_page_prot));

目前的结论

1.通过手写open,mmap初始化Binder服务的限制是4MB

2.通过ProcessState初始化Binder服务的限制是1MB-8KB

再问一下自己,4M或1MB-8KB这个答案是不是正确?

我发现一处代码
/drivers/staging/android/binder.c

static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
{
     //省内部分代码
    proc->free_async_space = proc->buffer_size / 2;//这个代码引起我注意,async代码异步的意思
    barrier();
    proc->files = get_files_struct(current);
    proc->vma = vma;
    proc->vma_vm_mm = vma->vm_mm;
static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
                          size_t data_size,
                          size_t offsets_size, int is_async)
{

    //省略部分代码
    if (is_async &&
        proc->free_async_space < size + sizeof(struct binder_buffer)) {
        //对于oneway的Binder调用,可申请内核空间,最大上限是buffer_size的一半,也就是mmap时候传递的值的一半。
        binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
                 "%d: binder_alloc_buf size %zd failed, no async space left\n",
                  proc->pid, size);
        return NULL;
    }

为什么要做这样子的限制,我的猜想是Binder调用中同步调用优先级大于oneway(异步)的调用,为了充分满足同步调用的内存需要,所以将oneway调用的内存限制到申请内存上限的一半。

问题:一次Binder通信最大可以传输多大的数据?

再问一下自己,自己写的APP能否突破1M-8KB的限制

答案是理论上可以,但是不建议这样子操作,因为Binder驱动中并没有对open,mmap有调用次数的限制,App可以通过JNI调用open,mmap来突破这个限制,但是会对当前正在进行Binder调用的APP造成不可想象问题,当然可以先close Binder驱动。但是一旦这个APP没有Binder通信了,这个APP就不能正常使用了,APP和其他应用,AMS,WMS的交互可都是依赖于Binder通信,所以还是那句话,无Binder无Android。

[007]一次Binder通信最大可以传输多大的数据? - 简书 (jianshu.com)    

标签:struct,mmap,多大,binder,vma,传输,Binder,proc
From: https://www.cnblogs.com/wanglongjiang/p/17817432.html

相关文章

  • 某音用SSL证书上了一把“安全锁”,加密保护网络传输数据安全
    依照《网络安全法》、《数据安全法》等相关法律法规,网络运营者应当按照网络安全等级保护制度的要求,采用数据加密等措施来防止网络数据泄露或者被窃取、篡改。某音作为头部的音乐创意短视频社交平台,每天都有数以亿计的用户在上面观看、发布视频,而这会产生大量包含个人账号、密码等用......
  • 19.6 Boost Asio 文本压缩传输
    Base64是一种二进制到文本的编码方案,用于将二进制数据转换为ASCII字符串格式。它通过将二进制数据流转换为一系列64个字符来工作,这些字符都可以安全地传输到设计用于处理文本数据的系统中。如下代码中我们使用Boost中提供的base64_from_binary头文件实现两个函数,其中Base64Decode......
  • C# 创建一个指定对象的类,传输此类对应的集合,比如:只传输name和value
    当接口需要只传出某两列的数据,其他数据不需要的时候,可以自定义个一个类,只传输需要的数据1.定义一个类1publicclassMobileHospital2{3publicstringname{get;set;}4publicstringvalue{get;set;}5}2.查询目标数据集合List......
  • 在线直播源码,js 文件上传 图片上传 传输速度计算
    在线直播源码,js文件上传图片上传传输速度计算<!doctypehtml><html><head>  <metacharset="UTF-8">  <metaname="viewport"content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scal......
  • Filebat跨公网传输日志
    目录......
  • COM服务项目中数据块(数组)的高效传输方式
    1.问题背景在《C#程序与COM服务程序传递数组和字符串的方式》一文中,我提供了数组的传递方式,是通过atlsafe.h中CComSafeArray模板类来实现的,但是在实际开发过程中发现,直接使用其自身提供的随机数据访问函数进行数据操作速度较慢,在大量传输数据时运行时间不可接受,所以本文记录......
  • 19.7 Boost Asio 传输序列化数据
    序列化和反序列化是指将数据结构或对象转换为一组字节,以便在需要时可以将其存储在磁盘上或通过网络传输,并且可以在需要时重新创建原始对象或数据结构。序列化是将内存中的对象转换为字节的过程。在序列化期间,对象的状态被编码为一组字节,并可以保存或传输到另一个位置。序列化后的......
  • 20.8 OpenSSL 套接字SSL传输文件
    有了上面的基础那么传输文件的实现就变得简单了,在传输时通常我们需要打开文件,并每次读入1024个字节的数据包,通过SSL加密传输即可,此处的文件传输功能在原生套接字章节中也进行过详细讲解,此处我们还是使用原来的密钥对,实现一个服务端等待客户端上传,当客户端连接到服务端后则开始传输......
  • 20.7 OpenSSL 套接字SSL加密传输
    OpenSSL中的SSL加密是通过SSL/TLS协议来实现的。SSL/TLS是一种安全通信协议,可以保障通信双方之间的通信安全性和数据完整性。在SSL/TLS协议中,加密算法是其中最核心的组成部分之一,SSL可以使用各类加密算法进行密钥协商,一般来说会使用RSA等加密算法,使用TLS加密针对服务端来说......
  • 20.7 OpenSSL 套接字SSL加密传输
    OpenSSL中的SSL加密是通过SSL/TLS协议来实现的。SSL/TLS是一种安全通信协议,可以保障通信双方之间的通信安全性和数据完整性。在SSL/TLS协议中,加密算法是其中最核心的组成部分之一,SSL可以使用各类加密算法进行密钥协商,一般来说会使用RSA等加密算法,使用TLS加密针对服务端来......