標籤:才幹 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調用介面分析