Android系列-ION內(nèi)存管理簡介

Android系列-ION內(nèi)存管理簡介

一元莫、ION相關(guān)介紹

Android的ION子系統(tǒng)的目的主要是通過在硬件設(shè)備和用戶空間之間分配和共享內(nèi)存绵载,實(shí)現(xiàn)設(shè)備之間零拷貝共享內(nèi)存羊苟。說來簡單胶惰,其實(shí)不易鹉戚。在Soc硬件中,許多設(shè)備可以進(jìn)行DMA师幕,這些設(shè)備可能有不同的能力粟按,以及不同的內(nèi)存訪問機(jī)制。

ION是Google在Android 4.0 ICS中引入霹粥,用于改善對于當(dāng)前不同的android設(shè)備灭将,有著各種不同內(nèi)存管理接口管理相應(yīng)內(nèi)存的狀況。當(dāng)前存在著各種不同的但是功能卻類似的內(nèi)存管理接口后控,例如在NVIDIA Tegra有一個(gè)“NVMAP”機(jī)制庙曙、在TI OMAP有一個(gè)“CMEM”機(jī)制、在Qualcomm MSM有一個(gè)“PMEM”機(jī)制浩淘,ION將其進(jìn)行通用化捌朴,通過其接口,可集中分配各類不同內(nèi)存(heap)张抄,同時(shí)上述三個(gè)芯片廠商也正將其內(nèi)存管理策略切換至ION上砂蔽。

另外,ION在內(nèi)核空間和用戶空間分別有一套接口欣鳖,它不僅能管理內(nèi)存察皇,還可在其clients(來自內(nèi)核的或者來自用戶空間的)之間共享內(nèi)存茴厉。

綜上泽台,ION主要功能:

  • 內(nèi)存管理器:提供通用的內(nèi)存管理接口,通過heap管理各種類型的內(nèi)存矾缓。
  • 共享內(nèi)存:可提供驅(qū)動(dòng)之間怀酷、用戶進(jìn)程之間、內(nèi)核空間和用戶空間之間的共享內(nèi)存嗜闻。

二蜕依、實(shí)現(xiàn)原理

在ION中,用不同heap代表不同類型的內(nèi)存,每種heap有自己的內(nèi)存分配策略样眠。

主要的heap:

  • ION_HEAP_TYPE_SYSTEM: 使用vmalloc分配友瘤,這個(gè)對應(yīng)ion_heap_ops中的map_user函數(shù)
  • ION_HEAP_TYPE_SYSTEM_CONTIG: 通過kmalloc分配
  • ION_HEAP_TYPE_CARVEOUT: 在啟動(dòng)的時(shí)候就保留的物理上連續(xù)的內(nèi)存塊
  • 另外還有兩種,這里不關(guān)注:
  • ION_HEAP_TYPE_CHUNK
  • ION_HEAP_TYPE_DMA: memory allocated via DMA API
圖片.png

每個(gè)heap中可分配若干個(gè)buffer檐束,每個(gè)client通過handle管理對應(yīng)的buffer辫秧。每個(gè)buffer只能有一個(gè)handle對應(yīng),每個(gè)用戶進(jìn)程只能有一個(gè)client被丧,每個(gè)client可能有多個(gè)handle盟戏。兩個(gè)client通過文件描述符fd(和handle有所對應(yīng),通過handle獲壬稹)柿究,通過映射方式,將相應(yīng)內(nèi)存映射黄选,實(shí)現(xiàn)共享內(nèi)存蝇摸。

圖片.png

三、使用方法

下面的內(nèi)容著重講述用戶空間進(jìn)程之間的內(nèi)存共享办陷。

1探入、用戶空間內(nèi)使用ION的方法

