Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹_第1頁
Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹_第2頁
Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹_第3頁
Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹_第4頁
Android系統(tǒng)匿名共享內(nèi)存Ashmem(Anonymous Shared Memory)簡要介紹_第5頁
已閱讀5頁,還剩17頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、       在Android系統(tǒng)中,提供了獨特的匿名共享內(nèi)存子系統(tǒng)Ashmem(Anonymous Shared Memory),它以驅(qū)動程序的形式實現(xiàn)在內(nèi)核空間中。它有兩個特點,一是能夠輔助內(nèi)存管理系統(tǒng)來有效地管理不再使用的內(nèi)存塊,二是它通過Binder進程間通信機制來實現(xiàn)進程間的內(nèi)存共享。本文中,我們將通過實例來簡要介紹Android系統(tǒng)的匿名共享內(nèi)存的使用方法,使得我們對Android系統(tǒng)的匿名共享內(nèi)存機制有一個感性的認識,為進一步學(xué)習(xí)它的源代碼實現(xiàn)打下基礎(chǔ)。        Android系統(tǒng)的匿

2、名共享內(nèi)存子系統(tǒng)的主體是以驅(qū)動程序的形式實現(xiàn)在內(nèi)核空間的,同時,在系統(tǒng)運行時庫層和應(yīng)用程序框架層提供了訪問接口,其中,在系統(tǒng)運行時庫層提供了C/C+調(diào)用接口,而在應(yīng)用程序框架層提供了Java調(diào)用接口。這里,我們將直接通過應(yīng)用程序框架層提供的Java調(diào)用接口來說明匿名共享內(nèi)存子系統(tǒng)Ashmem的使用方法,畢竟我們在Android開發(fā)應(yīng)用程序時,是基于Java語言的,而實際上,應(yīng)用程序框架層的Java調(diào)用接口是通過JNI方法來調(diào)用系統(tǒng)運行時庫層的C/C+調(diào)用接口,最后進入到內(nèi)核空間的Ashmem驅(qū)動程序去的。        我們在這里舉的例子是一個

3、名為Ashmem的應(yīng)用程序,它包含了一個Server端和一個Client端實現(xiàn),其中,Server端是以Service的形式實現(xiàn)的,在這里Service里面,創(chuàng)建一個匿名共享內(nèi)存文件,而Client是一個Activity,這個Activity通過Binder進程間通信機制獲得前面這個Service創(chuàng)建的匿名共享內(nèi)存文件的句柄,從而實現(xiàn)共享。在Android應(yīng)用程序框架層,提供了一個MemoryFile接口來封裝了匿名共享內(nèi)存文件的創(chuàng)建和使用,它實現(xiàn)在frameworks/base/core/java/android/os/MemoryFile.java文件中。下面,我們就來看看Server端是

4、如何通過MemoryFile類來創(chuàng)建匿名共享內(nèi)存文件的以及Client是如何獲得這個匿名共享內(nèi)存文件的句柄的。        在MemoryFile類中,提供了兩種創(chuàng)建匿名共享內(nèi)存的方法,我們通過MemoryFile類的構(gòu)造函數(shù)來看看這兩種使用方法:view plain1. public class MemoryFile  2.   3.     .  4.   5.    &

5、#160;/* 6.     * Allocates a new ashmem region. The region is initially not purgable. 7.     * 8.     * param name optional name for the

6、0;file (can be null). 9.     * param length of the memory file in bytes. 10.     * throws IOException if the memory file could not be created.

7、60;11.     */  12.     public MemoryFile(String name, int length) throws IOException   13.         mLength = length;  14.     

8、;    mFD = native_open(name, length);  15.         mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);  16.         mOwnsRegio

9、n = true;  17.       18.   19.     /* 20.     * Creates a reference to an existing memory file. Changes to the original file 

10、21.     * will be available through this reference. 22.     * Calls to link #allowPurging(boolean) on the returned MemoryFile will fail. 23.     *

11、0;24.     * param fd File descriptor for an existing memory file, as returned by 25.     *        link #getFileDescriptor(). This file 

12、descriptor will be closed 26.     *        by link #close(). 27.     * param length Length of the memory file in bytes. 28.   

13、;  * param mode File mode. Currently only "r" for read-only access is supported. 29.     * throws NullPointerException if <code>fd</code> is null. 3

14、0.     * throws IOException If <code>fd</code> does not refer to an existing memory file, 31.     *         or if the file&

15、#160;mode of the existing memory file is more restrictive 32.     *         than <code>mode</code>. 33.     * 34.     *

16、0;hide 35.     */  36.     public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException   37.         if (fd = null

17、)   38.             throw new NullPointerException("File descriptor is null.");  39.           40.      &

