MemoryFile 共享内存原理分析,中高级Android面试题目汇总解答

本文详细分析了Android中的MemoryFile如何利用Ashmem驱动进行内存共享,从Java API到Native层,再到驱动函数的调用流程。同时,文章提及Android面试中关于MemoryFile和内存共享的高级话题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

「进程 A 中申请一块共享内存写入数据,并准备好文件描述符:」

MemoryFile memoryFile = new MemoryFile(name, size);

memoryFile.getOutputStream().write(data);

Method method = MemoryFile.class.getDeclaredMethod(“getFileDescriptor”);

FileDescriptor des = (FileDescriptor) method.invoke(memoryFile);

ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(des);

「进程 B 中通过 binder 拿到 A 进程中准备好的文件描述符,然后直接读取数据:」

FileDescriptor descriptor = pfd.getFileDescriptor();

FileInputStream fileInputStream = new FileInputStream(descriptor);

fileInputStream.read(data);

如上代码所示,使用起来和文件读写一样很简单,但我们不能只停留在仅会使用的浅显层面。接着来看 MemoryFile 是怎么从 Java API 调用到 Ashmem 驱动函数的,先来看 MemoryFile 的构造函数:

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

try {

mSharedMemory = SharedMemory.create(name, length);

mMapping = mSharedMemory.mapReadWrite();

} catch (ErrnoException ex) {

ex.rethrowAsIOException();

}

}

可以看到构造 MemoryFile 时通过 SharedMemory create 方法申请了一块匿名共享内存,SharedMemory create 方法中调用了 nCreate native 方法:

private static native FileDescriptor nCreate(String name, int size) throws ErrnoException;

对应的 native 实现在 android_os_SharedMemory.cpp 中,实现如下:

static jobject SharedMemory_create(JNIEnv* env, jobject, jstring jname, jint size) {

const char* name = jname ? envGetStringUTFChars(jname, nullptr) : nullptr;

int fd = ashmem_create_region(name, size); //创建匿名共享内存

return jniCreateFileDescriptor(env, fd);

}

接着来看 ashmem_create_region 方法,它的对应实现在 ashmem-dev.cpp 中,如下:

int ashmem_create_region(const char *name, size_t size){

int ret, save_errno;    //创建匿名共享内存

int fd = __ashmem_open();

if (fd < 0) { return fd;}

if (name) {

char buf[ASHMEM_NAME_LEN] = {0};

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

// 设置 Ashmem 名字

ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_NAME, buf));

if (ret < 0) {goto error; }

}

}

如上设置 Ashmem 名字执行了 ioctl 系统调用, 它会进一步调用到 「ashmem_ioctl」 驱动函数。接着来看 __ashmem_open 方法:

static int __ashmem_open(){

int fd;

pthread_mutex_lock(&__ashmem_lock);

fd = __ashmem_open_locked(); //创建匿名共享内存

pthread_mutex_unlock(&__ashmem_lock);

return fd;

}

进一步调用到 __ashmem_open_locked 方法,如下:

#define ASHMEM_DEVICE “/dev/ashmem” //Ashmem 设备驱动

static int __ashmem_open_locked(){

int ret;

struct stat st;

int fd = TEMP_FAILURE_RETRY(

open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC)); //创建匿名共享内存

…    return fd;

}

在 __ashmem_open_locked 方法中调用了 open() 系统调用,和 ioctl 一样,对应到 Ashmem 设备驱动函数了,即 「ashmem_open」 驱动函数。

通过上面的分析知道 Ashmem 驱动的 ashmem_open 函数是由 SharedMemory 的 create 方法触发一步一步调用到的,期间还调用了 ashmem_ioctl 函数。

而 ashmem_mmap 驱动函数是通过 SharedMemory 的 mapReadWrite 方法触发,下面来分析这个过程:

//android.os.SharedMemory.java

public @NonNull ByteBuffer mapReadWrite() throws ErrnoException {

return map(OsConstants.PROT_READ | OsConstants.PROT_WRITE, 0, mSize);

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。希望能够帮助到大家提升技术

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

[外链图片转存中…(img-I3HXZ98g-1712786078317)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值