最近用到Android进程间共享数据,分享一点心得。
首先大体介绍一下Android中数据共享的几种方式
Android底下还是Linux,所以Android的数据共享跟Linux现有的机制有莫大的关系;
1. 在Linux效率最高的通信方式无非是Share Memory,它最大的优点就是利用了MMU的功能, 效率高,无需数据copy(两个Process同时访问同样的physical page[这些Physical Pages被map到不同process的空间内]).
2. 在Android上进程间通信用的最多的就是Binder,强大、方便,人家就是牛逼,能把东西设计的这么好;Binder在方便的同时,不失高效,如果通过Binder直接发送数据,需要一次数据copy就好【将Process A中的数据Copy到Process B mmap好的空间内,Process B可以直接访问】,另外Binder还让Share Memory更好用了,下面我们会看一下这种方式。
3.其他的进程间通信方式效率不高,各有优缺点,网上资料一大把,大家如果想了解可以去Google一下。
Google对于Linux的Shared Memory做了调整,并将Binder易用的特性合进来,关于基本原理,请看下图:
图中User Space Memory Layout的那部分是网络上的截图,自己画太麻烦
//引用出处:
原理跟Shared Memory一样(当然,Google在Linux Kernel做了Driver实现Share),Binder Client端有了BpMemory之后,就可以直接访问共享的Memory空间,无需数据copy(注意,这不是Binder 通信的Memory Copy,之前提到过,Binder通信需要一次数据copy)。
Memory共享之后,就可以分享数据。
对于Android上现存的方式;
1. 使用Binder直接传输数据的方式最大的好处是方便,但是因为效率关系,不适宜大批量、次数巨多的数据共享;这种数据传输无疑是Android中使用最多的一种方式
2. 如果使用Binder_MemoryBase传输数据,易用,方便,Over Head不大,这种方式在AudioFlinger等Android Framework中大量被使用(Audio Flinger【app,mediaserver之间】在共享数据的时候,数据量较大,绝不可以使用Binder直接传)。当然,Over Head, Process之间传一次IMemory Binder需要多次(当前应该是4次)Binder Transaction以及Kernel 中Binder Node的建立和销毁。如果需要process之间的交互很频繁,也不可以直接使用Binder_MemoryBase传来传去(可以memory map完之后,一直使用,避免来回传送binder,降低效率)。将Memory Map到不同process之后,就可以随你怎么操作了,例如:可以拿memory的部分memory空间来做pthread_mutex使用(用作Process间的同步)。
具体方式可以参考Pthread的使用方法:
需要注意的是,务必要用Shared Mutex
DESCRIPTION
The pthread_mutexattr_getpshared() function obtains the value of the process-shared attribute from the attributes object referenced by attr. Thepthread_mutexattr_setpshared() function is used to set the process-shared attribute in an initialised attributes object referenced by attr.
The process-shared attribute is set to PTHREAD_PROCESS_SHARED to permit a mutex to be operated upon by any thread that has access to the memory where the mutex is allocated, even if the mutex is allocated in memory that is shared by multiple processes. If the process-shared attribute is PTHREAD_PROCESS_PRIVATE, the mutex will only be operated upon by threads created within the same process as the thread that initialised the mutex; if threads of differing processes attempt to operate on such a mutex, the behaviour is undefined. The default value of the attribute is PTHREAD_PROCESS_PRIVATE.
在Audio Flinger中就有这种用法,
-
AudioTrackShared.h
-
-
// Important: do not add any virtual methods, including ~
-
struct audio_track_cblk_t
-
{
-
-
// The data members are grouped so that members accessed frequently and in the same context
-
// are in the same line of data cache.
-
Mutex lock; // sizeof(int)
-
Condition cv; // sizeof(int)
-
//.............................................................
-
-
sp<IMemory> cblk = record->getCblk();
-
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
-
audio_track_cblk_t* cblk = mCblk;
-
cblk->lock.lock();
关于Pthread Mutex的大体原理(不完整,最近很忙,所以画的很粗糙),请见下图:
阅读(519) | 评论(0) | 转发(0) |