18、#160;  if (!isMemoryFile(fd)   41.             throw new IllegalArgumentException("Not a memory file.");  42.          &

19、#160;43.         mLength = length;  44.         mFD = fd;  45.         mAddress = native_mmap(mFD, length, modeToProt(mo

20、de);  46.         mOwnsRegion = false;  47.       48.   49.     .  50.           從注釋中,我們可以看出這兩個構(gòu)造函數(shù)的使用方法,這里就不再詳述了。兩個構(gòu)造函數(shù)的主要區(qū)別

21、是第一個參數(shù),第一種構(gòu)造方法是以指定的字符串調(diào)用JNI方法native_open來創(chuàng)建一個匿名共享內(nèi)存文件,從而得到一個文件描述符,接著就以這個文件描述符為參數(shù)調(diào)用JNI方法natvie_mmap把這個匿名共享內(nèi)存文件映射在進程空間中,然后就可以通過這個映射后得到的地址空間來直接訪問內(nèi)存數(shù)據(jù)了;第二種構(gòu)造方法是以指定的文件描述符來直接調(diào)用JNI方法natvie_mmap把這個匿名共享內(nèi)存文件映射在進程空間中,然后進行訪問,而這個文件描述符就必須要是一個匿名共享內(nèi)存文件的文件描述符,這是通過一個內(nèi)部函數(shù)isMemoryFile來驗證的,而這個內(nèi)部函數(shù)isMemoryFile也是通過JNI方法調(diào)用

22、來進一步驗證的。前面所提到的這些JNI方法調(diào)用,最終都是通過系統(tǒng)運行時庫層進入到內(nèi)核空間的Ashmem驅(qū)動程序中去,不過這里我們不關(guān)心這些JNI方法、系統(tǒng)運行庫層調(diào)用以及Ashmem驅(qū)動程序的具體實現(xiàn),在接下來的兩篇文章中,我們將會著重介紹,這里我們只關(guān)注MemoryFile這個類的使用方法。        前面我們說到,我們在這里舉的例子包含了一個Server端和一個Client端實現(xiàn),其中, Server端就是通過前面一個構(gòu)造函數(shù)來創(chuàng)建一個匿名共享內(nèi)存文件,接著,Client端過Binder進程間通信機制來向Server請求這個匿名共享內(nèi)存

23、的文件描述符,有了這個文件描述符之后,就可以通過后面一個構(gòu)造函數(shù)來共享這個內(nèi)存文件了。        因為涉及到Binder進程間通信,我們首先定義好Binder進程間通信接口。Binder進程間通信機制的相關(guān)介紹,請參考前面一篇文章Android進程間通信(IPC)機制Binder簡要介紹和學(xué)習(xí)計劃,這里就不詳細介紹了,直接進入主題。        首先在源代碼工程的packages/experimental目錄下創(chuàng)建一個應(yīng)用程序工程目錄Ashmem。關(guān)于如何獲得Android源代碼工程,請參

24、考在Ubuntu上下載、編譯和安裝Android最新源代碼一文;關(guān)于如何在Android源代碼工程中創(chuàng)建應(yīng)用程序工程,請參考在Ubuntu上為Android系統(tǒng)內(nèi)置Java應(yīng)用程序測試Application Frameworks層的硬件服務(wù)        這里要用到的Binder進程間通信接口定義在src/shy/luo/ashmem/IMemoryService.java文件中:view plain1. package2.   3. import4. import5. import6. import7. import8.

25、import9. import10.   11. public interface IMemoryService extends IInterface   12.     public static abstract class Stub extends Binder implements IMemoryService   13.   &

26、#160;     private static final String DESCRIPTOR =   14.   15.         public Stub()   16.             at

27、tachInterface(this, DESCRIPTOR);  17.           18.   19.         public static IMemoryService asInterface(IBinder obj)   20.     

28、        if (obj = null)   21.                 return null;  22.             

29、;  23.   24.             IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);  25.             if (iin != n

30、ull && iin instanceof IMemoryService)   26.                 return (IMemoryService)iin;  27.            

31、60;  28.   29.             return new30.           31.   32.         public IBinder asBinder()  

32、; 33.             return this;  34.           35.   36.         Override   37.     &#

33、160;   public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws38.             switch (code)   39.      &#

34、160;      case INTERFACE_TRANSACTION:   40.                 reply.writeString(DESCRIPTOR);  41.           

35、0;     return true;  42.               43.             case TRANSACTION_getFileDescriptor:   44.   &

36、#160;             data.enforceInterface(DESCRIPTOR);  45.                   46.          &

37、#160;      ParcelFileDescriptor result = this.getFileDescriptor();  47.                   48.           &

38、#160;     reply.writeNoException();  49.                   50.                 if (result&

39、#160;!= null)   51.                     reply.writeInt(1);  52.                  

40、0;  result.writeToParcel(reply, 0);  53.                  else   54.                  

41、0;  reply.writeInt(0);  55.                   56.   57.                 return true;  

42、;58.               59.             case TRANSACTION_setValue:   60.              

43、0;  data.enforceInterface(DESCRIPTOR);  61.                   62.                 int val = dat

44、a.readInt();  63.                 setValue(val);  64.                   65.      

45、0;          reply.writeNoException();  66.                   67.               &

46、#160; return true;  68.               69.               70.   71.           

47、0; return super.onTransact(code, data, reply, flags);  72.           73.   74.         private static class Proxy implements IMemoryService&

48、#160;  75.             private IBinder mRemote;  76.   77.             Proxy(IBinder remote)   78.    

49、60;            mRemote = remote;  79.               80.   81.             public

50、 IBinder asBinder()   82.                 return mRemote;  83.               84.   85.   &

51、#160;         public String getInterfaceDescriptor()   86.                 return DESCRIPTOR;  87.       

52、        88.   89.             public ParcelFileDescriptor getFileDescriptor() throws RemoteException   90.         

53、        Parcel data = Parcel.obtain();  91.                 Parcel reply = Parcel.obtain();  92.   93.    

54、;             ParcelFileDescriptor result;  94.       95.                 try   96.   

55、;                  data.writeInterfaceToken(DESCRIPTOR);  97.   98.                     mR

56、emote.transact(Stub.TRANSACTION_getFileDescriptor, data, reply, 0);  99.           100.                     reply.readExcepti

57、on();  101.                     if (0 != reply.readInt()   102.103.                &#

58、160;     else   104.                         result = null;  105.          

59、             106.                  finally   107.               &

60、#160;     reply.recycle();  108.                     data.recycle();  109.              &#

61、160;    110.       111.                 return result;  112.               113.  

62、; 114.             public void setValue(int val) throws RemoteException   115.                 Parcel data

63、0;= Parcel.obtain();  116.                 Parcel reply = Parcel.obtain();  117.   118.              

64、0;  try   119.                     data.writeInterfaceToken(DESCRIPTOR);  120.               &#

65、160;     data.writeInt(val);  121.   122.                     mRemote.transact(Stub.TRANSACTION_setValue, data, reply, 0);  123. &

66、#160;                     124.                     reply.readException();  125.  

67、;                finally   126.                     reply.recycle();  127.    &#

68、160;                data.recycle();  128.                   129.          &

69、#160;    130.           131.   132.         static final int TRANSACTION_getFileDescriptor = IBinder.FIRST_CALL_TRANSACTION + 0;  133.

70、        static final int TRANSACTION_setValue = IBinder.FIRST_CALL_TRANSACTION + 1;  134.   135.       136.   137.     public ParcelFileDesc

71、riptor getFileDescriptor() throws RemoteException;  138.     public void setValue(int val) throws RemoteException;  139.           這里主要是定義了IMemoryService接口,它里面有兩個調(diào)用接口:view plain1. publi

72、c ParcelFileDescriptor getFileDescriptor() throws RemoteException;  2. public void setValue(int val) throws RemoteException;  Android系統(tǒng)進程間通信Binder機制在應(yīng)用程序框架層的Java接口源代碼分析一文。        有了Binder進程間通信接口之后,接下來就是要在Server

73、端實現(xiàn)一個本地服務(wù)了。這里,Server端實現(xiàn)的本地服務(wù)名為MemoryService,實現(xiàn)在src/shy/luo/ashmem/MemoryService.java文件中:view plain1. package2.   3. import4. import5.   6. import7. import8. import9. import10.   11. public class MemoryService extends IMemoryService.Stub  &#

74、160;12.     private final static String LOG_TAG =   13.     private MemoryFile file = null;  14.       15.     public MemoryService()&#

75、160;  16.         try   17.                         file = new MemoryFile("Ashmem", 4

76、);  18.                         setValue(0);  19.                   20

77、.                 catch(IOException ex)   21.                         Log.i(LOG_

78、TAG, "Failed to create memory file.");  22.                         ex.printStackTrace();  23.      

79、             24.       25.   26.     public ParcelFileDescriptor getFileDescriptor()   27.         Log.i(LOG_T

80、AG, "Get File Descriptor.");  28.   29.         ParcelFileDescriptor pfd = null;  30.   31.         try   32.   

81、60;         pfd = file.getParcelFileDescriptor();  33.          catch(IOException ex)   34.             Log.i(

82、LOG_TAG, "Failed to get file descriptor.");  35.             ex.printStackTrace();  36.           37.   38.    

83、;     return pfd;  39.       40.       41.     public void setValue(int val)   42.         if(file = 

84、;null)   43.             return;  44.           45.   46.         byte buffer = new byte4; 

85、;    47.         buffer0 = (byte)(val >>> 24) & 0xFF);  48.         buffer1 = (byte)(val >>> 16) & 0xFF)

