Android核心分析(25)——Android GDI之共用緩衝區機制

來源:互聯網
上載者:User
Androird GDI之共用緩衝區機制

1  native_handle_t對private_handle_t 的包裹

     private_handle_t是gralloc.so使用的本地緩衝區私人的資料結構,而Native_handle_t是上層抽象的可以在進程間傳遞的資料結構。在用戶端是如何還原所傳遞的資料結構呢?首先看看native_handle_t對private_handle_t的抽象封裝。

numFds= sNumFds=1;

numInts= sNumInts=8;

這個是Parcel中描述控制代碼的抽象模式。實際上是指的Native_handle所指向控制代碼對象的具體內容:

numFds=1表示有一個檔案控制代碼:fd/

numInts= 8表示後面跟了8個INT型的資料:magic,flags,size,offset,base,lockState,writeOwner,pid;

由於在上層系統不要關心buffer_handle_t中data的具體內容。在進程間傳遞buffer_handle_t(native_handle_t)控制代碼是其實是將這個控制代碼內容傳遞到Client端。在用戶端通過Binder讀取readNativeHandle @Parcel.cpp新產生一個native_handle。

native_handle* Parcel::readNativeHandle() const

{

native_handle* h = native_handle_create(numFds, numInts);

    for (int i=0 ; err==NO_ERROR && i

        h->data[i] = dup(readFileDescriptor());

        if (h->data[i]

    }

    err = read(h->data + numFds, sizeof(int)*numInts);

    ….

return h;

}

     這裡需要提到的是為在構造用戶端的native_handle時,對於對方傳遞過來的檔案控制代碼的處理。由於不是在同一個進程中,所以需要dup(…)一下為用戶端使用。這樣就將Native_handle控制代碼中的,用戶端感興趣的從服務端複製過來。這樣就將Private_native_t的資料:magic,flags,size,offset,base,lockState,writeOwner,pid;複製到了用戶端。

     用戶端利用這個新的Native_buffer被Mapper傳回到gralloc.xxx.so中,擷取到native_handle關聯的共用緩衝區映射地址,從而擷取到了該緩衝區的控制權,達到了客服端和Server間的記憶體共用。從SurfaceFlinger來看就是作圖地區的共用。

2 Graphic Mapper是幹什麼的?

    服務端(SurfaceFlinger)分配了一段記憶體作為Surface的作圖緩衝,用戶端怎樣在這個作圖緩衝區上工作呢?這個就是Mapper(GraphicBufferMapper)y要乾的事情。兩個進程間如何共用記憶體,如何擷取到共用記憶體?Mapper就是幹這個得。需要利用到兩個資訊:共用緩衝區裝置控制代碼,分配時的位移量。Mapper利用這樣的原理:

    用戶端只有lock,unlock,實質上就是mmap和ummap的操作。對於同樣一個共用緩衝區,位移量才是總要的,起始地址不重要。實際上他們操作了同一物理地址的記憶體塊。我們在上面討論了native_handle_t對private_handle_t 的包裹過程,從中知道服務端給用戶端傳遞了什麼東西。

        進程1在共用記憶體裝置上預分配了8M的記憶體。以後所有的分配都是在這個8M的空間進行。對以該檔案裝置來講,8M實體記憶體提交後,就實實在在的佔用了8M記憶體。每個每個進程都可以同個該記憶體裝置共用該8M的記憶體,他們使用的工具就會mmap。由於在mmap都是用0開始擷取映射地址,所以所有的用戶端進程都是有了同一個物理其真實位址,所以此時位移量和size就可以標識一段記憶體。而這個位移量和size是個數值,從服務進程傳遞到用戶端直接就可以使用。

 3 GraphicBuffer(緩衝區代理對象)

typedef struct android_native_buffer_t

{

    struct android_native_base_t common;

    int width;

    int height;

    int stride;

    int format;

    int usage;

     …

    buffer_handle_t handle;

     …

} android_native_buffer_t;

關係圖表:

GraphicBuffer :EGLNativeBase :android_native_buffer_t

GraphicBuffer(parcel &)建立本地的GraphicBuffer的資料native_buffer_t。在通過接收對方的傳遞的native_buffer_t 構建GraphicBuffer。我們來看看在用戶端Surface::lock擷取操作緩衝區的函數調用:

Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)

     {int Surface::dequeueBuffer(android_native_buffer_t** buffer)(Surface)

        {status_t Surface::getBufferLocked(int index, int usage)

          {

               sp buffer = s->requestBuffer(index, usage);

           {

virtual sp requestBuffer(int bufferIdx, int usage)

{   remote()->transact(REQUEST_BUFFER, data, &reply);

   sp buffer = new GraphicBuffer(reply);

Surface::Lock建立一個在Client端建立了一個新的GraphicBuffer 對象,該對象通過(1)描述的原理將SurfaceFlinger的buffer_handle_t相關資料構成新的用戶端buffer_handle_t資料。在用戶端的Surface對象就可以使用GraphicMapper對用戶端buffer_handle_t進行mmap從而擷取到共用緩衝區的開始地址了。

4 總結

   Android在該節使用了共用記憶體的方式來管理與顯示相關的緩衝區,他設計成了兩層,上層是緩衝區管理的代理機構GraphicBuffer,及其相關的native_buffer_t,下層是具體的緩衝區的分配管理及其緩衝區本身。上層的對象是可以在經常間通過Binder傳遞的,而在進程間並不是傳遞緩衝區本身,而是使用mmap來擷取指向共同實體記憶體的映射地址。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.