Android Shared Memory
The common mechanism in android to share data between processes is the binder.
We can also use other IPC like unix domain sockets, pipes etc.
The main problem with the above is performance. In some cases we need to share memory between processes to prevent the system from coping data to and from the kernel
Android ashmem
One feature that google added to linux kernel is ashmem. We can create a new region using MemoryFile class or ashmem_create_region on native layer but, for security reasons, we cant open an existing region The solution is to create a service that creates the region and return it to the client via file descriptor. First we declare the service AIDL:
interface IShmService
{
ParcelFileDescriptor getFD(in String name);
}
The type ParcelFileDescriptor wrap the kernel object to pass it using the binder
The Service Code
The java part of the code is auto generated using aidl utility, to create and map a shared memory (or any other file descriptor object) we need a native code because we need a pointer
static jint getFD(JNIEnv *env, jobject thiz, jstring n)
{
const char *name = (env)->GetStringUTFChars(n,NULL);
jint fd = open("/dev/ashmem",O_RDWR);
ioctl(fd,ASHMEM_SET_NAME,name);
ioctl(fd,ASHMEM_SET_SIZE,4096);
map = (int *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
// fill some data for testing purpose
map[0]=99;
map[10]=88;
(env)->ReleaseStringUTFChars(path,name);
return fd;
}
The Service Java Code
The native function returns an integer file descriptor , the java code needs to convert it to ParcelFileDescriptor
public ParcelFileDescriptor getFD(String name) throws RemoteException {
try {
int fd = ShmLib.getFD(name); // call to native function
ParcelFileDescriptor ret=ParcelFileDescriptor.fromFd(fd);
return ret;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
The function prototype is generated automatically using aidl and throws RemoteException because it passed through the binder
The Client Code -Java
Simply bind to the service (using bindservice and Intent object) and call the above function to get the duplicated file descriptor:
ParcelFileDescriptor p = service.getFD("samp");
ShmClientLib.init(p.getFd());
The Client Code – native
Declare a global pointer to hold the shared memory address and use mmap to set it:
static void init(JNIEnv *env, jobject thiz, jint fd)
{
map = (int *)mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
}
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment