pmem是android爲DSP vpu gpu等設備提供的一種內存分配機制,我們都知道vpu gpu這一類設備需要大塊的連續物理內存以便進行硬件解碼,硬件顯示加速。PMEM就像一個小型的buddy內存管理系統,獨立於linux kernel內存管理模塊管理,不會受到內存管理中的外碎片的影響,同時還可以靈活的提供額外功能。
當然在系統運行一段時間後,PMEM也同樣面臨着外碎片問題,因此PMEM內存區的使用者儘量分配大塊的內存,而不是零星的小內存。
應用層使用方法
1. 分配的內存只在一個進程中使用
pmem_fd = open("/dev/pmem_gpu", O_RDWR, 0);
pmem_base = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, pmem_fd, 0);
2. 不同進程間共享。這利用了PMEM 驅動的Connect功能
進程1:
pmem_fd0 = open("/dev/pmem_gpu", O_RDWR, 0);
pmem_base = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, pmem_fd0, 0);
進程2:
pmem_fd1 = open("/dev/pmem_gpu", O_RDWR, 0);
ret = ioctl(pmem_fd1, PMEM_CONNECT, pmem_fd0);
ret = ioctl(pmem_fd1, PMEM_MAP, ®ion1);
一個進程打開PMEM設備,通過mmap操作映射內存到進程空間,該進程稱爲PMEM的master進程。其他進程可以再次打開該設備,然後通過PMEM_CONNECT操作,pmem_fd1就和pmem_fd0獲得了相同的Pmem空間,這樣該進程就稱爲PMEM的client進程。
PMEM設備接口
內核爲每一個PMEM創建一個misc 設備節點,應用層通過這個設備節點的file_operations操作PMEM設備。
內存分配:
PMEM內存是供應用空間程序使用的,kernel和驅動並不會使用PMEM。應用程序首先打開相應PMEM設備節點,使用mmap系統調用或者PMEM_MAP PMEM_ALLOCATE ioctl申請pmem內存
內存釋放:
應用程序可以顯示的調用PMEM_UNMAP來釋放分配的pmem內存,文件release操作會釋放這個PMEM設備所有分配的內存。因此只要close了文件,那麼就保證所有分配的內存都被回收,防止由於用戶疏忽或者程序異常造成的內存泄漏。
獲取物理內存地址
sometimes,應用空間需要獲取物理地址
ioctl PMEM_GET_PHYS 獲取pmem內存物理地址,我們知道pmem驅動維護着多個pmem設備,並且每個pmem設備還可能進行多次分配。那麼這裏是如何確定請求哪個pmem設備,哪一次分配的物理地址呢?
通過設備節點的從設備號,就可以確定這次請求的pmem設備;此外在file結構的private_data是一個pmem_data結構,pmem_data->index指向了最後一次分配的索引位置。因此PMEM_GET_PHYS獲取的是這個pmem設備最後一次分配內存的起始物理地址。
PMEM_GET_SIZE, PMEM_GET_TOTAL_SIZE
PMEM_GET_SIZE用來獲取給定PMEM設備最後一次分配的size;而PMEM_GET_TOTAL_SIZE則獲取給定PMEM的整個空間size
PMEM_CACHE_FLUSH
刷新給定內存區的cache,dmac_flush_range包括writeback和invalidate操作,使得寫cache寫回,讀cache無效