Ashmem

Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 10

skip to main skip to sidebar Monday, March 22, 2010 Share memory using ashmem and binder in the

android framework To share memory between different processes in the android framework ashmem can be used. Ashmem is a android shared memory addon to the linux kernel. Ashmem has reference counting so that if many processes use the same area the ar ea will not be removed until all processes has released it, the memory is also v irtual and not physically contiguous. If physically contiguous memory is needed like for hardware reasons pmem can be used, but it has no reference counting and is not part of standard Android kernel. In this blog post we will concentrate only on ashmem. Ashmem is allocated via ashmem_create_region() that gives you an file descriptor then you use mmap() on it to get a memory area: int fd = ashmem_create_region("SharedRegionName", size); if(fd == 0) { data = mmap(NULL, size, PROT_READ PROT_WRITE, MAP_SHARED, fd, 0); if(data != MAP_FAILED) { /* It works do your stuff*/ } } But this will not solve your problem on how to share the memory area. The first problem is that the memory pointer "data" in our example above is per process an d can't be shared. The next problem is that for security reasons the name "Share dRegionName" in the example above are not shared between processes. The "other" process that want to access the same shared memory area can't use a ashmem_creat e_region() with the same name to get access to the same physical memory area. In stead the file descriptor (fd in the example above) needs to be used in a new mm ap() in the "other" process. Here comes the third problem, the file descriptor a re per process and can't be shared with the other process just like that. Bummer ! The solution is to share the file descriptor with the binder since the binder ha s special functions that can be used to transfer file descriptors over it's inte rface. To help you with ashmem handeling and file descriptor sharing the class MemoryHe apBase can be used. To transfer the MemoryHeapBase object you can use the asBinder() on the IMemoryH eap interface class on the server side to transfer the needed information to set up an new area on the client side mapped to the same physical memory. sp<imemoryheap> memHeap = ... reply->writeStrongBinder(memHeap->asBinder()) On the client side the MemoryHeapBase class will take care of all the needed stu ff for you and all you need to do in your binder wrapper class is something like this: sp<imemoryheap> memHeap; memHeap = interface_cast<imemoryheap> (reply.readStrongBinder()); Please remember that the mmap:ed memories virtual address is not equal to the ph ysical address even more important that the virtual address is different to each

process and might be different for every call to the getBufferMemPointer() function even if the same ashmem region is used so be care ful if you have stored your pointer somewhere and still operate on it. Here is a complete example setting up everything needed to get this working. Interface header: IEneaBuffer.h /* * * * * * IEneabuffer.h Created on: 19 mars 2010 Author: Zingo Andersen License: Public Domain (steal and use what you like) Buffer classes to handle the binder communication */

#ifndef IENEABUFFER_H_ #define IENEABUFFER_H_ #include #include #include #include #include <utils/RefBase.h> <binder/IInterface.h> <binder/Parcel.h> <binder/IMemory.h> <utils/Timers.h>

namespace android { class IEneaBuffer: public IInterface { public: DECLARE_META_INTERFACE(EneaBuffer); virtual sp<IMemoryHeap> getBuffer() = 0; }; /* --- Server side --- */ class BnEneaBuffer: public BnInterface<IEneaBuffer> { public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); }; }; // namespace android #endif /* IENEABUFFER_H_ */ Interface class: IEneaBuffer.cpp /* * IEneaBuffer.cpp * Created on: 19 mars 2010 Author: Zingo Andersen * License: Public Domain (steal and use what you like) * * Buffer classes to handle the binder communication */ //#define LOG_TAG "IEneaBuffer" #include <utils/Log.h>

#include #include #include #include

<stdint.h> <sys/types.h> <binder/MemoryHeapBase.h> <IEneaBuffer.h>

