在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 <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stddef.h>
#include <linux/ipc.h>
#include <linux/shm.h> #include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h> #define DEVASHMEM "/dev/ashmem"
#define SHNAME "hellomemory"
#define MAXBUFSIZE 1024
#define TRANSFDCODE 1000
#define WRITEDATACODE 1001 using namespace android; int main(int argc, char *argv[])
{
int fd = open(DEVASHMEM, O_RDWR);
if(fd < )
{
return -;
} int ret = ioctl(fd, ASHMEM_SET_NAME, SHNAME);
if(ret < ){
close(fd);
return -;
} char *get_sh_addr_write = NULL;
ret = ioctl(fd, ASHMEM_SET_SIZE, MAXBUFSIZE);
if(ret < ){
close(fd);
return -;
} get_sh_addr_write = (char*)mmap(NULL, MAXBUFSIZE , PROT_READ | PROT_WRITE, MAP_SHARED, fd, );
if(NULL == get_sh_addr_write)
{
return -;
}
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->checkService(String16("mybindertag"));
Parcel data, reply; data.writeDupFileDescriptor(fd);
binder->transact(TRANSFDCODE, data, &reply); char input_data[MAXBUFSIZE] = {};
while()
{
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 <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <linux/ashmem.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stddef.h>
#include <linux/ipc.h>
#include <linux/shm.h> #include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h> #define DEVASHMEM "/dev/ashmem"
#define SHNAME "hellomemory"
#define MAXBUFSIZE 1024
#define TRANSFDCODE 1000
#define WRITEDATACODE 1001 using namespace android; int g_sh_fd = ;
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 > )
{
get_sh_addr_read = (char*)mmap(NULL, get_sh_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_sh_fd, );
}
else
{
printf("mmap failed %d\n", get_sh_size);
return -;
}
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<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return ;
}

  3.3

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

  

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

  

  3.4

  演示截图:

  

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

  

Android native进程间通信实例-binder结合共享内存的更多相关文章

  1. Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  2. Android native进程间通信实例-binder篇之——简单的单工通信

    网上找了很多binder相关文章,大部分都是在跟踪binder实现源代码,然后再把框架代码贴出来,看着实在费力. 这篇文章从实际出发,直接用一个案例下手,后续想了解binder相关原理的话,可以参考& ...

  3. Android native进程间通信实例-binder篇之——用parcel传输数组

     和之前稍微不同,这次要稍微分析一下 Parce.cpp 和 android_os_Parcel.cp p的源码,为的是能够掌握调试技巧,后续传输其它类型数据就能举一反三了!   1. 代码共享 这次 ...

  4. Android native进程间通信实例-binder篇之——解决实际问题inputreader内建类清楚缓存

    我在实际开发中,遇到一个问题,在电容屏驱动中没有发送input_sync 给上层,导致电容屏有的数据缓存在inputreader 中,会导致系统一系列奇怪问题发生, 至于为什么驱动不发送input_s ...

  5. Android native进程间通信实例-socket本地通信篇之——服务端进程异常退出解决办法

    导读: 好难受啊,为什么服务端说挂就挂,明明只是客户端关闭而已,服务端怎么能挂呢? 想想,如果手机上使用一个聊天程序的时候,手机端关闭了聊天程序,那么远端服务器程序总不能说挂就挂吧!所以一定要查明真相 ...

  6. Android native进程间通信实例-socket本地通信篇之——基本通信功能

    导读: 网上看了很多篇有关socket本地通信的示例,很多都是调通服务端和客户端通信功能后就没有下文了,不太实用,真正开发中遇到的问题以及程序稳定性部分没有涉及,代码健壮性不够,本系列(socket本 ...

  7. 【转】Linux环境进程间通信(五) 共享内存(上)

    转自:https://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以 ...

  8. <转>Linux环境进程间通信(五): 共享内存(下)

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html 系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通 ...

  9. <转>Linux环境进程间通信(五): 共享内存(上)

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写 ...

随机推荐

  1. 附008.Kubernetes TLS证书介绍及创建

    一 Kubernetes证书 1.1 TLS Kubernetes系统的各个组件需要使用TLS证书对其通信加密以及授权认证,建议在部署之前先生成相关的TLS证书. 1.2 CA证书创建方式 kuber ...

  2. spring 5.x 系列第5篇 —— 整合 mybatis + druid 连接池 (xml配置方式)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 项目目录结构 1.创建maven工程,除了Spring基本依赖外,还需要导 ...

  3. 如何安装xenserver

    xenserver安装 选择键盘 是否同意协议 清理磁盘 选择本地磁盘安装 选择本地镜像文件 输入管理密码 配置IP地址 配置DNS服务器地址 选择地点 配置NTP服务器地址 开始安装 安装完成

  4. Java中的反射(1)

    Reflection in Java 反射到底是什么呢,我被问到的时候其实也没办法很好的回答这个问题,翻一翻博客,然后逐条讲解.今天干脆就整合一下,免得以后还要去翻. 首先讲一下Java是如何在运行时 ...

  5. [apue] 等待子进程的那些事儿

    谈到等待子进程,首先想到的就是SIGCHLD信号与wait函数族,本文试图厘清二者的方方面面,以及组合使用时可能不小心掉进去的坑. 1. 首先谈单独使用SIGCHLD的场景.下面是一段典型的代码片段: ...

  6. 5分钟快速部署DataDraw数字绘

    经常有小伙伴问,有没有一款好用又免费的画图软件,画画流程图.UML.思维导图?今天就介绍一款开源的在线画图软件,满足各方面人的需求. DataDraw数字绘是一个在线线框图.流程图.网络图.组织结构图 ...

  7. 就是要让你彻底学会 @Bean 注解

    @Bean 注解全解析 随着SpringBoot的流行,基于注解式开发的热潮逐渐覆盖了基于XML纯配置的开发,而作为Spring中最核心的bean当然也能够使用注解的方式进行表示.所以本篇就来详细的讨 ...

  8. C# 创建Windows服务demo

    一.准备工作 1.操作系统:Windows 10 X64 2.开发环境:VS2017 3.编程语言:C# 4. .NET版本:.NET Framework 4.5 二.创建Windows Servic ...

  9. Django rest framework(1)----认证

    目录 Django组件库之(一) APIView源码 Django restframework   (1)  ----认证 Django rest framework(2)----权限 Django ...

  10. 走近Java之幕后的String

    前几天,有个同事问了我一个表面看起来显而易见的问题,是关于String的,我们一起来看一下(如果有说的不正确的地方,欢迎大家指正). java中,字面量在编译期计算,并且String字面量作为常量,存 ...