Android系統匿名共用記憶體(Anonymous Shared Memory)Java調用介面分析

來源:互聯網
上載者:User

標籤:才幹   pause   uos   state   detail   file   android系統   arc   add   

一、Ashmem驅動程式

      ~/Android/kernel/goldfish

      ----include

              ----linux

                       ----ashmem.h

      ----mm

              ----ashmem.c

      驅動程式具體解釋請看《Android系統源碼情景分析》。作者羅昇陽。


二、執行時庫cutils的匿名共用記憶體訪問介面

      ~/Android/system/core

      ----libcutils

               ----ashmem-dev.c

       具體解釋請看《Android系統源碼情景分析》,作者羅昇陽。


三、MemoryFile

      ~/Android/frameworks/base/core/java/android/os

      ----MemoryFile.java

      ~/Android/frameworks/base/core/jni

      ----android_os_MemoryFile.cpp

      具體解釋請看《Android系統源碼情景分析》,作者羅昇陽。

      ~/Android/frameworks/base/core/java/android/os

      ----MemoryFile.java

    public ParcelFileDescriptor getParcelFileDescriptor() throws IOException {        FileDescriptor fd = getFileDescriptor();        return fd != null ?

new ParcelFileDescriptor(fd) : null; } ....... public FileDescriptor getFileDescriptor() throws IOException { return mFD; }


四、應用執行個體

      具體解釋請看《Android系統源碼情景分析》,作者羅昇陽。

      在本節中。我們將建立一個Android應用程式Ashmem。它由一個Service組件Server和一個Activity組件Client組成。Server組件執行在一個獨立的進程中,它內部有一個記憶體訪問服務MemoryService,後者通過MemoryFile類建立一塊匿名共用記憶體。

Client組件執行在還有一個進程中,它會將記憶體訪問服務MemoryService建立的那塊匿名共用記憶體映射到本進程的地址空間,以便能夠訪問它的內容,從而能夠和Server組件共用一塊匿名共用記憶體。

      ~/Android/packages/experimental/Ashmem

      ----AndroidManifest.java

      ----Android.mk

      ----src

             ----shy/luo/ashmem

                            ----IMemoryService.java

                            ----MemoryService.java

                            ----Server.java

                            ----Client.java

      ----res

             ----layout

                      ----main.xml

             ----values

                      ----strings.xml

             ----drawable

                      ----icon.png


      IMemoryService.java

package shy.luo.ashmem;import android.util.Log;import android.os.IInterface;import android.os.Binder;import android.os.IBinder;import android.os.Parcel;import android.os.ParcelFileDescriptor;import android.os.RemoteException;public interface IMemoryService extends IInterface {public static abstract class Stub extends Binder implements IMemoryService {private static final String DESCRIPTOR = "shy.luo.ashmem.IMemoryService";public Stub() {attachInterface(this, DESCRIPTOR);}public static IMemoryService asInterface(IBinder obj) {if (obj == null) {return null;}IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);if (iin != null && iin instanceof IMemoryService) {return (IMemoryService)iin;}return new IMemoryService.Stub.Proxy(obj);}public IBinder asBinder() {return this;}@Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {switch (code) {case INTERFACE_TRANSACTION: {reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_getFileDescriptor: {data.enforceInterface(DESCRIPTOR);ParcelFileDescriptor result = this.getFileDescriptor();reply.writeNoException();if (result != null) {reply.writeInt(1);result.writeToParcel(reply, 0);} else {reply.writeInt(0);}return true;}case TRANSACTION_setValue: {data.enforceInterface(DESCRIPTOR);int val = data.readInt();setValue(val);reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements IMemoryService {private IBinder mRemote;Proxy(IBinder remote) {mRemote = remote;}public IBinder asBinder() {return mRemote;}public String getInterfaceDescriptor() {return DESCRIPTOR;}public ParcelFileDescriptor getFileDescriptor() throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();ParcelFileDescriptor result;try {data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getFileDescriptor, data, reply, 0);reply.readException();if (0 != reply.readInt()) {result = ParcelFileDescriptor.CREATOR.createFromParcel(reply);} else {result = null;}} finally {reply.recycle();data.recycle();}return result;}public void setValue(int val) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();try {data.writeInterfaceToken(DESCRIPTOR);data.writeInt(val);mRemote.transact(Stub.TRANSACTION_setValue, data, reply, 0);reply.readException();} finally {reply.recycle();data.recycle();}}}static final int TRANSACTION_getFileDescriptor = IBinder.FIRST_CALL_TRANSACTION + 0;static final int TRANSACTION_setValue = IBinder.FIRST_CALL_TRANSACTION + 1;}public ParcelFileDescriptor getFileDescriptor() throws RemoteException;public void setValue(int val) throws RemoteException;}

      MemoryService.java

package shy.luo.ashmem;import java.io.FileDescriptor;import java.io.IOException;import android.os.Parcel;import android.os.MemoryFile;import android.os.ParcelFileDescriptor;import android.util.Log;public class MemoryService extends IMemoryService.Stub {private final static String LOG_TAG = "shy.luo.ashmem.MemoryService";private MemoryFile file = null;public MemoryService() {try {                        file = new MemoryFile("Ashmem", 4);                        setValue(0);                }                catch(IOException ex) {                        Log.i(LOG_TAG, "Failed to create memory file.");                        ex.printStackTrace();                }}public ParcelFileDescriptor getFileDescriptor() {Log.i(LOG_TAG, "Get File Descriptor.");ParcelFileDescriptor pfd = null;try {pfd = file.getParcelFileDescriptor();} catch(IOException ex) {Log.i(LOG_TAG, "Failed to get file descriptor.");ex.printStackTrace();}return pfd;}public void setValue(int val) {if(file == null) {return;}byte[] buffer = new byte[4];   buffer[0] = (byte)((val >>> 24) & 0xFF);buffer[1] = (byte)((val >>> 16) & 0xFF);buffer[2] = (byte)((val >>> 8) & 0xFF); buffer[3] = (byte)(val & 0xFF);try {file.writeBytes(buffer, 0, 0, 4);Log.i(LOG_TAG, "Set value " + val + " to memory file. ");}catch(IOException ex) {Log.i(LOG_TAG, "Failed to write bytes to memory file.");ex.printStackTrace();}}}

      Server.java

package shy.luo.ashmem;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.util.Log;import android.os.ServiceManager;public class Server extends Service {    private final static String LOG_TAG = "shy.luo.ashmem.Server";    private MemoryService memoryService = null;    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {Log.i(LOG_TAG, "Create Memory Service...");memoryService = new MemoryService();        try {            ServiceManager.addService("AnonymousSharedMemory", memoryService);            Log.i(LOG_TAG, "Succeed to add memory service.");        } catch (RuntimeException ex) {            Log.i(LOG_TAG, "Failed to add Memory Service.");            ex.printStackTrace();        }    }    @Override    public void onStart(Intent intent, int startId) {        Log.i(LOG_TAG, "Start Memory Service.");    }    @Override    public void onDestroy() {Log.i(LOG_TAG, "Destroy Memory Service.");    }}

      Client.java

