android native共享内存,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 #include#include#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 1001

using namespaceandroid;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);

}returnret;

}

3.2

mysharememory_b代码如下:

#include #include#include#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 1001

using namespaceandroid;int g_sh_fd = 0;class MyBinderService : publicBBinder{

status_t onTransact(uint32_t code,const Parcel& data, Parcel*reply, uint32_t flags)

{intret;char *get_sh_addr_read =NULL;intget_sh_size;

printf("songsong!! **** onTransact ***** code = %d \n",code);switch(code)

{caseTRANSFDCODE:

g_sh_fd=data.readFileDescriptor();

break;caseWRITEDATACODE:

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;

}returnNO_ERROR;

}

};int main(int argc, char *argv[])

{

defaultServiceManager()->addService(String16("mybindertag"), newMyBinderService());

spproc(ProcessState::self());

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();return 0;

}

3.3

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

intret;

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

演示截图:

4f5e1543c8726a924b324802ebd744e1.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值