關於graphicbuffer的使用,前幾天再檢視乙個記憶體洩漏的問題時,了解了一些關於android上的graphicbuffer使用的細節。以下的這個sample就是為了測試graphicbuffer對應的gralloc如何分配內/釋放記憶體,以及對於不同的執行緒或者是程序gralloc如何處理這塊graphicbuffer的生命週期。以及不同的graphicbuffer::handlewrapmethod,對應的如何處理這個graphicbuffer的構造和析構
對於初學者,可以參考frameworks/native/ui/tests的目錄下的測試用例,寫一些簡單的graphicbuffer的sample。
#include
#include
#include
using
namespace android;
constexpr
uint32_t ktestwidth =
1024
;constexpr
uint32_t ktestheight =
200;
constexpr
uint32_t ktestlayercount =1;
constexpr
uint64_t ktestusage = graphicbuffer::usage_sw_write_often;
constexpr pixelformat format = pixel_format_rgba_8888;
//填充buffer的資料,以及引數設定
void
fillrgba8buffer
(uint8_t
* buf,
int w,
int h,
int stride)}}
}class
mythread
:public thread
public
:explicit
mythread
(const native_handle_t* inhandle)
~mythread()
};int main (
void
)
說明: 以上的sample,大致的意思是,在主線程先建立乙個graphicbuffer,然後把這個native_handle_t傳遞給mythread,這個mythread會建立乙個新的graphicbuffer,那這些graphicbuffer的建構函式中有乙個關鍵的引數graphicbuffer::handlewrapmethod.
標頭檔案graphicbuffer.h中說明如下:
enum handlewrapmethod :
uint8_t
;
這個method在整個android的工程中,用的比較多,因為這個比較安全,但是這個也是需要按照一定的規則使用,因為上層呼叫這個在使用clone_handle建立出來的graphicbuffer。
比如說有些gpu的晶元方實現driver的時候,要求上層要保證gpu使用的時候這個graphicbuffer的生命週期有效,這個buffer的引用計數不能減到0,因為如果上層還有在用這個handle的時候,gpu釋放,根據不同的廠家gpu的實現,出現不同的問題。有些gpu釋放graphicbuffer的時候,對應的handle被lock的話,有些gpu的driver是實現不會處理這個error的資訊,只拋乙個warning,最種可能導致gralloc上記憶體洩漏。
接著說clone_handle的作用,這個method的使用,是為了保證,程序或者是執行緒之間傳遞這個native_handle_t的時候,防止這個handle對應的實際物理記憶體被別的程序或者執行緒釋放掉,需要呼叫
native_handle_create 建立乙個新的native_handle_t,對這個物理buffer引用+
1
其實也是呼叫了dup的方法,複製出來乙個這個handle對應的fd,就是在kernel那邊註冊下,告訴kernel或者是實際物理記憶體管理者,這個記憶體我還在用,需要把這個buffer的引用計數+1,不能被釋放。等我不用的時候,把這個
native_handle_close
native_handle_delete的時候,再把這個buffer的引用計數-
1。
注:那這塊實際的buffer釋放,是不確定的,誰最後呼叫了引用計數-1,正好踩到計數0的話,就可能會真的析構這個物理buffer。
native_handle_create –>
native_handle_close
((native_handle_t *
)psnativehandle)
->
native_handle_delete
((native_handle_t *
)psnativehandle)
因為graphicbuffer的構造和析構會根據method,決定是否去建立新的native_handle_t,wrap_handle是表示,只使用這個native_handle_t,不管理這個native_handle_t對應的記憶體釋放。
sample2 簡化為三步:
第一步:sp test1 =
newgraphicbuffer
(…)-
> 建立graphicbuffer,應該是呼叫下面的模板類生成sp的指標
sp的模板類如下:
template
<
typename t>
sp& sp
::operator
=(t* other)
第二步: test1.
clear
()的呼叫如下:
template
<
typename t>
void sp
::clear()
} 第三步:test1 =
nullptr的話,跟第乙個sp指標賦值的過程相同,同樣也會呼叫引用計數-
1
總之:誰踩到了減到0 的點,誰就會接著呼叫graphicbuffer的析構,這個跟物理buffer的析構不是乙個引用,因為物理buffer由驅動或者kernel管理生命週期。
anativewindowbuffer* graphicbuffer::
getnativebuffer()
const
列印graphicbuffer的指標和anativewindowbuffer的指標,但是返回的位址不是相同的,會有一定的偏移。
graphicbuffer=
0xef9701e0
, anativewindowbuffer=
0xef9701e8
這個應該是c++中類繼承的時候強轉的計算,要做偏移之後才能指向aanativewindowbuffer
void graphicbuffer::
free_handle()
else
if(mowner == owndata)
handle =
nullptr
;}
讀寫這個buffer之前需要先lock這個buffer,map出來乙個虛擬位址,寫完或者是讀完之後,需要unlock釋放。
lock和unlock的使用是需要配對,否則會有虛擬記憶體異常的問題或者是gpu的driver異常。
總結:
graphicbuffer是可以程序間共享的buffer,程序間傳遞的時候,除了一些graphicbuffer中寬高引數傳遞之外,還有乙個重要的引數,就是這個buffer對應的fd。graphicbuffer對應的物理buffer,在kernel中有對應的管理,也就是物理buffer的引用計數,對於上層不同的應用,每個應用都可以用乙個fd對應這個物理buffer,這個fd在不同的程序中也不一定相同。上面說的native_handle_create 就是生成乙個新的fd,也就是對這個物理buffer的引用計數+1。(這個是從別的部落格和跟同事討論中獲取的一些資訊,可能也表述的不夠精確,但是fd大概的意思就這樣,嘿嘿)
SqlCacheDependency的使用方法
步驟一 sql資料庫必須開啟servicebroker服務,首先檢測是否已經啟用servicebroker,檢測方法 select databasepropertyex 資料庫名稱 isbrokerenabled 1表示已經啟用0表示沒有啟用 步驟二 如果servicebroker沒有啟用,使用下面...
UITabBarController的使用心得
這段時間了解下uitabbarcontroller,今天把我遇到的問題和心得記錄下。網上有很多uitabbarcontroller的資料,對於一些uitabbarcontroller的基礎性知識,在這裡我就不囉嗦了。可以看這裡 今天我要說的是自己的一些不同於網上的的心得。官方的一副還是要貼出來。我也...
UITabBarController的使用步驟
初始化 uitabbarcontroller 設定uiwindow的rootviewcontroller為 uitabbarcontroller 根據具體情況,通過addchildviewcontroller方法新增對應個數的子控制器 uitabbarcontroller新增控制器的方式有2種 新增...