用戶空間可以使用libion庫實(shí)現(xiàn)對ion的操作,這里不講述該庫的操作方法懂诗,用戶程序直接通過ioctl和驅(qū)動(dòng)打交道蜂嗽,ion常見的ioctl命令為:

  • ION_IOC_ALLOC: 分配內(nèi)存
  • ION_IOC_FREE: 釋放內(nèi)存
  • ION_IOC_MAP: 獲得一個(gè)只想mmap映射的內(nèi)存的文件描述符
  • ION_IOC_SHARE: 創(chuàng)建一個(gè)指向共享的內(nèi)存的文件描述符
  • ION_IOC_IMPORT: 引入一個(gè)共享的文件描述符
  • ION_IOC_CUSTOM: 調(diào)用平臺自定義的ioctl

具體使用示例可以參見該庫的文件實(shí)現(xiàn)(system/core/lib/ion/),或如下:

sharedMemoryION.txz

(1)獲取一個(gè)ION client

需要打開ION設(shè)備:

open("/dev/ion", O_RDONLY)

這里殃恒,進(jìn)程要有訪問權(quán)限植旧,雖然是使用O_RDONLY標(biāo)記但是也返回一個(gè)可寫的內(nèi)存。返回的文件描述符號做為表示一個(gè)ION client的handle离唐。每個(gè)用戶進(jìn)程只能有一個(gè)client病附。用戶空間的client通過ioctl()系統(tǒng)調(diào)用接口和ION交互。

(2)設(shè)置獲取buffer的參數(shù)

填充結(jié)構(gòu)ion_allocation_data亥鬓,主要包含如下成員:

struct ion_allocation_data {
    size_t len;
    size_t align;
    unsigned int heap_mask;
    unsigned int flags;
    struct ion_handle *handle;                                                                                                                      
};

