您的位置:首页 > 移动开发 > Android开发

Android MemoryFile 源码分析以及使用

2014-04-30 00:10 423 查看
Android对于I/O操作效率比较低,提高效率的方法可以通过NDK直接进行读写,或者调用MemoryFile.java类对I/O进行处理。

一、MemoryFile.java 源码分析

MemoryFile.java 源码位置:frameworks/base/core/java/android/os/MemoryFile.java

MemoryFile类直接对native方法进行封装,通过JNI调用底层C++方法,下面对具体函数进行分析。

1. 构造函数

public MemoryFile(String name, int length) throws IOException {

mLength = length;

mFD = native_open(name, length);

if (length > 0) {

mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);

} else {

mAddress = 0;

}

}

这里直接调用native方法native_mmap对name文件进行内存映射,这里的native_mmap方法调用JNI方法android_os_MemoryFile_open,这个函数又通过运行库提供的ashmem_create_region来创建内存共享映射,这个函数的实现在system/core/libcutils/ashmem-dev.c中,具体代码如下:

/*

  * ashmem_create_region - creates a new ashmem region and returns the

file

  * descriptor, or <0 on error

  *

  * `name' is an optional label to give the region (visible in

/proc/pid/maps)

  * `size' is the size of the region, in page-aligned bytes

  */

  int ashmem_create_region(const char *name, size_t size)

  {

  int fd, ret;

  fd = open(ASHMEM_DEVICE, O_RDWR); // open函数打开ASHMEM_DEVICE设备文件

  if (fd < 0)

  return fd;

  if (name) {

  char buf[ASHMEM_NAME_LEN];

  strlcpy(buf, name, sizeof(buf));

  ret = ioctl(fd, ASHMEM_SET_NAME, buf);

  if (ret < 0)

  goto error;

  }

  ret = ioctl(fd, ASHMEM_SET_SIZE, size); // 设置匿名共享内存的名称和大小

  if (ret < 0)

  goto error;

  return fd;

  error:

  close(fd);

  return ret;

  }

调用native_mmap函数对打开的设备文件进行映射,调用JNI函数android_os_MemoryFile_mmap,这个函数利用内存映射mmap实现。

2. readBytes
函数

具体源码如下:

public int readBytes(byte[]
buffer, int srcOffset, int destOffset, int count)

throws IOException {

if (isDeactivated()) {

throw new IOException("Can't read from deactivated memory file.");

}

if (destOffset < 0 || destOffset > buffer.length || count < 0

|| count > buffer.length - destOffset

|| srcOffset < 0 || srcOffset > mLength

|| count > mLength - srcOffset) {

throw new IndexOutOfBoundsException();

}

return native_read(mFD, mAddress, buffer, srcOffset, destOffset, count, mAllowPurging);

}

readBytes函数同样调用JNI接口native_read即android_os_MemoryFile_read,通过SetByteArrayRegion进行内存的读取。

3. writeBytes函数


public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count)

throws IOException {

if (isDeactivated()) {

throw new IOException("Can't write to deactivated memory file.");

}

if (srcOffset < 0 || srcOffset > buffer.length || count < 0

|| count > buffer.length - srcOffset

|| destOffset < 0 || destOffset > mLength

|| count > mLength - destOffset) {

throw new IndexOutOfBoundsException();

}

native_write(mFD, mAddress, buffer, srcOffset, destOffset, count, mAllowPurging);

}

这里调用native_write接口,通过android_os_MemoryFile_write
调用GetByteArrayRegion对内存进行写操作。

这两个函数用到了ashmem_pin_region和ashmem_unpin_region是系统运行时库提供的接口,用来执行我们前面说的匿名共享内存的锁定和解锁操作,它们的作用是告诉Ashmem驱动程序,它的哪些内存块是正在使用的,需要锁定,哪些内存是不需要使用了,可以它解锁,这样,Ashmem驱动程序就可以辅助内存管理系统来有效地管理内存了。

二、MemoryFile.java
使用实例

public class MemoryFileTest {

private Context content;

public MemoryFileTest(Context content) {

this.content = content;

}

public void testFileDescriptor() throws Exception {

MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);

byte[] buffer = new byte[testString.length];

// check low level accessors

file.writeBytes(testString, 0, 2000, testString.length);

file.readBytes(buffer, 2000, 0, testString.length);

compareBuffers(testString, buffer, testString.length);

// check streams

buffer = new byte[testString.length];

OutputStream os = file.getOutputStream();

os.write(testString);

InputStream is = file.getInputStream();

is.mark(testString.length);

is.read(buffer);

compareBuffers(testString, buffer, testString.length);

// test mark/reset

buffer = new byte[testString.length];

is.reset();

is.read(buffer);

compareBuffers(testString, buffer, testString.length);

file.close();

}

