<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 1MB-8KB的限制來源于哪里 [frameworks](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2F)/[native](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2F)/[libs](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Flibs%2F)/[binder](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Flibs%2Fbinder%2F)/[ProcessState.cpp](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Flibs%2Fbinder%2FProcessState.cpp) ~~~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](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2F)/[base](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fbase%2F)/[cmds](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fbase%2Fcmds%2F)/[app\_process](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fbase%2Fcmds%2Fapp_process%2F)/[app\_main.cpp](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fbase%2Fcmds%2Fapp_process%2Fapp_main.cpp) ~~~rust 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](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2F)/[native](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2F)/[cmds](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Fcmds%2F)/[servicemanager](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Fcmds%2Fservicemanager%2F)/[bctest.c](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Fcmds%2Fservicemanager%2Fbctest.c) ~~~cpp 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](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2F)/[native](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2F)/[cmds](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Fcmds%2F)/[servicemanager](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Fcmds%2Fservicemanager%2F)/[binder.c](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2F9.0.0_r3%2Fxref%2Fframeworks%2Fnative%2Fcmds%2Fservicemanager%2Fbinder.c) ~~~rust 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](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2F)/[staging](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2Fstaging%2F)/[android](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2Fstaging%2Fandroid%2F)/[binder.c](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2Fstaging%2Fandroid%2Fbinder.c) ~~~rust 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](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2F)/[staging](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2Fstaging%2F)/[android](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2Fstaging%2Fandroid%2F)/[binder.c](https://links.jianshu.com/go?to=http%3A%2F%2Fandroidxref.com%2Fkernel_3.18%2Fxref%2Fdrivers%2Fstaging%2Fandroid%2Fbinder.c) ~~~rust 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; ~~~ ~~~rust 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通信最大可以傳輸多大的數據? ![](//upload-images.jianshu.io/upload_images/14919101-8d648cf27ce006d8.png?imageMogr2/auto-orient/strip|imageView2/2/w/1044/format/webp) 屏幕快照 2019-05-24 下午3.11.51.png # 再問一下自己,自己寫的APP能否突破1M-8KB的限制 答案是理論上可以,但是不建議這樣子操作,因為Binder驅動中并沒有對open,mmap有調用次數的限制,App可以通過JNI調用open,mmap來突破這個限制,但是會對當前正在進行Binder調用的APP造成不可想象問題,當然可以先close Binder驅動。但是一旦這個APP沒有Binder通信了,這個APP就不能正常使用了,APP和其他應用,AMS,WMS的交互可都是依賴于Binder通信,所以還是那句話,無Binder無Android。 # 傳遞大量數據 ## 共享內存 共享內存是進程間通信的一種方式,通過映射一塊公共內存到各自的進程空間來達到共享內存的目的。 ![![shmem.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c61eae70f6ff41d8bacc573e10d91031~tplv-k3u1fbpfcp-watermark.awebp) ](images/screenshot_1643253910596.png) 對于進程間需要傳遞大量數據的場景下,這種通信方式是十分高效的,但是共享內存并未提供同步機制,也就是說,在第一個進程結束對共享內存的寫操作之前,并無自動機制可以阻止第二個進程開始對它進行讀取,所以我們通常需要用其他的機制來同步對共享內存的訪問,例如信號量。 `Android`中的匿名共享內存(Ashmem)是基于`Linux`共享內存的,借助`Binder`+文件描述符(`FileDescriptor`)實現了共享內存的傳遞。它可以讓多個進程操作同一塊內存區域,并且除了物理內存限制,沒有其他大小限制。相對于`Linux`的共享內存,Ashmem對內存的管理更加精細化,并且添加了互斥鎖。`Java`層在使用時需要用到`MemoryFile`,它封裝了`native`代碼。`Android`平臺上共享內存通常的做法如下: * 進程A通過`MemoryFile`創建共享內存,得到fd(`FileDescriptor`) * 進程A通過fd將數據寫入共享內存 * 進程A將fd封裝成實現`Parcelable`接口的`ParcelFileDescriptor`對象,通過`Binder`將`ParcelFileDescriptor`對象發送給進程B * 進程B獲從`ParcelFileDescriptor`對象中獲取fd,從fd中讀取數據 # 參考資料 [一次Binder通信最大可以傳輸多大的數據?](https://www.jianshu.com/p/ea4fc6aefaa8) [一道面試題:使用AIDL實現跨進程傳輸一個2M大小的文件](https://juejin.cn/post/6990379493235884062)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看