在android源码的驱动目录下,一般会有共享内存的相关实现源码,目录是:kernel\drivers\staging\android\ashmem.c。但是本篇文章不是讲解android共享内存的功能实现原理,而是讲怎么运用它。

  1. 

  在linux中,不同进程间拥有自己独立的内存空间,32位操作系统中好像一个进程能用的内存大小是4G吧。而且一般不同进程间不能够互相使用各自内存的数据。

  当然不同进程间共享数据方法很多,比如之前说的进程间通信binder,socket等等,不过android出了一个共享内存的概念,为的是不同进程间能够共同操作同一块内存数据,比如进程1001往一块共享内存addr里面写数据“hello world”,进程1009往这块共享内存addr读取出“hello world”,也能够往这块共享内存addr写数据“hello china”。这就是共同享用了一块内存的基本概念了(说白了就是同耕一块田)。讲的够仔细了吧,如果不清楚评论区见。

  注意:好像binder传输的数据实现也是类似于共享内存,读者可以自行去了解。

  

  2.

  先说一下等会写程序的思路:

  首先想想代码编译出两个可执行文件后如何操作,打开两个终端,都进入设备adb shell,第一个终端执行进程a,第二个终端执行进程b。在进程a输入一串数据后,在进程b中可以读出这段数据(也能够改写这段数据,读者可以自行添加这部分功能)。

  然后再想想实现的方式,

  进程a:1. 创建共享内存,设置共享内存大小,这时会得到一个fd。2. 获取共享内存地址。3. 先读取地址数据,然后往地址写入数据。4. 把fd通过binder发送给需要使用的进程。

  进程b:1. 通过binder读取到fd。2. 用fd获取共享内存地址。3. 读取共享内存数据,然后往地址写入数据。

  注意:linux一切皆文件,所以文件描述符fd很重要。  

  

  3. 

  3.1

  捋清思路后,就可以开始写代码了(android.mk的编写可以参考之前的文章),进程a,命名为mysharememory_a代码如下:

  

#include #include #include <string.h>#include #include #include #include #include #include #include #include #include #include #define DEVASHMEM "/dev/ashmem"#define SHNAME "hellomemory"#define MAXBUFSIZE 1024#define TRANSFDCODE 1000#define WRITEDATACODE 1001using namespace android;int  main(int argc, char *argv[]){    int fd = open(DEVASHMEM, O_RDWR);    if(fd < 0)    {        return -1;    }    int ret = ioctl(fd, ASHMEM_SET_NAME, SHNAME);    if(ret < 0){        close(fd);        return -1;    }    char *get_sh_addr_write = NULL;        ret = ioctl(fd, ASHMEM_SET_SIZE, MAXBUFSIZE);    if(ret < 0){        close(fd);        return -1;    }    get_sh_addr_write = (char*)mmap(NULL, MAXBUFSIZE , PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);    if(NULL == get_sh_addr_write)    {        return -1;    }    sp sm = defaultServiceManager();    sp binder = sm->checkService(String16("mybindertag"));    Parcel data, reply;    data.writeDupFileDescriptor(fd);    binder->transact(TRANSFDCODE, data, &reply);        char input_data[MAXBUFSIZE] = {0};    while(1)    {        printf("read share memory buf is %s\n", get_sh_addr_write);        printf("please input data to buf :");        scanf("%s", input_data);        getchar();        strcpy(get_sh_addr_write,input_data);        binder->transact(WRITEDATACODE, data, &reply);    }    return ret;}

  3.2

   mysharememory_b代码如下:

  

#include #include #include <string.h>#include #include #include #include #include #include #include #include #include #include #define DEVASHMEM "/dev/ashmem"#define SHNAME "hellomemory"#define MAXBUFSIZE 1024#define TRANSFDCODE 1000#define WRITEDATACODE 1001using namespace android;int g_sh_fd = 0;class MyBinderService : public BBinder{            status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)            {                int ret;                char *get_sh_addr_read = NULL;                int get_sh_size;                            printf("songsong!! **** onTransact ***** code = %d \n",code);                switch(code)                {                    case TRANSFDCODE:                        g_sh_fd = data.readFileDescriptor();                        break;                    case WRITEDATACODE:                        get_sh_size = ioctl(g_sh_fd, ASHMEM_GET_SIZE,NULL);                        if(get_sh_size > 0)                        {                             get_sh_addr_read = (char*)mmap(NULL, get_sh_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_sh_fd, 0);                        }                        else                        {                            printf("mmap failed %d\n", get_sh_size);                            return -1;                             }                        printf("what is in the share memory: %s\n", get_sh_addr_read);                        break;                    default:                        break;                }                return NO_ERROR;            }};int  main(int argc, char *argv[]){    defaultServiceManager()->addService(String16("mybindertag"), new MyBinderService());    sp proc(ProcessState::self());    ProcessState::self()->startThreadPool();    IPCThreadState::self()->joinThreadPool();    return 0;}

 

  3.3

  回收关闭部分代码可选择添加在mysharememory_b中,如下:

  

    int ret;    ret = munmap((void*)get_sh_addr_read, get_sh_size);    if(ret == -1)    {        return -1;    }        ret = close(g_sh_fd);    if(ret == -1)    {        return -1;    }

 

  

 

  3.4 

  演示截图:

  

 

 

   4. 为了骗取评论,我不再解释代码,心累。不过您可以把代码直接拷贝去编译执行,再通过调试去理解代码的精髓,也是没问题的。

  

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  5. Android之AIDL使用binder进程间通信原理
  6. Android成长历程第一步
  7. android中获取手机相机和相册可以传多张图片
  8. android系统启动流程之init.rc详细分析笔记
  9. Android开发之内容提供者

随机推荐

  1. Android使用AsyncTask实现多线程下载的方
  2. Android 7.0 如何将应用添加设置列表
  3. getSharedPreferences和getDefaultShared
  4. 苹果二手手机换购计划很快支持 Android(
  5. Android通信模块(单线程,多线程通信方式,Han
  6. Android MapView简单使用
  7. Xamarin Mono 环境搭建(使用Visual Studi
  8. Android TextView加中划线/下划线
  9. Android studio中使用xUtils报错
  10. android开发【二】(基于android studio3.2