86、;  49.         buffer2 = (byte)(val >>> 8) & 0xFF);   50.         buffer3 = (byte)(val & 0xFF);  51.    

87、;       52.         try   53.             file.writeBytes(buffer, 0, 0, 4);  54.        &#

88、160;    Log.i(LOG_TAG, "Set value " + val + " to memory file. ");  55.           56.         catch(IOExce

89、ption ex)   57.             Log.i(LOG_TAG, "Failed to write bytes to memory file.");  58.             ex.

90、printStackTrace();  59.           60.       61.           注意,這里的MemoryService類實現(xiàn)了IMemoryService.Stub類,表示這是一個Binder服務(wù)的本地實現(xiàn)。在構(gòu)造函數(shù)中,通過指定文件名和文件大小來創(chuàng)建了一個匿名共享內(nèi)存文件,即創(chuàng)建MemoryFile的一個實例,

91、并保存在類成員變量file中。這個匿名共享內(nèi)存文件名為"Ashmem",大小為4個節(jié)字,剛好容納一個整數(shù),我們這里舉的例子就是要說明如果創(chuàng)建一個匿名共享內(nèi)存來在兩個進程間實現(xiàn)共享一個整數(shù)了。當(dāng)然,在實際應(yīng)用中,可以根據(jù)需要創(chuàng)建合適大小的共享內(nèi)存來共享有意義的數(shù)據(jù)。        這里還實現(xiàn)了IMemoryService.Stub的兩個接口getFileDescriptor和setVal,一個用來獲取匿名共享內(nèi)存文件的文件描述符,一個來往匿名共享內(nèi)存文件中寫入一個整數(shù),其中,接口getFileDescriptor的返回值是一個

92、ParcelFileDescriptor。在Java中,是用FileDescriptor類來表示一個文件描述符的,而ParcelFileDescriptor是用來序列化FileDescriptor的,以便在進程間調(diào)用時傳輸。        定義好本地服務(wù)好,就要定義一個Server來啟動這個服務(wù)了。這里定義的Server實現(xiàn)在src/shy/luo/ashmem/Server.java文件中:view plain1. package2.   3. import4. import5. import6. import7. imp

93、ort8.   9. public class Server extends Service   10.     private final static String LOG_TAG =   11.   12.     private MemoryService memoryService =&#

94、160;null;  13.   14.     Override  15.     public IBinder onBind(Intent intent)   16.         return null;  17.      

95、60;18.   19.     Override  20.     public void onCreate()   21.     Log.i(LOG_TAG, "Create Memory Service.");  22.   23.     memor

96、yService = new MemoryService();  24.   25.         try   26.             ServiceManager.addService("AnonymousSharedMemory", memoryServi

97、ce);  27.             Log.i(LOG_TAG, "Succeed to add memory service.");  28.          catch (RuntimeException ex)   

98、;29.             Log.i(LOG_TAG, "Failed to add Memory Service.");  30.             ex.printStackTrace();  31.   

99、60;       32.   33.       34.   35.     Override  36.     public void onStart(Intent intent, int startId)   37.   &

100、#160;     Log.i(LOG_TAG, "Start Memory Service.");  38.       39.   40.     Override  41.     public void onDestroy()   42. &

101、#160;   Log.i(LOG_TAG, "Destroy Memory Service.");  43.       44.           這個Server繼承了Android系統(tǒng)應(yīng)用程序框架層提供的Service類,當(dāng)它被啟動時,運行在一個獨立的進程中。當(dāng)這個Server被啟動時,它的onCreate函數(shù)就會被調(diào)用,然后它就通過ServiceManage

