Anonymous Shared Memory android 匿名共享内存
原址
两个特点:
- 能够辅助内存管理系统来有效的管理不再使用的内存块
- 通过Binder进程间通信机制来实现进程间的内存共享。
Android系统的匿名共享内存子系统的主体是以驱动程序的形式实现在内核空间的。
应用程序框架层的Java调用接口是通过JNI方法来调用库层的C/C++调用接口
android应用程序框架层提供了一个MemoryFile接口来封装了匿名共享内存文件的创建和使用
它实现在frameworks/base/core/java/android/os/MemoryFIle.java
文件中
MemoryFile.java 的构造函数:(两种创建匿名共享内存的方法)
public class MemoryFile {...public MemoryFile(String name, int length) throws IOException {mLength = length;mFD = native_open(name, length);mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);mOwnsRegion = true;}...public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException {if (fd == null) {throw new NullPointerException("File descriptor is null")}if (!isMemoryFile(fd)) {throw new ILlegalArgumentException("Not a memory file.");}mLength = length;mFD = fd;mAddress = native_mmap(mFD, length, modeToProt(mode));mOwnsRegion = false;}...
}
第一种方法是以指定的字符串调用jni方法native_open()
来创建一个匿名共享内存文件,得到mFD
文件描述符, 把其传入进native_mmap()
映射在进程空间中,便可以通过这个映射得到的地址空间来直接访问内存数据。
第二种则是以指定的文件描述符来直接调用JNI方法native_mmap(...)
把这个匿名共享内存文件映射在进程空间中,然后进行访问。要判断该fd是否为匿名共享内存文件的文件描述符isMemoryFile(fd)
具有辅助内存管理系统来有效的管理内存的特点
Ashmem 驱动程序的源代码
ashmem机制是建立在Linux内核实现的共享内存的基础上的,同时向Linux内存管理系统的内存回收算法注册接口,告诉linux内存管理系统它的某些内存块不再使用了,可以被回收了。
MemoryFile接口
创建(open
), 映射(mmap
), 读写(read/write
)以及锁定和解锁(pin/unpin
)四个使用场景
先看Ashmem驱动程序模块的初始化函数
ashmem驱动程序实现在kernel/common/mm/ashmem.c文件中,初始化函数为ashmem_init
static struct file_operations ashmem_fops = {.owner = THIS_MODULE,.open = ashmem_open,.release = ashmem_release,.mmap = ashmem_mmap,.unlocked_ioctl = ashmem_ioctl,.compat_ioctl = ashmem_ioctl,
};static struct miscdevice ashmem_misc = {.minor = MISC_DYNAMIC_MINOR,.name = "ashmem",.fops = &ashmem_fops,
};static int __init ashmem_init(void) {int ret;......ret = misc_register(&ashmem_misc);if (unlikely(ret)) {printk(KERN_ERR "ashmem: failed to register misc device!\n");return ret;}......return 0;
}
匿名共享内存的创建过程(open)
在MemoryFile
第一个构造函数中通过JNI的native_open
来创建,
而这个方法的实现在frameworks/base/core/jni/adroid_os_MemoryFile.cpp
,
在里面又会调用ashmem_create_region()
来创建匿名共享内存,这个函数实现在
system/core/libcutils/ashmem-dev.c
文件中,在region()中会先open,
然后两次ioctl
, open()是打开设备文件ASHMEM_DEVICE, 后面的分别是设置匿名共享内存的名称和大小。
struct ashmem_area
它是Ashmem驱动程序的一个相关数据结构,用于表示一块共享内存。
它的实例都是从自定义的一个slab缓冲区(是在初始化函数创建的)创建的
在region函数里面(open函数):
//执行打开文件的操作
fd = open(ASHMEM_DIVICE, O_RDWR);
//ASHMEM_DIVICE是个宏,定义为: #define ASHMEM_DIVICE "/dev/ashmem"(共享内存设备文件)
iconl函数:
//调用两次iconl,匿名共享内存的名称和大小
//在kernel/common/mm/include/ashmem.h文件中,
#define ASHMEM_NAME_LEN 256
#define __ASHMEMIOC 0x77
#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEK])
#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
ASHMEM_SET_NAME 命令的iconl调用,最终进入到Ashmem驱动程序的ashmem_iconl函数中, 依次调用set_name()
,将名字映射到asma->name
中;
同理ASHMEME_SET_SIZE,将大小保存在对应的asma->size
域中
ashmem的创建完成
ashmem 的内存映射操作(mmap)
在MemoryFile
类的构造函数中, 进行了匿名共享内存的创建操作后,然后就是要把匿名共享内存设备文件映射到空间中:
public class MemoryFile {private static native int native_mmap(FileDescriptor fd, int length, int mode) throws IOException;...
}
映射是通过JNI方法native_mmap
来进行的,它的实现是在android_os_MemoryFile.cpp
:
static jint android_os_MemoryFile_mmap(JNIEnv * env, jobject clazz, jobject, jobject fileDescriptor jint length, jint prot) {int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);if (!result) {jniThrowException(env, "java/io/IOException", "mmap failed");}return result;
}
fd是在签名open匿名设备文件/dev/ashmem获得的, 有这个文件描述符后,就可以直接通过mmap来执行内存映射操作了。最后调用进入到Ashmem驱动程序的ashmem_mmap
函数中:
static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) {struct ashmem_area *asma = file -> private_data;int ret = 0;mutex_lock(&ashmem_mutex);//if (unlikely(!asma->size)) {rt = -EINVAL;goto out;}//if (unlikely((vma->vm_falags & ~asma->prot_mask) & PROT_MASK)) {ret = -EPERM;goto out;}/*requested protection bits must match our allowed protection mask*/if (!asma-> file) {char *name = ASHMEM_NAME_DEF;struct file *vmfile;//if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0')name = asma -> name;/* 主要函数 ...and allocate the backing shmem file */vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);if (unlikely(IS_EFR(vmfile))) {ret = PTR_ERR(vmfile);goto out;}asma->file = vmfile;}get_file(asma->file);if (vma->vm_flags & VM_SHARED)shmem_set_file(vma, asma->file);else {if (vma->vm_file)fput(vma->vm_file)vma->vm_file = asma->file;}vma->vm_flags |= VM_CAN_NONLINEAR;
out:mutex_unlock(&ashmem_mutex);return ret;
}
调用了Linux 内核提供的shmem_file_setup 函数来在临时文件系统tmpfs中创建一个临时文件a,
a与Ashmem驱动程序创建的匿名共享内存对应。
Linux 内核中的共享内存机制其实是一种进程间通信机制(IPC)
通过shmem_file_setup
函数创建的临时文件vmfile最终保存在vma->file中。
vma是struct vm_area_struct
类型,表示的是当前进程空间中一块连续的虚拟地址空间
同时这个临时文件vmfile
也会保存在asma->file
域中, 这样Ashmem
驱动程序就可以通过
asma->file
来操作这个匿名共享文件了。
函数ashmem_mmap
执行完成后,经过层层返回到JNI方法native_mmap
中去,后面,共享内存的读写操作就是对这个地址空间进行操作了。
匿名共享内存的读写操作
MemoryFile
的匿名共享内存读写操作都是通过JNI方法来实现的,读操作和写操作的JNI方法分别是: native_read
和native_write
.
因为前面的mmap得到了文件的地址,所以可直接进行访问,不必进入到Ashmem驱动程序中去。
这也是Ashmem
没有提供read
和write
文件操作的原因.
其中利用到了ashmem_pin_region
和ashmem_unpin_region
两个函数是系统运行时库提供的接口,用来执行匿名共享内存的锁定和解锁操作。
匿名共享内存的锁定和解锁
它们的作用是告诉Ashmem驱动程序,它的哪些内存块是正在使用的,需要锁定,哪些内存是不需要使用了,可以让它解锁。
这样,Ashmem驱动程序就可以辅助内存管理系统来有效地管理内存了
实现在system/core/libcutils/ashmem/ashmem-dev.c
文件中:
int ashmem_pin_region(int fd, size_t offset, size_t len) {struct ashmem_pin pin = { offser, len };return ioctl(fd, ASHMEM_PIN, &pin);
}
//
int ashmem_unpin_region(int fd, size_t offset, size_t len) {struct ashmem_pin pin = { offser, len };return ioctl(fd, ASHMEM_UNPIN, &pin);
}
它们的实现很简单,由ASHMEM_PIN和ASHMEM_UNPIN 两个ioctl 操作来实现匿名共享内存的锁定和解锁操作。
它们定义在kernel/common/include/linux/ashmem.h
文件中
#define __ASHMEMIOC 0x77#define ASHMEM_PIN _IOW(__ASHMEMIOC, 7, struct ashmem_pin)
#define ASHMEM)UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin)
参数类型为struct ashmem_pin
, 定义在这个文件下:
struct ashmem_pin {__u32 offset;__u32 len;
};
这个结构体中只有两个域, 分别表示要锁定或者要解锁的内存块的起始大小以及大小。
搜索unpinnd
Anonymous Shared Memory android 匿名共享内存相关推荐
- Android 匿名共享内存Java接口分析
原址 在Android 匿名共享内存驱动源码分析中介绍了匿名共享内存的驱动实现过程,本文在Android匿名共享内存驱动基础上,介绍Android匿名共享内存对外Android系统的匿名共享内存子系统 ...
- Android 匿名共享内存C++接口分析
原址 在上一篇Android 匿名共享内存C接口分析中介绍了Android系统的匿名共享内存C语言访问接口,本文在前文的基础上继续介绍Android系统的匿名共享内存提供的C++访问接口.在C++层通 ...
- Android 匿名共享内存C接口分析
原址 在Android 匿名共享内存驱动源码分析中详细分析了匿名共享内存在Linux内核空间的实现,虽然内核空间实现了匿名共享内存,但仍然需要在用户空间为用户使用匿名共享内存提供访问接口.Androi ...
- Android 匿名共享内存驱动源码分析
原址 Android系统的匿名共享内存Ashmem驱动程序利用了Linux的共享内存子系统导出的接口来实现,本文通过源码分析方式详细介绍Android系统的匿名共享内存机制.在Android系统中,匿 ...
- 安卓ashmem(匿名共享内存映射)学习native篇
转自:http://blog.csdn.net/u010657219/article/details/41248965 先看看之前三个进程的关系: 由于这里用到了Binder进程间通信机制,这里再次贴 ...
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
在Android系统中,提供了独特的匿名共享内存子系统Ashmem(Anonymous Shared Memory),它以驱动程序的形式实现在内核空间中.它有两个特点,一是能够辅助内存管理系统来有效地 ...
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共 ...
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了 ...
- Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析
出自:http://blog.csdn.net/luoshengyang/article/details/6939890 在Android系统中,针对移动设备内存空间有限的特点,提供了一种在进程间共享 ...
最新文章
- jquery easyui datagrid 排序列
- 009_字符串内建函数
- JZOJ 5820. 【NOIP提高A组模拟2018.8.16】 非法输入
- 近五年计算机网络技术的发展,计算机网络技术的近期发展
- 关于Transformer,面试官们都怎么问?
- 面试官:序列化和反序列化为什么要实现Serializable接口?
- 客户端稳定性优化实战,Crash率最高下降40%
- mysql将一个库中表的某几个字段插入到另一个库中的表
- Redis布隆过滤器
- C - Mr. Panda and Strips Gym - 101194C(思维//尺取//2016 icpc china final)
- JVM——Java对象是如何创建、存储和访问的?
- 内存颗粒和闪存颗粒的区别_NAND Flash闪存颗粒与SSD知识深度解析
- 带哨兵节点的链_BNC公链 | IPFS:区块链“不可能三角”的可能解
- 事业单位考试高频考点一:马克思主义基本原理
- android 仿小米便签,高仿小米便签
- 自我怀疑的开发者:你够好吗?
- 赛效:超级简历在线简历助手教您一键制作简历
- 父亲节华为P40软文营销广告
- 实战!双硬盘安装图解!
- windows10系统-12-WPS文档编辑排版
热门文章
- Haproxy配置http模式负载均衡
- oracle_linux安装oracle_12.1.0
- 在线数据库设计ERD-ONLINE
- Keras学习---RNN模型建立篇
- 想要你的HTTP稳定不蹦,必须吃透「负载均衡」
- LUA验证系统PHP,用Nginx+Lua实现高性能、高可靠、安全的登陆验证
- C语言scanf输入a3,【C语言】04 printf和scanf函数
- vb 打开sdf数据_DWG、DGN、SDF、DWF!Civil 3D图形数据共享的几种方法
- BZOJ3529: [Sdoi2014]数表(莫比乌斯反演,离线)
- Python学习 Day8-2 python的三元表达式(三目运算符)、lambda表达式、内置函数