Android应用层使用共享内存机制进行进程间交换数据

Android应用层使用共享内存机制进行进程间交换数据

Android提供了一个高效的共享内存机制。如果应用中涉及到在多个进程间交换数据时使用Android提高的共享内存机制将会大大的提高效率。但是也许是出于安全考虑,在应用层使用共享内存机制将会遇到很多障碍,这篇文章旨在解决这些障碍

使用共享内存的流程大概是:

在一个进程中创建一个共享内存。在Android应用层中,用MemoryFile描述一块共享内存,创建共享内存其实就是创建一MemoryFile对象。这一步非常简单,MemoryFile提供了相应的构造函数

public MemoryFile(String name, int length) throws IOException

因为这块内存需要让其他进程共享,所以需要取得刚刚创建的共享内存的文件描述符FileDescriptor,并且把序列化成ParcelFileDescriptor。对于获取FileDescriptor,MemoryFile提供了相应的方法

/**
     * Gets a FileDescriptor for the memory file.
     *
     * The returned file descriptor is not duplicated.
     *
     * @throws IOException If the memory file has been closed.
     *
     * @hide
     */
    public FileDescriptor getFileDescriptor() throws IOException {
        return mFD;
    }

可是这个方法是隐藏的,在应用层没法直接调用。所以需要用反射来完成,具体代码如下

/**
     * 获取memoryFile的FileDescriptor
     * @param memoryFile 描述一块共享内存
     * @return 这块共享内存对应的文件描述符
     */
    public static FileDescriptor getFileDescriptor(MemoryFile memoryFile){
        if(memoryFile == null){
            throw new IllegalArgumentException("memoryFile 不能为空");
        }
        FileDescriptor fd;
        fd = (FileDescriptor) ReflectUtil.invoke("android.os.MemoryFile",memoryFile,"getFileDescriptor");
        return fd;
    }

对于把FileDescriptor序列化成ParcelFileDescriptor,ParcelFileDescriptor也提供了一隐藏的构造函数:

/** {@hide} */
    public ParcelFileDescriptor(FileDescriptor fd) {
        this(fd, null);
    }

所以我们还是可以通过反射来实现:

/**
     * 获取memoryFile的ParcelFileDescriptor
     * @param memoryFile 描述一块共享内存
     * @return ParcelFileDescriptor
     */
    public static ParcelFileDescriptor getParcelFileDescriptor(MemoryFile memoryFile){
        if(memoryFile == null){
            throw new IllegalArgumentException("memoryFile 不能为空");
        }
        ParcelFileDescriptor pfd;
        FileDescriptor fd = getFileDescriptor(memoryFile);
        pfd = (ParcelFileDescriptor) ReflectUtil.getInstance("android.os.ParcelFileDescriptor",fd);
        return pfd;
    }

把刚刚得到的ParcelFileDescriptor传递到其他进程,这个比较简单直接用binder传就可以了

通过描述共享内存文件描述取得一个描述共享内存的MemoryFile对象,并且需要让这个MemoryFile对象指向刚刚创建的共享内存。在低版本的系统中存在一个构造函数可以直接以FileDescriptor为参数构造出一个MemoryFile对象,这样构造出来的对象刚好指向FileDescriptor描述的共享内存。但是在高版本中没有样的构造函数了。所以在这里我利用了一个取巧的方式。思路是:利用构造函数
public MemoryFile(String name, int length) throws IOException
构造一个MemoryFile对象,当然此时也创建了一块新的共享内存,但是这块共享内存不是我们需要的;调用public void close()方法关闭刚刚创建的共享内存。通过前面的操作后我们得到了一个MemoryFile对象,但是这个对象没有指向任何共享内存,所以接下来我们就需要让MemoryFile对象指向我们需要的共享内存,也就是FileDescriptor描述的那块。在MemoryFile中有一个native方法:

private static native long native_mmap(FileDescriptor fd, int length, int mode)

这个方法就是把fd描述的共享内存映射到虚拟地址空间中。所以我们可以已刚刚获得的FileDescriptor 作为参数利用反射调用这个方法:

/**
     * 打开共享内存,一般是一个地方创建了一块共享内存
     * 另一个地方持有描述这块共享内存的文件描述符,调用
     * 此方法即可获得一个描述那块共享内存的MemoryFile
     * 对象
     *
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值