Android系統匿名共享記憶體Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
Android系統的匿名共享記憶體子系統的主體是以驅動程式的形式實現在核心空間的,同時,在系統執行時庫層和應用程式框架層提供了訪問介面,其中,在系統執行時庫層提供了C/C++呼叫介面,而在應用程式框架層提供了Java呼叫介面。這裡,我們將直接透過應用程式框架層提供的Java呼叫介面來說明匿名共享記憶體子系統Ashmem的使用方法,畢竟我們在Android開發應用程式時,是基於Java語言的,而實際上,應用程式框架層的Java呼叫介面是透過JNI方法來呼叫系統執行時庫層的C/C++呼叫介面,最後進入到核心空間的Ashmem驅動程式去的。
我們在這裡舉的例子是一個名為Ashmem的應用程式,它包含了一個Server端和一個Client端實現,其中,Server端是以Service的形式實現的,在這裡Service裡面,建立一個匿名共享記憶體檔案,而Client是一個Activity,這個Activity透過Binder程式間通訊機制獲得前面這個Service建立的匿名共享記憶體檔案的控制程式碼,從而實現共享。在Android應用程式框架層,提供了一個MemoryFile介面來封裝了匿名共享記憶體檔案的建立和使用,它實現在frameworks/base/core/java/android/os/MemoryFile.java檔案中。下面,我們就來看看Server端是如何透過MemoryFile類來建立匿名共享記憶體檔案的以及Client是如何獲得這個匿名共享記憶體檔案的控制程式碼的。
在MemoryFile類中,提供了兩種建立匿名共享記憶體的方法,我們透過MemoryFile類的建構函式來看看這兩種使用方法:
- public class MemoryFile
- {
- ......
- /**
- * Allocates a new ashmem region. The region is initially not purgable.
- *
- * @param name optional name for the file (can be null).
- * @param length of the memory file in bytes.
- * @throws IOException if the memory file could not be created.
- */
- public MemoryFile(String name, int length) throws IOException {
- mLength = length;
- mFD = native_open(name, length);
- mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);
- mOwnsRegion = true;
- }
- /**
- * Creates a reference to an existing memory file. Changes to the original file
- * will be available through this reference.
- * Calls to {@link #allowPurging(boolean)} on the returned MemoryFile will fail.
- *
- * @param fd File descriptor for an existing memory file, as returned by
- * {@link #getFileDescriptor()}. This file descriptor will be closed
- * by {@link #close()}.
- * @param length Length of the memory file in bytes.
- * @param mode File mode. Currently only "r" for read-only access is supported.
- * @throws NullPointerException if
fd
is null. - * @throws IOException If
fd
does not refer to an existing memory file, - * or if the file mode of the existing memory file is more restrictive
- * than
mode
. - *
- * @hide
- */
- public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException {
- if (fd == null) {
- throw new NullPointerException("File descriptor is null.");
- }
- if (!isMemoryFile(fd)) {
- throw new IllegalArgumentException("Not a memory file.");
- }
- mLength = length;
- mFD = fd;
- mAddress = native_mmap(mFD, length, modeToProt(mode));
- mOwnsRegion = false;
- }
- ......
- }
- public class MemoryFile
- {
- ......
- /**
- * Allocates a new ashmem region. The region is initially not purgable.
- *
- * @param name optional name for the file (can be null).
- * @param length of the memory file in bytes.
- * @throws IOException if the memory file could not be created.
- */
- public MemoryFile(String name, int length) throws IOException {
- mLength = length;
- mFD = native_open(name, length);
- mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);
- mOwnsRegion = true;
- }
- /**
- * Creates a reference to an existing memory file. Changes to the original file
- * will be available through this reference.
- * Calls to {@link #allowPurging(boolean)} on the returned MemoryFile will fail.
- *
- * @param fd File descriptor for an existing memory file, as returned by
- * {@link #getFileDescriptor()}. This file descriptor will be closed
- * by {@link #close()}.
- * @param length Length of the memory file in bytes.
- * @param mode File mode. Currently only "r" for read-only access is supported.
- * @throws NullPointerException if
fd
is null. - * @throws IOException If
fd
does not refer to an existing memory file, - * or if the file mode of the existing memory file is more restrictive
- * than
mode
. - *
- * @hide
- */
- public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException {
- if (fd == null) {
- throw new NullPointerException("File descriptor is null.");
- }
- if (!isMemoryFile(fd)) {
- throw new IllegalArgumentException("Not a memory file.");
- }
- mLength = length;
- mFD = fd;
- mAddress = native_mmap(mFD, length, modeToProt(mode));
- mOwnsRegion = false;
- }
- ......
- }
public class MemoryFile { ...... /** * Allocates a new ashmem region. The region is initially not purgable. * * @param name optional name for the file (can be null). * @param length of the memory file in bytes. * @throws IOException if the memory file could not be created. */ public MemoryFile(String name, int length) throws IOException { mLength = length; mFD = native_open(name, length); mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE); mOwnsRegion = true; } /** * Creates a reference to an existing memory file. Changes to the original file * will be available through this reference. * Calls to {@link #allowPurging(boolean)} on the returned MemoryFile will fail. * * @param fd File descriptor for an existing memory file, as returned by * {@link #getFileDescriptor()}. This file descriptor will be closed * by {@link #close()}. * @param length Length of the memory file in bytes. * @param mode File mode. Currently only "r" for read-only access is supported. * @throws NullPointerException if從註釋中,我們可以看出這兩個建構函式的使用方法,這裡就不再詳述了。兩個建構函式的主要區別是第一個引數,第一種構造方法是以指定的字串呼叫JNI方法native_open來建立一個匿名共享記憶體檔案,從而得到一個檔案描述符,接著就以這個檔案描述符為引數呼叫JNI方法natvie_mmap把這個匿名共享記憶體檔案對映在程式空間中,然後就可以透過這個對映後得到的地址空間來直接訪問記憶體資料了;第二種構造方法是以指定的檔案描述符來直接呼叫JNI方法natvie_mmap把這個匿名共享記憶體檔案對映在程式空間中,然後進行訪問,而這個檔案描述符就必須要是一個匿名共享記憶體檔案的檔案描述符,這是透過一個內部函式isMemoryFile來驗證的,而這個內部函式isMemoryFile也是透過JNI方法呼叫來進一步驗證的。前面所提到的這些JNI方法呼叫,最終都是透過系統執行時庫層進入到核心空間的Ashmem驅動程式中去,不過這裡我們不關心這些JNI方法、系統執行庫層呼叫以及Ashmem驅動程式的具體實現,在接下來的兩篇文章中,我們將會著重介紹,這裡我們只關注MemoryFile這個類的使用方法。fd
is null. * @throws IOException Iffd
does not refer to an existing memory file, * or if the file mode of the existing memory file is more restrictive * thanmode
. * * @hide */ public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException { if (fd == null) { throw new NullPointerException("File descriptor is null."); } if (!isMemoryFile(fd)) { throw new IllegalArgumentException("Not a memory file."); } mLength = length; mFD = fd; mAddress = native_mmap(mFD, length, modeToProt(mode)); mOwnsRegion = false; } ...... }
前面我們說到,我們在這裡舉的例子包含了一個Server端和一個Client端實現,其中, Server端就是透過前面一個建構函式來建立一個匿名共享記憶體檔案,接著,Client端過Binder程式間通訊機制來向Server請求這個匿名共享記憶體的檔案描述符,有了這個檔案描述符之後,就可以透過後面一個建構函式來共享這個記憶體檔案了。
因為涉及到Binder程式間通訊,我們首先定義好Binder程式間通訊介面。Binder程式間通訊機制的相關介紹,請參考前面一篇文章Android程式間通訊(IPC)機制Binder簡要介紹和學習計劃,這裡就不詳細介紹了,直接進入主題。
首先在原始碼工程的packages/experimental目錄下建立一個應用程式工程目錄Ashmem。關於如何獲得Android原始碼工程,請參考在Ubuntu上下載、編譯和安裝Android最新原始碼一文;關於如何在Android原始碼工程中建立應用程式工程,請參考在Ubuntu上為Android系統內建Java應用程式測試Application Frameworks層的硬體服務一文。這裡,工程名稱就是Ashmem了,它定義了一個路徑為shy.luo.ashmem的package,這個例子的原始碼主要就是實現在這裡了。下面,將會逐一介紹這個package裡面的檔案。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13164110/viewspace-747971/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android匿名共享記憶體(Ashmem)原理Android記憶體
- Linux系統程式設計—共享記憶體之mmapLinux程式設計記憶體
- 計算機記憶體管理介紹計算機記憶體
- 記憶體回收介紹記憶體
- CUDA記憶體介紹記憶體
- JVM中記憶體和GC的介紹JVM記憶體GC
- jvm堆記憶體和GC簡介JVM記憶體GC
- Sieve—Android 記憶體分析系統Android記憶體
- Android Studio Profiler Memory (記憶體分析工具)的簡單使用及問題Android記憶體
- 作業系統——記憶體管理學習筆記作業系統記憶體筆記
- Linux系統程式設計之命名管道與共享記憶體Linux程式設計記憶體
- Android記憶體優化(四)解析Memory Monitor、Allocation Tracker和Heap DumpAndroid記憶體優化
- STM32記憶體結構介紹和FreeRTOS記憶體分配技巧記憶體
- Unix高階程式設計學習筆記--系統呼叫簡介程式設計筆記
- 記憶體檔案系統的再學習記憶體
- Memory記憶體傳值記憶體
- VisionPro學習筆記(1)——軟體介紹和基本使用筆記
- 【Android系統】Android系統架構簡介Android架構
- Java記憶體模型簡介Java記憶體模型
- Java記憶體模型 - 簡介Java記憶體模型
- Win10系統GPU共享記憶體怎麼關閉?Win10系統GPU共享記憶體的關閉方法Win10GPU記憶體
- ros學習檔案系統介紹ROS
- Android系統介紹與框架Android框架
- Android 輸入系統介紹Android
- 記憶體管理(Debug Memory Graph)記憶體
- Allowed memory size 記憶體不足記憶體
- Unity Memory Profiler 記憶體分析Unity記憶體
- 元學習簡單介紹
- 持久記憶體指令(PMDK)簡介記憶體
- Linux系統的發展歷史和學習前景介紹Linux
- 學習筆記-React的簡單介紹&工作原理筆記React
- Golang 共享記憶體Golang記憶體
- POSIX 共享記憶體記憶體
- [Linux]共享記憶體Linux記憶體
- 12. 記憶體管理(Memory Management)記憶體
- 知名駭客組織Anonymous(匿名者)
- MySQL記憶體管理,記憶體分配器和作業系統MySql記憶體作業系統
- 共享記憶體對映(linux程式與執行緒學習筆記)記憶體Linux執行緒筆記
- ClickHouse學習系列之七【系統命令介紹】