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 #define SHM_HUGETLB    04000#include #include #include #include #include /* Get common definition of System V style IPC.  */#include /* Get system dependent definition of `struct shmid_ds' and more.  */#include typedef unsigned long long U64;__BEGIN_DECLSextern 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_shmLOCAL_SRC_FILES := android_shm.cppinclude $(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 #include #include "android_shm.h"extern "C" JNIEXPORT jint JNICALLJava_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 JNICALLJava_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"是确保另一个进程读取共享内存

                                        

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

更多相关文章

  1. Android的底层库libutils介绍
  2. Android——使用 Broastcast 实现进程间通讯
  3. Android(安卓)进程间通信 实例分析
  4. android 常见死机问题--log分析
  5. Android的Btimap处理大图片解决方法
  6. 《Android系统开发》笔记
  7. Android(安卓)Dalvik 内存管理学习
  8. Android(安卓)OOM内存溢出解决方案之一
  9. 如何使Android应用程序获取系统权限【转】

随机推荐

  1. MySQL数据库8——数据库中函数的应用详解
  2. mysql下载与安装过程详解
  3. MySQL使用LOAD_FILE()函数方法总结
  4. mysql 8.0.15 下载安装详细教程 新手必备
  5. Centos7下mysql 8.0.15 安装配置图文教程
  6. Linux下mysql 8.0.15 安装配置图文教程以
  7. sql与各个nosql数据库使用场景的讲解
  8. MySQL group by对单字分组序和多字段分组
  9. MySQL开发规范与使用技巧总结
  10. pycharm2017实现python3.6与mysql的连接