通常我们会有这样的需求,在安卓系统中,两个独立的进程之间需要通信,如进程A需要进程B的发过来的信号;或者进程A与进程B共享一个内存块;或者进程A是32位进程而进程B是64位进程,为了加速处理过程,需要把进程A处理后的数据传递给进程B进行处理。
这个时候就涉及到了安卓系统中的进程间通信,而安卓系统中的进程间通信往往离不开binder。binder是安卓系统中独有的进程间通信方式,关于其实现机制跟原理,可以参考《Binder系列》
这里主要关心如何实现两个进程通过binder进行通信。
1、如何使用binder进行进程间通信
这里参考:
http://gityuan.com/2015/11/22/binder-use/
该实例主要完成了进程client向进程server发送hello,然后server返回2015数字。
需要注意到的是,如果client无法找到server,可能的原因是selinux的关系,即安卓的防火墙机制,使得client无法连接到server
这时,可以通过adb设置暂时关闭selinux,如下:
adb shell setenforce 0
2、如何进行内存共享
关于内存共享,这里有两种方式。
1)通过MemoryHeap分配共享内存。
当client向server发送指令时,server进行内存分配并共享,然后通过binder返回。
如下所示,
sp<IMemory> buffer = getBuffer();
if(buffer != NULL)
{
reply->writeStrongBinder(buffer->asBinder());
}
具体可参考:http://blog.csdn.net/luoshengyang/article/details/6939890
这里主要适用于不涉及内存拷贝(memcpy)或者说内存拷贝耗时可以忽略不计的情况。因为当client有个数据要传递给server时,需要把client上的数据拷贝到server分配的内存区,然后server进行处理。这样会增加内存拷贝的时间,因此,为了避免内存拷贝的情况,可以使用ION进行内存共享。
2)ION进行内存共享
关于ION的基本概念,可以参考:http://blog.csdn.net/kris_fei/article/details/8588661
进程A打开了ION设备,进行内存分配,得到一个共享的fd,并且开辟了相对应的内存区;
当进程B需要操作这部分数据时,可以直接通过这个共享的fd获取对应的内存区,然后再进行操作。
主要代码如下:
进程A:
int ionfd = open("/dev/ion", O_RDWR);
alloc_data.len = 0x1000;
alloc_data.align = 0x1000;
alloc_data.flags = ION_HEAP(ION_CP_MM_HEAP_ID);
rc = ioctl(ionfd,ION_IOC_ALLOC, &alloc_data);
fd_data.handle = alloc_data.handle;
rc = ioctl(ionfd,ION_IOC_SHARE,&fd_data);
shared_fd = fd_data.fd;
进程B:
fd_data.fd = shared_fd;
rc = ioctl(ionfd,ION_IOC_IMPORT,&fd_data);
buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0);
在这里,需要注意到的是,通过binder传递fd时,不能简单的只传递fd的数值,即不能采用
Parcel data;
data.writeInt(fd);// 不能这样传递fd
应该采用传递文件描述符的接口,具体如下:
Parcel data;
data.writeFileDescriptoer(fd);