android内存管理(二)

匿名内存共享

匿名内存映射简单介绍
Anonymous Shared Memory是Android特有的内存共享机制,它是基于linxus共享内存而改进的,它可以将指定的物理内存分别映射到各个进程自己的虚拟的地址空间中,从而便捷地实现进程间的内存共享。
在内存映射中,主要涉及到的函数是为mmap()函数,其函数定义如下:
#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

这mmap函数里有多个参数,其中addr代表文件被映射的开始地址(这个地址相对于进程空间来说),这个通常为空,由系统去决定开始地址,len内存映射长度,prot代表读写权限,flags代表共享权限,fd描述符,offset文件映射偏移量,整个映射结构如图:
这里写图片描述
引用内存映射对象,会三种情况:

  • 在文件映射长度之内的引用
  • 在文件映射长度之外但却在文件内存映射区之内的引用
  • 在文件没有映射的内存区之外的引用

这三个区域如图所示:
这里写图片描述
第一种情况:在文件映射长度之内,对其映射内存的数据改写,都会在操作结束后(产生一个SIGSEGV信号通知系统)同步到文件中。
第二种情况:在对其文件映射长度之内的映射内存的数据改写会同步到文件中,而在其外的数据改写就不会同步到文件中。
第三种情况:对其文件没有映射的内存区之外的引用会因其系统产生一个SIGBUS信号而中断程序。
假设:文件大小的为5000B,内存映射块也设置5000B,虚拟内存的每一页大小设置为8192B,并让文件全部映射到内存映射快中,其映射过程和引用结果就如图所示:
这里写图片描述
又假设:文件大小依然为5000B,内存映射快设置为15000B,虚拟内存的每一页大小设置为8192B,并让文件全部映射到内存映射快中,其映射过程和引用结果就如图所示:
这里写图片描述
关于linxus的进程间内存共享通讯的简单介绍及实例,请参考下面这两篇博客:
http://blog.csdn.net/ljianhui/article/details/10253345
http://www.cnblogs.com/wwwjieo0/p/3758023.html
匿名共享内存创建过程
android在应用层通过frameworks\base\core\java\android\os下的MemoryFile文件来创建匿名内存映射的。

 /**
     * Allocates a new ashmem region. The region is initially not purgable.
     *
     * @param name optional name for the file (can be null).
     * @param length of the memory file in bytes.
     * @throws IOException if the memory file could not be created.
     */
    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;
        }
    }

从这个构造方法我们可以知道,Android其实调用了本地的方法创建匿名共享内存,其本地方法在frameworks\base\core\jni目录下的android_os_MemoryFile.cpp,其源码如下:

static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
{
    //将Java字符串转换C语言char*类型
    const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
    //创建文件内存映射块
    int result = ashmem_create_region(namestr, length);
    //释放Java字符对象的内存
    if (name)
        env->ReleaseStringUTFChars(name, namestr);
    if (result < 0) {
        jniThrowException(env, "java/io/IOException", "ashmem_create_region failed");
        return NULL;
    }
    //返回文件描述符(相当于操作文件的指针)
    return jniCreateFileDescriptor(env, result);
}

static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, 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;
}

从这个文件来看,它调用了系统内核底层的方法创建了内存,其文件在Linux/drivers/staging/android/ashmem.c。

 static int __init ashmem_init(void)
{
        int ret;
         //创建缓存内存
         ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
                                           sizeof(struct ashmem_area),
                                           0, 0, NULL);
         if (unlikely(!ashmem_area_cachep)) {
                 pr_err("failed to create slab cache\n");
                return -ENOMEM;
         }
         //创建缓存内存
         ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
                                           sizeof(struct ashmem_range),
                                           0, 0, NULL);
         if (unlikely(!ashmem_range_cachep)) {
                 pr_err("failed to create slab cache\n");
                 return -ENOMEM;
         }

         //注册初始化信息
         ret = misc_register(&ashmem_misc);
        if (unlikely(ret)) {
                 pr_err("failed to register misc device!\n");
                 return ret;
         }      
        //注册回收算法
         register_shrinker(&ashmem_shrinker);

         pr_info("initialized\n");

         return 0;
 }

分配文件内存的源码:

/**
 * ashmem_open() - Opens an Anonymous Shared Memory structure
 * @inode:     The backing file's index node(?)
 * @file:      The backing file
 *
 * Please note that the ashmem_area is not returned by this function - It is
 * instead written to "file->private_data".
 *
 * Return: 0 if successful, or another code if unsuccessful.
 */
static int ashmem_open(struct inode *inode, struct file *file)
{
    struct ashmem_area *asma;
    int ret;    
    ret = generic_file_open(inode, file);
    if (unlikely(ret))
        return ret;
    //分配文件内存大小
    asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL);
    if (unlikely(!asma))
        return -ENOMEM;
    //对分配的内存做一些初始化操作
    INIT_LIST_HEAD(&asma->unpinned_list);
    memcpy(asma->name, ASHMEM_NAME_PREFIX, ASHMEM_NAME_PREFIX_LEN);
    asma->prot_mask = PROT_MASK;
    file->private_data = asma;

    return 0;
}

映射内存到进程空间的源码:

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);

    /* user needs to SET_SIZE before mapping */
    if (unlikely(!asma->size)) {
        ret = -EINVAL;
        goto out;
    }

    /* requested protection bits must match our allowed protection mask */
    if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask)) &
             calc_vm_prot_bits(PROT_MASK))) {
        ret = -EPERM;
        goto out;
    }
    vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_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_ERR(vmfile))) {
            ret = PTR_ERR(vmfile);
            goto out;
        }
        asma->file = vmfile;
    }
    get_file(asma->file);

    /*
     * XXX - Reworked to use shmem_zero_setup() instead of
     * shmem_set_file while we're in staging. -jstultz
     */
    if (vma->vm_flags & VM_SHARED) {
    //内存映射并初始化内存的数据为0
        ret = shmem_zero_setup(vma);
        if (ret) {
            fput(asma->file);
            goto out;
        }
    }

    if (vma->vm_file)
        fput(vma->vm_file);
    vma->vm_file = asma->file;

out:
//释放锁
    mutex_unlock(&ashmem_mutex);
    //返回文件内存映射进程空间的开始地址
    return ret;
}

参考资料:
http://notjustburritos.tumblr.com/post/21442138796/an-introduction-to-android-shared-memory
https://vec.io/posts/andriod-ipc-shared-memory-with-ashmem-memoryfile-and-binder

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值