102、r的addService接口來添加MemoryService了:view plain1. memoryService = new MemoryService();  2.   3. try   4.     ServiceManager.addService("AnonymousSharedMemory", memoryService);  5.     Log.i(

103、LOG_TAG, "Succeed to add memory service.");  6.  catch (RuntimeException ex)   7.     Log.i(LOG_TAG, "Failed to add Memory Service.");  8.    

104、60;ex.printStackTrace();  9.          這樣,當(dāng)這個Server成功啟動了,Client就可以通過ServiceManager的getService接口來獲取這個MemoryService了。       接著,我們就來看Client端的實現(xiàn)。Client端是一個Activity,實現(xiàn)在src/shy/luo/ashmem/Client.java文件中:view plain1. package2.   3. import

105、4. import5.   6. import7. import8. import9. import10. import11. import12. import13. import14. import15. import16. import17. import18. import19.   20. public class Client extends Activity implements OnClickListener   21.   

106、60; private final static String LOG_TAG =   22.       23.     IMemoryService memoryService = null;  24.     MemoryFile memoryFile = null; &#

107、160;25.       26.     private EditText valueText = null;  27.     private Button readButton = null;  28.     private Button writeButton 

108、;= null;  29.     private Button clearButton = null;  30.       31.         Override  32.         public void&

109、#160;onCreate(Bundle savedInstanceState)   33.             super.onCreate(savedInstanceState);  34.35.   36.         IMemoryService ms = getMemor

110、yService();  37.         if(ms = null)           38.                 startService(new Intent(); 

111、; 39.          else   40.             Log.i(LOG_TAG, "Memory Service has started.");  41.        

112、60;  42.   43.44.45.46.47.   48.         readButton.setOnClickListener(this);  49.             writeButton.setOnClickListener(this);  50.   

113、          clearButton.setOnClickListener(this);  51.           52.             Log.i(LOG_TAG, "Client Activity 

114、;Created.");  53.           54.   55.         Override  56.         public void onResume()   57.   &

115、#160;     super.onResume();  58.   59.         Log.i(LOG_TAG, "Client Activity Resumed.");  60.           61.   62. 

116、0;       Override  63.         public void onPause()   64.         super.onPause();  65.   66.       

117、;  Log.i(LOG_TAG, "Client Activity Paused.");  67.           68.       69.         Override  70.     

118、0;   public void onClick(View v)   71.             if(v.equals(readButton)   72.                 int

119、 val = 0;  73.               74.                 MemoryFile mf = getMemoryFile();  75.   &

120、#160;             if(mf != null)   76.                 try   77.         &#

121、160;               byte buffer = new byte4;  78.                         mf

122、.readBytes(buffer, 0, 0, 4);  79.                   80.                      

123、60;  val = (buffer0 << 24) | (buffer1 & 0xFF) << 16) | (buffer2 & 0xFF) << 8) | (buffer3 & 0xFF);  81.         

124、;         catch(IOException ex)   82.                     Log.i(LOG_TAG, "Failed to read bytes from 

125、memory file.");  83.                     ex.printStackTrace();  84.                  

126、 85.                      86.               87.             

127、    String text = String.valueOf(val);  88.                 valueText.setText(text);  89.             

128、60;else if(v.equals(writeButton)   90.                 String text = valueText.getText().toString();  91.            

129、60;    int val = Integer.parseInt(text);  92.               93.                 IMemoryService ms

130、60;= getMemoryService();  94.                 if(ms != null)   95.                 try  &#

131、160;96.                         ms.setValue(val);  97.                  catch(RemoteE

132、xception ex)   98.                     Log.i(LOG_TAG, "Failed to set value to memory service.");  99.     

133、;                ex.printStackTrace();  100.                   101.         

134、0;         102.              else if(v.equals(clearButton)   103.                 String&#

135、160;text = ""  104.                 valueText.setText(text);  105.               106.     

136、      107.       108.         private IMemoryService getMemoryService()   109.             if(memoryService !=

137、 null)   110.                 return memoryService;  111.               112.       &#

138、160;   113.114.                             ServiceManager.getService("AnonymousSharedMemory");  115.   116.  

139、       Log.i(LOG_TAG, memoryService != null ? "Succeed to get memeory service." : "Failed to get memory service.");  117.       &#

140、160;   118.             return memoryService;  119.           120.       121.         priv

141、ate MemoryFile getMemoryFile()   122.             if(memoryFile != null)   123.                 return memoryFile;  124.               125.               126.   

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論