一、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调用接口分析的更多相关文章

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

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6666491 在前面一篇文章Android系统匿 ...

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

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共 ...

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

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6939890 在Android系统中,针对移动设 ...

  4. 【并行计算-CUDA开发】关于共享内存(shared memory)和存储体(bank)的事实和疑惑

    关于共享内存(shared memory)和存储体(bank)的事实和疑惑 主要是在研究访问共享内存会产生bank conflict时,自己产生的疑惑.对于这点疑惑,网上都没有相关描述, 不管是国内还 ...

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

    共享内存(shared memory)是位于SM上的on-chip(片上)一块内存,每个SM都有,就是内存比较小,早期的GPU只有16K(16384),现在生产的GPU一般都是48K(49152). ...

  6. 共享内存(shared memory)

    共享内存指在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存.由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache). 任何一个缓存的数据被更新后,由于其他处理 ...

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

    在https://www.cnblogs.com/xiaoxiaoyibu/p/11402607.html中介绍了使用一个包含N个线程的线程块和共享内存进行数组归约求和, 基本思路: 定义M个包含N个 ...

  8. IPC最快的方式----共享内存(shared memory)

    在linux进程间通信的方式中,共享内存是一种最快的IPC方式.因此,共享内存用于实现进程间大量的数据传输,共享内存的话,会在内存中单独开辟一段内存空间,这段内存空间有自己特有的数据结构,包括访问权限 ...

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

    Fresco的内存机制 Fresco是Facebook出品的高性能图片加载库,采用了Ashmem匿名共享内存机制, 来解决图片加载中的OOM问题.这里不对Fresco做深入分析,只关注Fresco在A ...

随机推荐

  1. zabbix 3.2 高可用实现方式一,亲测无坑

    1.架构设计图 2.设计说明 1. 基础架构为LAMP环境,采用keepalived实现zabbix服务器高可用,保证主server的mysql或者httpd宕掉后能切换到从server. 2.数据库 ...

  2. 第一数学归纳法 vs 第二数学归纳法 vs 良序定理

    相关: 第一数学归纳法 vs 第二数学归纳法 vs 良序定 第二数学归纳法:硬币问题和堆垛游戏 第一数学归纳法:施塔特中心的地板砖 良序原理:算术基本定理的证明 From : Mathematics ...

  3. 整数中1出现的次数(从1到n的整数中1出现的次数)

    题目 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了.AC ...

  4. Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0,"解决办法

    这是因为先安装了 .NET Framework 4,随后启用了 .NET Framework 3.5 WCF HTTP 激活,则会发生此错误. 只需要已管理员用户在cmd中运行aspnet_regii ...

  5. .Net 中通用的FormatString格式符整理

    格式化日期和数字的字符串经常要用到这个, 就把帮助里面的东西大概整理了一些列在这里了. 下表描述了用来格式化 DateTime 对象的标准格式说明符.格式说明符 名称 说明 d 短日期模式 显示由与当 ...

  6. File I/O

    File I/O Introduction     We'll start our discussion of the UNIX System by describing the functions ...

  7. eclipse项目中丢失的R包找回方法

    当我们项目中的R文件丢失的时候会令我们痛苦不已,怎样找回呢?总不能删了吧,那样心血会毁于一旦的,我们肯定不会那样做,那要怎么办呢?我这里提供三种方法: ​一,一般情况下这样: ​    ​方法一:选中 ...

  8. jvm内存区域与内存溢出

    java内存 java动态运行时区域包括:方法区.虚拟机栈.本地方法栈.堆.程序计数器,如右图所示:   程序计数器 程序计数器用来标识要执行的代码的行号,为线程私有   虚拟机栈 为线程所私有 虚拟 ...

  9. Mac OS X更新VirtualBox以后Genymotion无法启动的一种情况

    这两天VirtualBox更新到5.0了,于是乎就升级了.结果升级后就中了个大奖,Genymotion起不来了.我用的是Genymotion 2.5,不久前刚升级的,因为官网打不开,不知是不是最新版. ...

  10. NPM install -save 和 -save-dev 傻傻分不清

    本文原文地址:https://www.limitcode.com/detail/59a15b1a69e95702e0780249.html 回顾 npm install 命令 最近在写Node程序的时 ...