Android native进程间通信实例-binder结合共享内存
Posted songsongman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 < 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<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] = 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 <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 = 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<ProcessState> 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. 为了骗取评论,我不再解释代码,心累。不过您可以把代码直接拷贝去编译执行,再通过调试去理解代码的精髓,也是没问题的。
以上是关于Android native进程间通信实例-binder结合共享内存的主要内容,如果未能解决你的问题,请参考以下文章