這里 handle做為輸出 (struct ion_handle 類型)讽挟,需要填充的是其中除handle成員之外的成員(整個(gè)buffer是 struct ion_allocation_data 類型)。對于其他參數(shù)蕾哟,注意在文檔 (http://lwn.net/Articles/480055/) 中并沒有給出heap_mask搂誉,只說flags是一個(gè)比特掩碼,標(biāo)識一個(gè)或者多個(gè)將要分配所使用的ION heap(結(jié)合后面熟呛,它的解釋是錯(cuò)誤的宽档,應(yīng)該是對heap_mask的解釋),但是從源代碼中的注釋看庵朝,這些參數(shù)的含義如下:

  • len:分配的大小吗冤。
  • align:分配所需的對其參數(shù)又厉。
  • heap_mask:待分配所使用的所有heaps的掩碼(如:ION_HEAP_SYSTEM_MASK)。
  • flags:傳給heap的標(biāo)志(如:ION_FLAG_CACHED)椎瘟,ion系統(tǒng)使用低16位覆致,高16位用于各自heap實(shí)現(xiàn)使用。

具體各自取值和實(shí)現(xiàn)肺蔚,請參見ion驅(qū)動(dòng)頭文件定義和驅(qū)動(dòng)代碼篷朵。

(3)分配buffer

將設(shè)置好的buffer參數(shù)傳遞給ioctl:

int ioctl(int client_fd, ION_IOC_ALLOC, struct ion_allocation_data *allocation_data)

這里,client_fd就是剛剛打開的/dev/ioc文件描述符號婆排。分配的buffer通過返回的上述結(jié)構(gòu)的 struct ion_handle *handle 成員來引用声旺,但是這個(gè)handle并不是一個(gè)CPU訪問的地址。一個(gè)client不能有兩個(gè)handle指向同樣的buffer段只。

(4)共享buffer

buffer的handle只能通過如下調(diào)用獲取一個(gè)文件描述符號用于buffer共享:

int ioctl(int client_fd, ION_IOC_SHARE, struct ion_fd_data *fd_data);

其中fd_data如下:

struct ion_fd_data {
        struct ion_handle *handle;
        int fd;
   }

這里腮猖, handle是輸入 ,標(biāo)示要共享buffer的handle赞枕; fd是輸出 澈缺,標(biāo)示用于共享buffer的文件描述符號。

(5)傳遞待共享的文件描述符號

在android設(shè)備中炕婶,可能會(huì)通過Binder機(jī)制將共享的文件描述符fd發(fā)送給另外一個(gè)進(jìn)程姐赡。

為了獲得被共享的buffer,第二個(gè)用戶進(jìn)程必須通過首先調(diào)用 open("/dev/icon", O_RDONLY) 獲取一個(gè)client handle柠掂,ION通過進(jìn)程ID跟蹤它的用戶空間clients项滑。 在同一個(gè)進(jìn)程中重復(fù)調(diào)用open("/dev/icon", O_RDONLY)將會(huì)返回另外一個(gè)文件描述符號,這個(gè)文件描述符號會(huì)引用內(nèi)核同樣的client結(jié)構(gòu) 涯贞。

獲取到共享文件描述符fd后枪狂,共享進(jìn)程可以通過mmap來操作共享內(nèi)存。

(6)釋放

為了釋放緩存宋渔,第二個(gè)client需要通過munmap來取消mmap的效果州疾,第一個(gè)client需要關(guān)閉通過ION_IOC_SHARE命令獲得的文件描述符號,并且使用ION_IOC_FREE如下:

int ioctl(int client_fd, ION_IOC_FREE, struct ion_handle_data *handle_data);

其中:

struct ion_handle_data {
    struct ion_handle *handle;
}

命令會(huì)導(dǎo)致handle的引用計(jì)數(shù)減少1皇拣。當(dāng)這個(gè)引用計(jì)數(shù)達(dá)到0的時(shí)候严蓖,ion_handle對象會(huì)被析構(gòu),同時(shí)ION的索引數(shù)據(jù)結(jié)構(gòu)被更新氧急。

用戶進(jìn)程也可與內(nèi)核驅(qū)動(dòng)共享ION buffer颗胡。

2、內(nèi)核空間內(nèi)使用ION的方法

具體參見參考資料态蒂,這里簡略介紹杭措。

(1)獲取一個(gè)ION Client

調(diào)用如下函數(shù):

struct ion_client *ion_client_create(struct ion_device *dev,unsigned int heap_mask, const char *debug_name)

內(nèi)核中可以有多個(gè)ION clients费什,每個(gè)使用ION的driver擁有一個(gè)client钾恢。這里手素,參數(shù)dev就是對應(yīng)/dev/ion的設(shè)備,為何需要這個(gè)參數(shù)瘩蚪,目前還不確切泉懦;參數(shù)heap_mask和前面敘述一樣,用于選擇一個(gè)或多個(gè)ion heaps類型標(biāo)識堆類型疹瘦。flags參數(shù)前面說過了崩哩。

(2)共享來自用戶空間的ion buffer

用戶傳遞 ion共享文件描述符 給內(nèi)核驅(qū)動(dòng),驅(qū)動(dòng) 轉(zhuǎn)成ion_handle

struct ion_handle *ion_import_fd(struct ion_client *client, int fd_from_user);

在許多包含多媒體中間件的智能手機(jī)中言沐,用戶進(jìn)程經(jīng)常從ion中分配buffer邓嘹,然后使用ION_IOC_SHARE命令獲取文件描述符號,然后將文件描述符號傳遞給內(nèi)核驅(qū)動(dòng)险胰。內(nèi)核驅(qū)動(dòng)調(diào)用ion_import_fd()將文件描述符轉(zhuǎn)換成ion_handle對象汹押。內(nèi)核驅(qū)動(dòng)使用ion_handle對象做為對共享buffer的client本地引用。該函數(shù)查找buffer的物理地址一確認(rèn)是否這個(gè)client是否之前分配了同樣的buffer起便,如果是棚贾,則僅增加相應(yīng)handle的引用計(jì)數(shù)。

有些硬件塊只能操作物理地址連續(xù)的buffer榆综,所以相應(yīng)的驅(qū)動(dòng)應(yīng) 對ion_handle轉(zhuǎn)換

int ion_phys(struct ion_client *client, struct ion_handle *handle, ion_phys_addr_t *addr, size_t *len)

若buffer的物理地址不連續(xù)妙痹,這個(gè)調(diào)用會(huì)失敗。

在處理client的調(diào)用之時(shí)鼻疮,ion始終會(huì)對input file descriptor,client,和handle arguments進(jìn)行確認(rèn)怯伊。例如:當(dāng)import一個(gè)file descriptor(文件描述符)之時(shí),ion會(huì)保證這個(gè)文件描述符確實(shí)是通過ION_IOC_SHARE命令創(chuàng)建的判沟。當(dāng)ion_phys()被調(diào)用之時(shí)震贵,ION會(huì)驗(yàn)證buffer handle是否在client允許訪問的handles列表中,若不是水评,則返回錯(cuò)誤猩系。這些驗(yàn)證機(jī)制減少了期望之外的訪問與資源泄露。

四中燥、ION 調(diào)試

關(guān)于ION debug寇甸,在 /sys/kernel/debug/ion/ 提供一個(gè)debugfs 接口。

每個(gè)heap都有自己的debugfs目錄疗涉,client內(nèi)存使用狀況顯示在 /sys/kernel/debug/ion/<<heap name>>

$cat /sys/kernel/debug/ion/ion-heap-1 
 client              pid             size
test_ion             2890            16384

每個(gè)由pid標(biāo)識的client也有一個(gè)debugfs目錄/sys/kernel/debug/ion/<a id="orgtarget1"></a>

$cat /sys/kernel/debug/ion/2890 
heap_name:    size_in_bytes
ion-heap-1:    40960 11

五拿霉、其它資料

待更新

內(nèi)核空間

注:使用例如“git clone https://android.googlesource.com/kernel/common” 下載之后,目錄為空咱扣,這可能是因?yàn)榇嬖诙鄠€(gè)分支绽淘,而當(dāng)前分支為空,可以用"git branch -a"查看相應(yīng)分支闹伪,然后切換之沪铭。

用戶空間

同樣可參照上述方法下載壮池。

整體介紹:

https://wiki.linaro.org/BenjaminGaignard/ion

功能方面:

http://lwn.net/Articles/565469/

使用方面:

http://lwn.net/Articles/480055/

其它參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市杀怠,隨后出現(xiàn)的幾起案子椰憋,更是在濱河造成了極大的恐慌,老刑警劉巖赔退,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橙依,死亡現(xiàn)場離奇詭異,居然都是意外死亡硕旗,警方通過查閱死者的電腦和手機(jī)窗骑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漆枚,“玉大人慧域,你說我怎么就攤上這事±硕粒” “怎么了昔榴?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碘橘。 經(jīng)常有香客問我互订,道長,這世上最難降的妖魔是什么痘拆? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任仰禽,我火速辦了婚禮,結(jié)果婚禮上纺蛆,老公的妹妹穿的比我還像新娘吐葵。我一直安慰自己,他們只是感情好桥氏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布温峭。 她就那樣靜靜地躺著,像睡著了一般字支。 火紅的嫁衣襯著肌膚如雪凤藏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天堕伪,我揣著相機(jī)與錄音揖庄,去河邊找鬼。 笑死欠雌,一個(gè)胖子當(dāng)著我的面吹牛蹄梢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播富俄,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼禁炒,長吁一口氣:“原來是場噩夢啊……” “哼而咆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起齐苛,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤翘盖,失蹤者是張志新(化名)和其女友劉穎桂塞,沒想到半個(gè)月后凹蜂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阁危,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年玛痊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狂打。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡擂煞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趴乡,到底是詐尸還是另有隱情对省,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布晾捏,位于F島的核電站蒿涎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惦辛。R本人自食惡果不足惜劳秋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胖齐。 院中可真熱鬧玻淑,春花似錦、人聲如沸呀伙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剿另。三九已至干像,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驰弄,已是汗流浹背麻汰。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戚篙,地道東北人五鲫。 一個(gè)月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像岔擂,于是被迫代替她去往敵國和親位喂。 傳聞我的和親對象是個(gè)殘疾皇子浪耘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359