Android系统匿名共享内存(Anonymous Shared Memory)Java调用接口分析

一、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不一样。

时间: 2024-10-07 06:00:12

Android系统匿名共享内存(Anonymous Shared Memory)Java调用接口分析的相关文章

Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析

一.Ashmem驱动程序 ~/Android/kernel/goldfish ----include ----linux ----ashmem.h ----mm ----ashmem.c 驱动程序详解请看<Android系统源代码情景分析>,作者罗升阳. 二.运行时库cutils的匿名共享内存访问接口 ~/Android/system/core ----libcutils ----ashmem-dev.c 详解请看<Android系统源代码情景分析>,作者罗升阳. 三.Memory

Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划中, 我们简要介绍了Android系统的匿名共享内存机制,其中,简要提到了它具有辅助内存管理系统来有效地管理内存的特点,但是没有进一步去了解它是如何实 现的.在本文中,我们将通过分析Android系统的匿名共享内存

Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6666491 在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了它是如何辅助内存管理系统来有效地管理内存的,在再前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Share

cuda编程:关于共享内存(shared memory)和存储体(bank)的事实和疑惑

关于共享内存(shared memory)和存储体(bank)的事实和疑惑 主要是在研究访问共享内存会产生bank conflict时,自己产生的疑惑.对于这点疑惑,网上都没有相关描述, 不管是国内还是国外的网上资料.貌似大家都是当作一个事实,一个公理,而没有对其仔细研究.还是我自己才学疏浅,不知道某些知识. 比如下面这篇讲解bank conflict的文章. http://cuda-programming.blogspot.com/2013/02/bank-conflicts-in-share

CUDA学习(五)之使用共享内存(shared memory)进行归约求和

共享内存(shared memory)是位于SM上的on-chip(片上)一块内存,每个SM都有,就是内存比较小,早期的GPU只有16K(16384),现在生产的GPU一般都是48K(49152). 共享内存由于是片上内存,因而带宽高,延迟小(较全局内存而言),合理使用共享内存对程序效率具有很大提升. 下面是使用共享内存对一个数组进行求和,使用全局内存进行归约求和可以浏览https://www.cnblogs.com/xiaoxiaoyibu/p/11397205.html #pragma on

CUDA学习(六)之使用共享内存(shared memory)进行归约求和(M个包含N个线程的线程块)

在https://www.cnblogs.com/xiaoxiaoyibu/p/11402607.html中介绍了使用一个包含N个线程的线程块和共享内存进行数组归约求和, 基本思路: 定义M个包含N个线程的线程块时(NThreadX = ((NX + ThreadX - 1) / ThreadX)),全局线程索引需使用tid = blockIdx.x * blockDim.x + threadIdx.x,而在每个线程块中局部线程索引是i = threadIdx.x, 每个线程块只计算一部分求和,

Fresco内存机制(Ashmem匿名共享内存)

Fresco的内存机制 Fresco是Facebook出品的高性能图片加载库,采用了Ashmem匿名共享内存机制, 来解决图片加载中的OOM问题.这里不对Fresco做深入分析,只关注Fresco在Android Bitmap的管理上采用了哪些黑科技. Android的内存区域 Java Heap(Dalvik Heap),这部分的内存区域是由Dalvik虚拟机管理,通过Java中 new 关键字来申请一块新内存.这块区域的内存是由GC直接管理,能够自动回收内存.这块内存的大小会受到系统限制,当

Android漫游记(1)---内存映射镜像(memory maps)

Android系统内核基于Linux2.6+内核,因此,其在进程内存管理方面的很多机制和Linux是很相像的.首先,让我们来看一个典型的Android进程的内存镜像(App进程和Native本地进程略有差别,但原理是一样的): 和Linux一样,Android提供了基于/proc的"伪文件"系统来作为查看用户进程内存映像的接口(cat /proc/pid/maps).可以说,这是Android系统内核层开放给用户层关于进程内存信息的一扇窗户.通过它,我们可以查看到当前进程空间的内存映射

查看Android 系统单个进程内存、CPU使用情况的几种方法

一.利用Android API函数查看 1.1 ActivityManager查看可用内存. ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo(); am.getMemoryInfo(outInfo); outInfo.availMem即为可用空闲内存. 1.2.Android.os.Debug查询PSS,VSS,USS等单个进程使用内存信息 MemoryInfo[] memoryInfoArray = am.