[007]一次Binder通信最大可以傳輸多大的數(shù)據(jù)?

前言

在第六章中征椒,我通過匿名共享內(nèi)存的方式解決Binder通信是無法傳遞大數(shù)據(jù)的問題娇哆,一次Binder通信最大可以傳輸是1MB-8KB(PS:8k是兩個pagesize,一個pagesize是申請物理內(nèi)存的最小單元)

但是這個答案對不對呢勃救,我只能說不準(zhǔn)確碍讨,接下來我們來仔細(xì)研究一下

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.
        // 調(diào)用mmap接口向Binder驅(qū)動中申請內(nèi)核空間的內(nèi)存
        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();
        }
    }
}

如果一個進(jìn)程使用ProcessState這個類來初始化Binder服務(wù)溉躲,這個進(jìn)程的Binder內(nèi)核內(nèi)存上限就是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進(jìn)程孵化出來的,Zygote進(jìn)程的初始化Binder服務(wù)的時候提前調(diào)用了ProcessState這個類粗恢,所以普通的APP進(jìn)程上限就是1MB-8KB。

問一下自己,能否不用ProcessState來初始化Binder服務(wù),來突破1M-8KB的限制鱼鸠?

答案是當(dāng)然可以了,Binder服務(wù)的初始化有兩步麻蹋,open打開Binder驅(qū)動刹勃,mmap在Binder驅(qū)動中申請內(nèi)核空間內(nèi)存,所以我們只要手寫open乏梁,mmap就可以輕松突破這個限制揖曾。源碼中已經(jīng)給了類似的例子模暗。

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);//我們可以把這個數(shù)值改成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驅(qū)動不怕我們傳遞一個超級大的數(shù)字進(jìn)去嗎隶糕?

其實是我們想多了株旷,在Binder驅(qū)動中mmap的具體實現(xiàn)中還有一個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了齿尽,會在驅(qū)動中被修改成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));

目前的結(jié)論

1.通過手寫open,mmap初始化Binder服務(wù)的限制是4MB

2.通過ProcessState初始化Binder服務(wù)的限制是1MB-8KB

再問一下自己,4M或1MB-8KB這個答案是不是正確?

我發(fā)現(xiàn)一處代碼
/drivers/staging/android/binder.c

static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
{
     //省內(nèi)部分代碼
    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調(diào)用诵原,可申請內(nèi)核空間辑畦,最大上限是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調(diào)用中同步調(diào)用優(yōu)先級大于oneway(異步)的調(diào)用肾砂,為了充分滿足同步調(diào)用的內(nèi)存需要,所以將oneway調(diào)用的內(nèi)存限制到申請內(nèi)存上限的一半。

問題:一次Binder通信最大可以傳輸多大的數(shù)據(jù)嚷狞?

屏幕快照 2019-05-24 下午3.11.51.png

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

答案是理論上可以传货,但是不建議這樣子操作,因為Binder驅(qū)動中并沒有對open祖乳,mmap有調(diào)用次數(shù)的限制作媚,App可以通過JNI調(diào)用open女揭,mmap來突破這個限制境蔼,但是會對當(dāng)前正在進(jìn)行Binder調(diào)用的APP造成不可想象問題,當(dāng)然可以先close Binder驅(qū)動疮鲫。但是一旦這個APP沒有Binder通信了,這個APP就不能正常使用了,APP和其他應(yīng)用刹淌,AMS喊崖,WMS的交互可都是依賴于Binder通信,所以還是那句話,無Binder無Android。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末大猛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子持痰,更是在濱河造成了極大的恐慌,老刑警劉巖言津,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屑咳,死亡現(xiàn)場離奇詭異慰安,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門赶盔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抖坪,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵西设,是天一觀的道長。 經(jīng)常有香客問我,道長印屁,這世上最難降的妖魔是什么雄人? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任阵漏,我火速辦了婚禮裆泳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己糕韧,他們只是感情好枫振,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兔沃,像睡著了一般蒋得。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乒疏,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天额衙,我揣著相機(jī)與錄音,去河邊找鬼怕吴。 笑死窍侧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的转绷。 我是一名探鬼主播伟件,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼议经!你這毒婦竟也來了斧账?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤煞肾,失蹤者是張志新(化名)和其女友劉穎咧织,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體籍救,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡习绢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝙昙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闪萄。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖奇颠,靈堂內(nèi)的尸體忽然破棺而出败去,到底是詐尸還是另有隱情,我是刑警寧澤烈拒,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布圆裕,位于F島的核電站三椿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏葫辐。R本人自食惡果不足惜搜锰,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耿战。 院中可真熱鬧蛋叼,春花似錦、人聲如沸剂陡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸭栖。三九已至歌馍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晕鹊,已是汗流浹背松却。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留溅话,地道東北人晓锻。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像飞几,于是被迫代替她去往敵國和親砚哆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容