namespace android { enum { GET_BUFFER = IBinder::FIRST_CALL_TRANSACTION }; /* --- Client side --- */ class BpEneaBuffer: public BpInterface<IEneaBuffer> { public: BpEneaBuffer(const sp<IBinder>& impl) : BpInterface<IEneaBuffer>(impl) { } sp<IMemoryHeap> getBuffer() { Parcel data, reply; sp<IMemoryHeap> memHeap = NULL; data.writeInterfaceToken(IEneaBuffer::getInterfaceDescriptor()); // This will result in a call to the onTransact() // method on the server in it's context (from it's binder threads) remote()->transact(GET_BUFFER, data, &reply); memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder()); return memHeap; } }; IMPLEMENT_META_INTERFACE(EneaBuffer, "android.vendor.IEneaBuffer"); /* --- Server side --- */ status_t BnEneaBuffer::onTransact(uint32_t code, const Parcel& data, Parcel* rep ly, uint32_t flags) { switch (code) { case GET_BUFFER: { CHECK_INTERFACE(IEneaBuffer, data, reply); sp<IMemoryHeap> Data = getBuffer(); if (Data != NULL) { reply->writeStrongBinder(Data->asBinder()); } return NO_ERROR; break; } default: return BBinder::onTransact(code, data, reply, flags); } } }; // namespace android Then use it in your server class by inherit the server class with something like

this: Server command: EneaBufferServer.cpp /* * EneaBufferServer.cpp * Created on: 19 mars 2010 Author: Zingo Andersen * License: Public Domain (steal and use what you like) * * The Server will create a shared area that the client will then use * The server will initiate the first int in the area and print it's value ever y * 5s. If you start the client in parallell it will try to change this value * (value=value+1). */ #include #include #include #include "IEneaBuffer.h" <binder/MemoryHeapBase.h> <binder/IServiceManager.h> <binder/IPCThreadState.h>

namespace android { #define MEMORY_SIZE 10*1024 /* 10Kb shared memory*/ class EneaBufferService : public BnEneaBuffer { public: static void instantiate(); EneaBufferService(); virtual ~EneaBufferService(); virtual sp<IMemoryHeap> getBuffer(); private: sp<MemoryHeapBase> mMemHeap; }; sp<IMemoryHeap> EneaBufferService::getBuffer() { return mMemHeap; } void EneaBufferService::instantiate() { status_t status; status = defaultServiceManager()->addService(String16("vendor.enea.Buffer"), n ew EneaBufferService()); } EneaBufferService::EneaBufferService() { //The memory is allocated using a MemoryHeapBase, and thereby is using ashmem mMemHeap = new MemoryHeapBase(MEMORY_SIZE); unsigned int *base = (unsigned int *) mMemHeap->getBase(); *base=0xdeadcafe; //Initiate first value in buffer } EneaBufferService::~EneaBufferService() { mMemHeap = 0; }

static sp<IMemoryHeap> receiverMemBase; unsigned int * getBufferMemPointer(void) { static sp<IEneaBuffer> eneaBuffer; /* Get the buffer service */ if (eneaBuffer == NULL) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; binder = sm->getService(String16("vendor.enea.Buffer")); if (binder != 0) { eneaBuffer = IEneaBuffer::asInterface(binder); } } if (eneaBuffer == NULL) { LOGE("The buffer service is not published"); return (unsigned int *)-1; /* return an errorcode... */ } else { receiverMemBase = eneaBuffer->getBuffer(); return (unsigned int *) receiverMemBase->getBase(); } } } using namespace android; int main(int argc, char** argv) { unsigned int *base; EneaBufferService::instantiate(); //Create binder threads for this "server" ProcessState::self()->startThreadPool(); LOGD("Server is up and running"); base = getBufferMemPointer(); for(;;) { LOGD("EneaBufferServer base=%p Data=0x%x", base,*base); sleep(5); } // wait for threads to stop // IPCThreadState::self()->joinThreadPool(); return 0; }

You need add the following line to register the service in the file frameworks/b ase/cmds/servicemanager/service_manager.c { AID_MEDIA, "vendor.enea.Buffer" }, On the client process side you can use something like the code snippet below to get the memory pointer. NOTE: MemoryHeapBase is based on strong pointer and will be "magical" ref counte d and removed thats why the client put the object pointer in a static variable i n the example below to keep it from being removed. /* * EneaBufferClient.cpp * Created on: 19 mars 2010 Author: Zingo Andersen * License: Public Domain (steal and use what you like) * * Get the shared memory buffer from the server and change the first int value * by adding one to it. The Server should be running in parallell pleas view * the logcat for the result */ #include "IEneaBuffer.h" #include <binder/MemoryHeapBase.h> #include <binder/IServiceManager.h> namespace android { static sp<IMemoryHeap> receiverMemBase; unsigned int * getBufferMemPointer(void) { static sp<IEneaBuffer> eneaBuffer = 0; /* Get the buffer service */ if (eneaBuffer == NULL) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; binder = sm->getService(String16("vendor.enea.Buffer")); if (binder != 0) { eneaBuffer = IEneaBuffer::asInterface(binder); } } if (eneaBuffer == NULL) { LOGE("The EneaBufferServer is not published"); return (unsigned int *)-1; /* return an errorcode... */ } else { receiverMemBase = eneaBuffer->getBuffer(); return (unsigned int *) receiverMemBase->getBase(); } } }

using namespace android; int { // // // main(int argc, char** argv) base could be on same address as Servers base but this is purely by luck do NEVER rely on this. Linux memory management may put it wherever it likes. unsigned int *base = getBufferMemPointer(); if(base != (unsigned int *)-1) { LOGD("EneaBufferClient base=%p Data=0x%x\n",base, *base); *base = (*base)+1; LOGD("EneaBufferClient base=%p Data=0x%x CHANGED\n",base, *base); receiverMemBase = 0; } else { LOGE("Error shared memory not available\n"); } return 0;

And my Android.mk file for this: # Ashmem shared buffer example # Created on: 19 mars 2010 Author: Zingo Andersen # License: Public Domain (ste al and use what you like) LOCAL_PATH:= $(call my-dir) # # BufferServer # include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ IEneaBuffer.cpp \ EneaBufferServer.cpp \ LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder LOCAL_MODULE:= EneaBufferServer LOCAL_CFLAGS+=-DLOG_TAG=\"EneaBufferServer\" LOCAL_PRELINK_MODULE:=false include $(BUILD_EXECUTABLE) # # BufferClient # include $(CLEAR_VARS) LOCAL_SRC_FILES:= IEneaBuffer.cpp \ \

EneaBufferClient.cpp \ LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder LOCAL_MODULE:= EneaBufferClient LOCAL_CFLAGS+=-DLOG_TAG=\"EneaBufferClient\" LOCAL_PRELINK_MODULE:=false include $(BUILD_EXECUTABLE) /Rebecka & Zingo Upplagd av Enea Android Team kl. 10:34 AM Email ThisBlogThis!Share to TwitterShare to Facebook3 kommentarer: Michael Ambrus said... Hi Rebecka & Zingo, it seems that whenever you publish code snippets including the template sp, the type-name is mistakenly interpreted as a non-existing HTML-tag. I.e. the type-na me will not be shown. You need to use & g t ; and & l t ; (without the spaces in-between) instead of > and < when publishing. Besides from that, thanks for your excellent work! /Michael October 5, 2010 12:30 PM Enea Android Team said... Fixed, thanx for the input, missed that the <pre> tag didn't take care of this, sorry. December 8, 2010 10:35 AM kolanchinathan said... Hi members, I am new android technology, can any one provide me detailed information regardi ng (ashmem, binder, alarm, power manager). what is the purpose of these driver i n android kernel. Regards Kolanchinathan S kolanchi19@gmail.com August 11, 2011 2:52 PM Post a Comment Newer Post Older Post Home Subscribe to: Post Comments (Atom) The unofficial blo g of the Enea Android team This blog is maintained by some of the people working in the Android Competence Center at Enea. It is used to describe our work with the Android mobile technolo gy platform, and to share some useful information with the community. We are involved in Android projects at the platform level and also provide train ing courses for people working on the device level with Android. For more info o n the Enea Android Competence Center and our commercial Android projects please visit www.enea.com/Android.

Blog Archive ? 2011 (4) ? October (1) Using NFC in Android ? September (1) Using Android in industrial applications ? August (1) An example of porting existing code to a custom An... ? May (1) Android Only ? 2010 (10) ? October (2) Working with Android on development boardsSlides from the presentation on Securi ty Concepts ... ? September (1) Android Only conference and plans for the fall ? June (2) Sky Is The Limit - Now on Android MarketUsing the local_manifest.xml file in rep o to custo... ? May (1) Android Open Source Project workflow ? April (1) Using Checkstyle with Android Open Source Project ? March (1) Share memory using ashmem and binder in the androi... ? February (2) Everyone wants to learn more about AndroidUsing Android to control Lego Mindstor ms ? 2009 (18) ? December (3) Adding a system server to the Android frameworkHowto setup a and roid project in Eclipse that acce...Ubuntu 9.10, Java 5 and the Android Open Sou rce Pr... ? November (2) Train Tracker - our first Android applicationAndroid report in E lektroniktidningen ? October (1) Examples on extending the framework ? September (2) Officially a competence centerStarting an Android service after boot ? August (2) The init process and init.rcBack after the summer with some NDK co mments ? July (1) The System Server in Android ? June (1) The Android boot process from power on ? April (3) A closer look at the Android project build system ...A closer look at the Android project build system ...JNI hands on ? March (3) Android seminar in LundGetting started with LINX on AndroidHowto bu ild sdk and plugin - copy'n'paste version Followers About ENEA Android Enea Android Team The Enea Android team consists of Mattias, Robert, Zingo, Karin, Rebecka, Erik, Torkel, and others at the Enea Android Competence Center. View my complete profile

http://lists.canonical.org/pipermail/kragen-hacks/2002-January/000292.html

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy