Android native进程间通信实例-binder结合共享内存
在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结合共享内存的更多相关文章
- Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务
有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...
- Android native进程间通信实例-binder篇之——简单的单工通信
网上找了很多binder相关文章,大部分都是在跟踪binder实现源代码,然后再把框架代码贴出来,看着实在费力. 这篇文章从实际出发,直接用一个案例下手,后续想了解binder相关原理的话,可以参考& ...
- Android native进程间通信实例-binder篇之——用parcel传输数组
和之前稍微不同,这次要稍微分析一下 Parce.cpp 和 android_os_Parcel.cp p的源码,为的是能够掌握调试技巧,后续传输其它类型数据就能举一反三了! 1. 代码共享 这次 ...
- Android native进程间通信实例-binder篇之——解决实际问题inputreader内建类清楚缓存
我在实际开发中,遇到一个问题,在电容屏驱动中没有发送input_sync 给上层,导致电容屏有的数据缓存在inputreader 中,会导致系统一系列奇怪问题发生, 至于为什么驱动不发送input_s ...
- Android native进程间通信实例-socket本地通信篇之——服务端进程异常退出解决办法
导读: 好难受啊,为什么服务端说挂就挂,明明只是客户端关闭而已,服务端怎么能挂呢? 想想,如果手机上使用一个聊天程序的时候,手机端关闭了聊天程序,那么远端服务器程序总不能说挂就挂吧!所以一定要查明真相 ...
- Android native进程间通信实例-socket本地通信篇之——基本通信功能
导读: 网上看了很多篇有关socket本地通信的示例,很多都是调通服务端和客户端通信功能后就没有下文了,不太实用,真正开发中遇到的问题以及程序稳定性部分没有涉及,代码健壮性不够,本系列(socket本 ...
- 【转】Linux环境进程间通信(五) 共享内存(上)
转自:https://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以 ...
- <转>Linux环境进程间通信(五): 共享内存(下)
http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index2.html 系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通 ...
- <转>Linux环境进程间通信(五): 共享内存(上)
http://www.ibm.com/developerworks/cn/linux/l-ipc/part5/index1.html 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写 ...
随机推荐
- Storm 学习之路(四)—— Storm集群环境搭建
一.集群规划 这里搭建一个3节点的Storm集群:三台主机上均部署Supervisor和LogViewer服务.同时为了保证高可用,除了在hadoop001上部署主Nimbus服务外,还在hadoop ...
- ZooKeeper学习之路(一)—— ZooKeeper简介及核心概念
一.Zookeeper简介 Zookeeper是一个开源的分布式协调服务,目前由Apache进行维护.Zookeeper可以用于实现分布式系统中常见的发布/订阅.负载均衡.命令服务.分布式协调/通知. ...
- 新手怎么学JS?JavaScript基础入门
新手应该怎么学习JS?JavaScript入门 - 01 准备工作 在正式的学习JavaScript之前,我们先来学习一些小工具,帮助我们更好的学习和理解后面的内容. js代码位置 首先是如何编写Ja ...
- 系统学习 Java IO (十)----回退流 PushbackInputStream
目录:系统学习 Java IO---- 目录,概览 PushbackInputStream 旨在从 InputStream 解析数据时使用. 有时您需要先读取几个字节以查看将要发生的事情,然后才能确定 ...
- 23 | 知其然知其所以然:聊聊API自动化测试框架的前世今生
- 漫谈Redis分布式锁实现
在Redis上,可以通过对key值的独占来实现分布式锁,表面上看,Redis可以简单快捷通过set key这一独占的方式来实现分布式锁,也有许多重复性轮子,但实际情况并非如此.总得来说,Redis实现 ...
- 【数据库】Navicat Premium12远程连接MySQL数据库
目录 00. 目录 01. 环境介绍 02. Navicat安装 03. MySQL开启远程登录权限 04. Navicat连接MySQL 00. 目录 @ 参考博客:https://blog.csd ...
- 性能测试即服务-docker部署jmeter及.netcore应用
前言 现在各种业务都追求上云,通俗的讲,“XX即服务”,作为一名专职的性能测试调优人员的我,由于会点三脚猫的开发功夫,“性能测试即服务”这种开发大任就落到我头上了,先做一个能完成核心压测功能的基础版. ...
- git中常用的操作命令有哪些?常用操作命令归纳
git中常用的操作命令有哪些?本篇文章就给到大家归纳了一些git中常用操作命令.有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. git开始 全局配置:配置用户名和e-mail地址 1 ...
- centos 7 安装docker,conflicts 异常
[root@localhost html]# yum install docker-io 已加载插件:fastestmirror, langpacks Loading mirror speeds fr ...