private void compareBuffers(byte[] buffer1, byte[] buffer2, int length) throws Exception {

for (int i = 0; i < length; i++) {

if (buffer1[i] != buffer2[i]) {

Toast.makeText(content, "readBytes did not read back what writeBytes wrote", Toast.LENGTH_SHORT).show();

}

}

}

private static final byte[] testString = new byte[] {

3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7, 5, 1, 0, 5, 8, 2, 0, 9, 7, 4, 9, 4, 4, 5, 9, 2, 3, 0, 7, 8, 1, 6, 4,

0, 6, 2, 8, 6, 2, 0, 8, 9, 9, 8, 6, 2, 8, 0, 3, 4, 8, 2, 5, 3, 4, 2, 1, 1, 7, 0, 6, 7, 9, 8, 2, 1, 4, 8, 0, 8, 6, 5, 1, 3, 2, 8, 2, 3, 0, 6, 6, 4, 7, 0, 9, 3, 8, 4, 4, 6, 0, 9, 5, 5, 0, 5, 8, 2, 2, 3, 1, 7, 2,

5, 3, 5, 9, 4, 0, 8, 1, 2, 8, 4, 8, 1, 1, 1, 7, 4, 5, 0, 2, 8, 4, 1, 0, 2, 7, 0, 1, 9, 3, 8, 5, 2, 1, 1, 0, 5, 5, 5, 9, 6, 4, 4, 6, 2, 2, 9, 4, 8, 9, 5, 4, 9, 3, 0, 3, 8, 1, 9, 6, 4, 4, 2, 8, 8, 1, 0, 9, 7, 5,

6, 6, 5, 9, 3, 3, 4, 4, 6, 1, 2, 8, 4, 7, 5, 6, 4, 8, 2, 3, 3, 7, 8, 6, 7, 8, 3, 1, 6, 5, 2, 7, 1, 2, 0, 1, 9, 0, 9, 1, 4, 5, 6, 4, 8, 5, 6, 6, 9, 2, 3, 4, 6, 0, 3, 4, 8, 6, 1, 0, 4, 5, 4, 3, 2, 6, 6, 4, 8, 2,

1, 3, 3, 9, 3, 6, 0, 7, 2, 6, 0, 2, 4, 9, 1, 4, 1, 2, 7, 3, 7, 2, 4, 5, 8, 7, 0, 0, 6, 6, 0, 6, 3, 1, 5, 5, 8, 8, 1, 7, 4, 8, 8, 1, 5, 2, 0, 9, 2, 0, 9, 6, 2, 8, 2, 9, 2, 5, 4, 0, 9, 1, 7, 1, 5, 3, 6, 4, 3, 6,

7, 8, 9, 2, 5, 9, 0, 3, 6, 0, 0, 1, 1, 3, 3, 0, 5, 3, 0, 5, 4, 8, 8, 2, 0, 4, 6, 6, 5, 2, 1, 3, 8, 4, 1, 4, 6, 9, 5, 1, 9, 4, 1, 5, 1, 1, 6, 0, 9, 4, 3, 3, 0, 5, 7, 2, 7, 0, 3, 6, 5, 7, 5, 9, 5, 9, 1, 9, 5, 3,

0, 9, 2, 1, 8, 6, 1, 1, 7, 3, 8, 1, 9, 3, 2, 6, 1, 1, 7, 9, 3, 1, 0, 5, 1, 1, 8, 5, 4, 8, 0, 7, 4, 4, 6, 2, 3, 7, 9, 9, 6, 2, 7, 4, 9, 5, 6, 7, 3, 5, 1, 8, 8, 5, 7, 5, 2, 7, 2, 4, 8, 9, 1, 2, 2, 7, 9, 3, 8, 1,

8, 3, 0, 1, 1, 9, 4, 9, 1, 2, 9, 8, 3, 3, 6, 7, 3, 3, 6, 2, 4, 4, 0, 6, 5, 6, 6, 4, 3, 0, 8, 6, 0, 2, 1, 3, 9, 4, 9, 4, 6, 3, 9, 5, 2, 2, 4, 7, 3, 7, 1, 9, 0, 7, 0, 2, 1, 7, 9, 8, 6, 0, 9, 4, 3, 7, 0, 2, 7, 7,

0, 5, 3, 9, 2, 1, 7, 1, 7, 6, 2, 9, 3, 1, 7, 6, 7, 5, 2, 3, 8, 4, 6, 7, 4, 8, 1, 8, 4, 6, 7, 6, 6, 9, 4, 0, 5, 1, 3, 2, 0, 0, 0, 5, 6, 8, 1, 2, 7, 1, 4, 5, 2, 6, 3, 5, 6, 0, 8, 2, 7, 7, 8, 5, 7, 7, 1, 3, 4, 2,

7, 5, 7, 7, 8, 9, 6, 0, 9, 1, 7, 3, 6, 3, 7, 1, 7, 8, 7, 2, 1, 4, 6, 8, 4, 4, 0, 9, 0, 1, 2, 2, 4, 9, 5, 3, 4, 3, 0, 1, 4, 6, 5, 4, 9, 5, 8, 5, 3, 7, 1, 0, 5, 0, 7, 9, 2, 2, 7, 9, 6, 8, 9, 2, 5, 8, 9, 2, 3, 5,

4, 2, 0, 1, 9, 9, 5, 6, 1, 1, 2, 1, 2, 9, 0, 2, 1, 9, 6, 0, 8, 6, 4, 0, 3, 4, 4, 1, 8, 1, 5, 9, 8, 1, 3, 6, 2, 9, 7, 7, 4, 7, 7, 1, 3, 0, 9, 9, 6, 0, 5, 1, 8, 7, 0, 7, 2, 1, 1, 3, 4, 9, 9, 9, 9, 9, 9, 8, 3, 7,

2, 9, 7, 8, 0, 4, 9, 9, 5, 1, 0, 5, 9, 7, 3, 1, 7, 3, 2, 8, 1, 6, 0, 9, 6, 3, 1, 8, 5, 9, 5, 0, 2, 4, 4, 5, 9, 4, 5, 5, 3, 4, 6, 9, 0, 8, 3, 0, 2, 6, 4, 2, 5, 2, 2, 3, 0, 8, 2, 5, 3, 3, 4, 4, 6, 8, 5, 0, 3, 5,

2, 6, 1, 9, 3, 1, 1, 8, 8, 1, 7, 1, 0, 1, 0, 0, 0, 3, 1, 3, 7, 8, 3, 8, 7, 5, 2, 8, 8, 6, 5, 8, 7, 5, 3, 3, 2, 0, 8, 3, 8, 1, 4, 2, 0, 6, 1, 7, 1, 7, 7, 6, 6, 9, 1, 4, 7, 3, 0, 3, 5, 9, 8, 2, 5, 3, 4, 9, 0, 4,

2, 8, 7, 5, 5, 4, 6, 8, 7, 3, 1, 1, 5, 9, 5, 6, 2, 8, 6, 3, 8, 8, 2, 3, 5, 3, 7, 8, 7, 5, 9, 3, 7, 5, 1, 9, 5, 7, 7, 8, 1, 8, 5, 7, 7, 8, 0, 5, 3, 2, 1, 7, 1, 2, 2, 6, 8, 0, 6, 6, 1, 3, 0, 0, 1, 9, 2, 7, 8, 7,

6, 6, 1, 1, 1, 9, 5, 9, 0, 9, 2, 1, 6, 4, 2, 0, 1, 9, 8, 9, 3, 8, 0, 9, 5, 2, 5, 7, 2, 0, 1, 0, 6, 5, 4, 8, 5, 8, 6, 3, 2, 7, 8, 8, 6, 5, 9, 3, 6, 1, 5, 3, 3, 8, 1, 8, 2, 7, 9, 6, 8, 2, 3, 0, 3, 0, 1, 9, 5, 2,

0, 3, 5, 3, 0, 1, 8, 5, 2, 9, 6, 8, 9, 9, 5, 7, 7, 3, 6, 2, 2, 5, 9, 9, 4, 1, 3, 8, 9, 1, 2, 4, 9, 7, 2, 1, 7, 7, 5, 2, 8, 3, 4, 7, 9, 1, 3, 1, 5, 1, 5, 5, 7, 4, 8, 5, 7, 2, 4, 2, 4, 5, 4, 1, 5, 0, 6, 9, 5, 9,

5, 0, 8, 2, 9, 5, 3, 3, 1}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: