添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Android下匿名共享内存java层接口利用MemoryFile实现进程间内存共享;利用MemoryFile可以参考这篇文章: https://blog.csdn.net/qq_24451593/article/details/80514566

MemoryFile是java层封装的接口,它实现共享内存主要调用了如下函数:

int fd = open("/dev/ashmem",O_RDWR);
ioctl(fd, ASHMEM_SET_NAME,name);
ioctl(fd,ASHMEM_SET_SIZE, size);
//addr为共享内存地址
addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

创建出来的fd转换成ParcelFileDescriptor通过AIDL传递给另一个进程;另一个进程将ParcelFileDescriptor转换成该进程对应fd,调用mmap来使用该共享内存。
注:进程A的fd与进程B的fd是不一样的,但是都对应同一文件
在这里插入图片描述

既然知道了MemoryFile实际调用函数,那么我们就可以在native层用C++代码实现共享内存。

(1)C++代码实现

android_shm.cpp

#include "android_shm.h"
#define ASHMEM_DEVICE  "/dev/ashmem"
//ret= 0 创建成功;ret=-1,失败;
//注:ret =1,共享内存已经存在,但是目前这个没用,暂时放这
int create_shared_memory(const char* name, U64 size, int node, char*& addr, U64& shm_id){
    U64 fd = open(ASHMEM_DEVICE, O_RDWR);
    if(fd < 0){
        return -1;
    U64 len = ioctl(fd, ASHMEM_GET_SIZE, NULL);
    if(len > 0){             
        addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
   shm_id = fd;
   return 1;
    }else{
        int ret = ioctl(fd, ASHMEM_SET_NAME,name);
        if(ret < 0){
       close(fd);
            return -1;
        ret = ioctl(fd,ASHMEM_SET_SIZE, size);
        if(ret < 0){
       close(fd);
            return -1;
        addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        shm_id = fd;
    return 0;
int open_shared_memory(const char* name, int node, char*& addr, U64& shm_id){
    U64 size = ioctl(shm_id, ASHMEM_GET_SIZE,NULL);
    if(size > 0){ 
        addr = (char*)mmap(NULL, size , PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0);
    }else{
        return -1;     
    return 0;
int close_shared_memory(U64& shm_id, char*& addr){
    U64 size = ioctl(shm_id, ASHMEM_GET_SIZE, NULL);
    if(size <0){
        return -1;
    int ret = munmap((void*)addr, size);
    if(ret == -1){
        return -1;
    ret = close(shm_id);
    if(ret == -1){
        return -1;
    return 0;

android_shm.h

#ifndef _SYS_SHM_H
#define _SYS_SHM_H 1
#include <fcntl.h>
#define SHM_HUGETLB    04000
#include <stdio.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stddef.h>
/* Get common definition of System V style IPC.  */
#include <linux/ipc.h>
/* Get system dependent definition of `struct shmid_ds' and more.  */
#include <linux/shm.h>
typedef unsigned long long U64;
__BEGIN_DECLS
extern int create_shared_memory(const char* name, U64 size, int node, char*& addr, U64& shm_id);
extern int open_shared_memory(const char* name, int node, char*& addr, U64& shm_id);
extern int close_shared_memory(U64& shm_id, char*& addr);
__END_DECLS
#endif /* sys/shm.h */

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libandroid_shm
LOCAL_SRC_FILES := android_shm.cpp
include $(BUILD_SHARED_LIBRARY)

(2)ndk-build编译C++

参考我另一篇博客:https://blog.csdn.net/liny000/article/details/83020530

(3)将进程A的fd传给进程B

利用binder跨进程通信
1)服务类实现binder onTransact函数(两个进程传递ParcelFileDescriptor)
MainService.java

public class MainService extends Service {
    ParcelFileDescriptor pfd;
    @Override
    public IBinder onBind(Intent arg0) {
        return new MyBinder();
    class MyBinder extends Binder {
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            switch (code) {
                case 0:
                    //pfd = data.readParcelable(null);
                    // 或者
                    pfd = data.readFileDescriptor();
                    break;
                case 1:
                    //reply.writeParcelable(pfd,0);
                    // 或者
                    reply.writeFileDescriptor(pfd.getFileDescriptor());
                    break;
                default:
                    break;
            return true;

2)MainActivity 调用C++代码创建共享内存并写入内容,得到fd,转换为ParcelFileDescriptor 传递给MainActivity2
MainActivity.java

package com.example.linyuan.shared_memory;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    Binder mBinder;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mBinder = (Binder) service;
        public void onServiceDisconnected(ComponentName className) {
            mBinder = null;
    @Override
    protected void onDestroy() {
        unbindService(mConnection);
        mConnection = null;
        super.onDestroy();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent it = new Intent(MainActivity.this, MainService.class);
        startService(it);
        bindService(it, mConnection, Context.BIND_AUTO_CREATE);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,MainActivity2.class));
    android.os.Parcel data = android.os.Parcel.obtain();
    android.os.Parcel reply = android.os.Parcel.obtain();
    public void write(View v){
        try {
            if(mBinder!=null){
                //  data.writeParcelable(pfd, 0);
                // 或者
                int fd = fdFromJNI();
                TextView tv = (TextView) findViewById(R.id.sample_text);
                tv.setText("fd:"+ new String(String.valueOf(fd)));
                ParcelFileDescriptor cfd = ParcelFileDescriptor.fromFd(fd);
                FileDescriptor fileDescriptor2 = cfd.getFileDescriptor();
                data.writeFileDescriptor(fileDescriptor2);
                mBinder.transact(0, data, reply, 0);
        } catch (Exception e) {
            e.printStackTrace();
//            Toast.makeText(this, "写失败", 0).show();
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        return super.onOptionsItemSelected(item);
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
    public native int fdFromJNI();

3)获取ParcelFileDescriptor,转换为fd,读取共享内存上内容
MainActivity2.java

public class MainActivity2 extends AppCompatActivity {
    static {
        System.loadLibrary("native-lib");
    private byte[] buffer = new byte[20];
    IBinder mBinder;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // 非服务创建进程,获取的Binder只是一个代理Binder对象,不能直接转换
            // mBinder = (Binder) service;
            mBinder = service;
        public void onServiceDisconnected(ComponentName className) {
            mBinder = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_2);
        Intent it = new Intent(MainActivity2.this,MainService.class);
        startService(it);
        bindService(it, mConnection, Context.BIND_AUTO_CREATE);
    public void read(View v) {
        TextView tv = (TextView) findViewById(R.id.tv);
        try {
            if (mBinder != null) {
                android.os.Parcel data = android.os.Parcel.obtain();
                android.os.Parcel reply = android.os.Parcel.obtain();
                mBinder.transact(1, data, reply, 0);
                //ParcelFileDescriptor pfd = reply.readParcelable(null);
                // 或者
                ParcelFileDescriptor pfd = reply.readFileDescriptor();
                if(pfd==null){
                    buffer = "ParcelFileDescriptor 空指针".getBytes();
                    tv.setText(new String(buffer));
                    return;
                int fd = pfd.getFd();
                String buf;
                buf = read(fd);
                tv.setText(new String(buf));
        } catch (RemoteException e) {
            e.printStackTrace();
    @Override
    protected void onDestroy() {
        unbindService(mConnection);
        mConnection = null;
        super.onDestroy();
    public static   native String read(int fd);

native-lib.cpp 调用C++代码

#include <jni.h>
#include <string>
#include "android_shm.h"
extern "C" JNIEXPORT jint JNICALL
Java_com_example_linyuan_shared_1memory_MainActivity_fdFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    char* buf;
    U64 ufd = 0;
    int ret = create_shared_memory("test1",1024,-1,buf,ufd);
    strcpy(buf,"shared_test你好");
    return ufd;
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_linyuan_shared_1memory_MainActivity2_read(
        JNIEnv *env,
        jobject /* this */,jint fd) {
    std::string hello = "进程2 ";
    U64  ufd = (U64)fd;
    char* buf;
    open_shared_memory("test1",-1,buf,ufd);
    char c[20];
    sprintf(c,"%D",ufd);
    hello = hello +buf +"    fd:" +c;
    close_shared_memory(ufd,buf);
    return  env->NewStringUTF(hello.c_str());

需要在AndroidManifest.xml里添加如下,android:process=":activity_2"是确保另一个进程读取共享内存

<activity
    android:name=".MainActivity2"
    android:label="activity_2"
    android:theme="@style/AppTheme.NoActionBar"
    android:process=":activity_2">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<service android:name="com.example.linyuan.shared_memory.MainService">
    <intent-filter>
        <action android:name="com.example.dtmlluadminuser.test2.MainService" />
    </intent-filter>
</service>

整个工程文件(Android studio)下载:https://download.csdn.net/download/liny000/10763992

Android下匿名共享内存java层接口利用MemoryFile实现进程间内存共享;利用MemoryFile可以参考这篇文章:https://blog.csdn.net/qq_24451593/article/details/80514566MemoryFile是java层封装的接口,它实现共享内存主要调用了如下函数:int fd = open(&amp;quot;/dev/ashmem&amp;quot;,O_RDWR);...
最近研究Android6.0流媒体传输,用到了Android里面的内存共享(Ashmem匿名共享),研究了两天怎么用的,现在分享一下: 1、Java使用内存共享:关键MemoryFile的类。 1.1 service 初始化 1.2 service 写数据 1.3 获取文件描述符传递给别的进程使用。 1.4 别的进程拿到文件描述符后读取数据:
Android共享内存的序列化过程知识点:1. 面试题:2. 重点: Native 构建对象如何与 Java 对应2.1 opencv Mat 源码阅读2.2 Parcel.java 的源码3.手写个Native的Parcel.cpp,便于理解 代码请看:NDKPractice项目的jni09 1. 面试题: 进程间的通信方式有哪些 binder 和 socket 通信的区别有哪些 从传输性能上说 : Socket,传输效率低,开销大,主要用在跨网络的进程间通信;消息队列和管道采用存储-转
android系统在应用程序框架中提供了两个C++MemoryHeapBase和MemoryBase来创建和管理匿名共享内存。 如果一个进程需要与其他进程共享一块完整的匿名共享内存,那么就可以通过使用MemoryHeapBase类类创建这块匿名共享内存。如果一个进程创建一块匿名共享内存后,只希望与其他进程共享其中的一部分,那么就可以通过MemoryBase类来创建这块匿名共享内存。 IMemory.h:定义内存相关类的接口,表示堆内存的类IMemoryHeap和BnMemoryHeap,表示一
Android 提供了几种进程间通信的方式,除了Socket,基本都是基于binder实现的。为什么要用共享内存实现呢?因为binder传输数据被限制在1M,在较大的数据交换一般会使用文件,但效率非常的低,因此使用共享内存是很好的方式。在内存中开辟一块空间,通过binder或者其他方式将fd(文件描述符)传递到客户端或服务端进程,从而实现大文件传输 其中Android提供了封装好的MemoryFile对象,供使用。 具体实现 一,服务端 1,首先在APP内部存储中存放一张图片:路径 data/dat.
共享内存相关的函数shm_open、shm_unlink。Linux系统中可用,Android系统上不支持。 函数shm_open的作用是打开一个特殊的文件,返回file descriptor,这个fd可以与mmap一同使用。 http://comments.gmane.org/gmane.comp.gnu.apl.bugs/1377 Elias Mårtenson | 2 Ju
Arrays.copyOf(array, to_index); Arrays.fill(array, from_index, to_index); 第一个方法其实就是返回一个数组,而这个数组就等于数组array的前to_index个数,也就是array[0] ~ array[to_index - 1]。 而第二种方法也只是加了一个初始的位置,即返回一个数组等于array[from_index] ~ array[to_index - 1]。 这里要注意一下,不管是上面哪种使用方法,都务必记住时不包含array
### 回答1: Android C的共享内存是一种高效的IPC机制,它允许不同的进程共享内存区域,从而实现数据共享和数据传输。在Android系统中,使用共享内存有两种基本方法:POSIX共享内存和Ashmem。 POSIX共享内存(shm_open系统调用)是基于文件的IPC机制,它可以在不同的进程间共享文件系统中的内存块。在使用该方法时,首先创建并打开一个共享内存对象以便其他进程能够在其中写入或读取数据。与普通文件不同的是,该对象可以被多个进程同时访问,从而实现内存共享和数据传输。 Ashmem是Android专有的共享内存机制,它通过匿名内存映射(mmap系统调用)来创建共享内存,使多个进程可以共享相同的内存区域。在使用Ashmem时,首先在一个进程中分配一块内存区域,并将其标记为共享内存。其他进程可以通过Binder接口来获取该内存区域所对应的Ashmem文件描述符,并进一步映射内存区域,以便共享数据。 正如所见,Android C的共享内存机制提供了一种高效的IPC方法,可以在不同的进程之间实现数据共享和数据传输。但是由于共享内存存在并发访问、内存泄露等问题,因此在应用中使用时需要格外小心。 ### 回答2: Android C共享内存是一种在Android系统中用于不同进程间共享数据的机制。在多进程应用程序中,进程之间共享数据允许各个进程共同访问数据,从而提高系统的整体性能。C共享内存实现了这种数据共享的方式,允许多个进程可以同步地访问相同的内存区域,从而实现数据共享。 C共享内存操作需要用到管道和信号量等Linux中的IPC技术。进程可以通过信号量来控制对共享内存区域的访问,从而实现数据同步。同时,通过管道机制,同步地向共享内存区域写入和读出数据。在Android开发中,通常会使用NDK库和底C语言来实现共享内存操作,可以对共享内存区域进行读写操作和管理。 通常情况下,在Android的多进程应用程序中,可以使用C共享内存实现不同进程之间的数据共享,从而提高应用程序的整体性能和响应速度。C共享内存也可以被用于进程间的通信,例如在游戏和音视频应用程序中,可以使用共享内存实现不同进程的交互与协作。总的来说,Android C共享内存提供了一种能够优化应用程序性能和提高用户体验的底机制。