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 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写 ...
随机推荐
- 一篇文章概括 Java Date Time 的使用
本文目的:掌握 Java 中日期和时间常用 API 的使用. 参考:Jakob Jenkov的英文教程Java Date Time Tutorial 和 JavaDoc 概览 Java 8 新增 AP ...
- 2019.ccpc女生赛-wfinal总结
2019ccpc女生赛离它结束有四天了,在这个期间我想了很多,想了想还是决定写这个总结.作为这个队伍唯一的一名大一队员,我很庆幸,能跟着两个学姐一起打比赛,计爱玲师姐,即将工作,张莹俐学姐.这估计都是 ...
- 真实项目中 ThreadLocal 的妙用
一.什么是 ThreadLocal ThreadLocal 提供了线程的局部变量,每个线程都可以通过 set() 和 get() 来对这个局部变量进行操作,但不会和其他线程的局部变量冲突,实现了线程间 ...
- BFS(五):八数码难题 (POJ 1077)
Eight Description The 15-puzzle has been around for over 100 years; even if you don't know it by tha ...
- 浅入深出Vue:子组件与数据传递
上一篇了解了组件的概念及在使用中需要注意的地方.在面对单个组件逻辑复杂需要拆分时,难免会遇到父子组件之间数据传递的问题.那么我们来了解一下在父子组件之间进行数据传递时需要遵循哪些约定,以及要注意哪些问 ...
- NumPy基础操作(3)——代数运算和随机数
NumPy基础操作(3)--代数运算和随机数 (注:记得在文件开头导入import numpy as np) 目录: NumPy在矩阵运算中的应用 常用矩阵运算函数介绍 编程实现 利用NumPy生成随 ...
- CSU 1811: Tree Intersection(线段树启发式合并||map启发式合并)
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1811 题意:给出一棵树,每一个结点有一个颜色,然后依次删除树边,问每次删除树边之后,分开的两个 ...
- 微信小程序源码
内带scroll滚动轮播:如图: 微信小程序开发工具:微信开发工具: 文件目录: images:小程序的图标 pages:小程序页面 utils:方法js git地址:https://gi ...
- easyui datagrid 单元格 编辑时 事件 修改另一单元格
//datagrid 列数据 $('#acc').datagrid({ columns : [ [ { field : 'fee_lend', title : '收费A', width : 100, ...
- 学习使用Quartz,java
报名立减200元.暑假直降6888. 邀请链接:http://www.jnshu.com/login/1/20535344 邀请码:20535344 Quartz官网 添加quartz到Java应用中 ...