package shy.luo.ashmem;import java.io.FileDescriptor;import java.io.IOException;import shy.luo.ashmem.R;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.MemoryFile;import android.os.ParcelFileDescriptor;import android.os.ServiceManager;import android.os.RemoteException;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;public class Client extends Activity implements OnClickListener {private final static String LOG_TAG = "shy.luo.ashmem.Client";IMemoryService memoryService = null;MemoryFile memoryFile = null;private EditText valueText = null;private Button readButton = null;private Button writeButton = null;private Button clearButton = null;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);IMemoryService ms = getMemoryService();if(ms == null) {                startService(new Intent("shy.luo.ashmem.server"));} else {Log.i(LOG_TAG, "Memory Service has started.");}        valueText = (EditText)findViewById(R.id.edit_value);        readButton = (Button)findViewById(R.id.button_read);        writeButton = (Button)findViewById(R.id.button_write);        clearButton = (Button)findViewById(R.id.button_clear);readButton.setOnClickListener(this);        writeButton.setOnClickListener(this);        clearButton.setOnClickListener(this);                Log.i(LOG_TAG, "Client Activity Created.");    }    @Override    public void onResume() {super.onResume();Log.i(LOG_TAG, "Client Activity Resumed.");    }    @Override    public void onPause() {super.onPause();Log.i(LOG_TAG, "Client Activity Paused.");    }        @Override    public void onClick(View v) {    if(v.equals(readButton)) {    int val = 0;        MemoryFile mf = getMemoryFile();    if(mf != null) {try {    byte[] buffer = new byte[4];    mf.readBytes(buffer, 0, 0, 4);        val = (buffer[0] << 24) | ((buffer[1] & 0xFF) << 16) | ((buffer[2] & 0xFF) << 8) | (buffer[3] & 0xFF);} catch(IOException ex) {Log.i(LOG_TAG, "Failed to read bytes from memory file.");ex.printStackTrace();}    }        String text = String.valueOf(val);    valueText.setText(text);    } else if(v.equals(writeButton)) {    String text = valueText.getText().toString();    int val = Integer.parseInt(text);        IMemoryService ms = getMemoryService();    if(ms != null) {try {    ms.setValue(val);} catch(RemoteException ex) {Log.i(LOG_TAG, "Failed to set value to memory service.");ex.printStackTrace();}    }    } else if(v.equals(clearButton)) {    String text = "";    valueText.setText(text);    }    }        private IMemoryService getMemoryService() {    if(memoryService != null) {    return memoryService;    }        memoryService = IMemoryService.Stub.asInterface(                ServiceManager.getService("AnonymousSharedMemory"));Log.i(LOG_TAG, memoryService != null ? "Succeed to get memeory service." : "Failed to get memory service.");        return memoryService;    }        private MemoryFile getMemoryFile() {    if(memoryFile != null) {    return memoryFile;    }        IMemoryService ms = getMemoryService();    if(ms != null) {try {    ParcelFileDescriptor pfd = ms.getFileDescriptor();if(pfd == null) {Log.i(LOG_TAG, "Failed to get memory file descriptor.");return null;}try {FileDescriptor fd = pfd.getFileDescriptor();if(fd == null) {Log.i(LOG_TAG, "Failed to get memeory file descriptor.");return null;                      }    memoryFile = new MemoryFile(fd, 4, "r");} catch(IOException ex) {Log.i(LOG_TAG, "Failed to create memory file.");ex.printStackTrace();}    } catch(RemoteException ex) {Log.i(LOG_TAG, "Failed to get file descriptor from memory service.");ex.printStackTrace();}}        return memoryFile;    }}

       首先開始在Activity,onCreate時開啟了Service。然後點擊讀按鈕,執行相應代碼。

       處理序間通訊具體步驟,臨時省略,僅僅看錶明的步驟,見:


      接下來的分析,請看Android系統匿名共用記憶體Ashmem(Anonymous Shared Memory)在進程間共用的原理分析http://blog.csdn.net/luoshengyang/article/details/6666491。

       注意上文中的這句話,  這裡, 我們須要關注的便是虛線框部分了,它在Binder驅動程式中實現了在兩個進程中共用同一個開啟檔案的方法。我們知道。在Linux系統中,檔案描寫敘述符事實上就是一個整數。每個進程在核心空間都有一個開啟檔案的數組,這個檔案描寫敘述符的整數值就是用來索引這個數組的。並且,這個檔案描寫敘述符僅僅是在本進程內有效,也就是說。在不同的進程中,同樣的檔案描寫敘述符的值。代表的可能是不同的開啟檔案。因此。在進程間傳輸檔案描寫敘述符時,不能簡要地把一個檔案描寫敘述符從一個進程傳給另外一個進程。中間必須做一過轉換。使得這個檔案描寫敘述在目標進程中是有效,並且它和源進程的檔案描寫敘述符所相應的開啟檔案是一致的。這樣才幹保證共用。

         也就是依據fd。得到的file結構,在兩個進程是一樣的。即使兩個進程的fd不一樣。

Android系統匿名共用記憶體(Anonymous Shared Memory)Java調用介面分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.