[Android]Ashmem共享内存使用

Android中设计的Ashmem使用起来非常方便,但是很多封装使用,却让其看起来复杂了。

下面通过一个例子来查看其使用

服务端创建共享内存fd,并通过binder通信把fd提供给客户端


#define LOG_TAG "bindertest"

#include <stdio.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>

#include <iostream>
#include <iomanip>

#include <unistd.h>

//for ALOGD
#include <log/log.h>


using namespace android;
using namespace std;
//

int32_t* pdata = NULL;
int fd = -1;


class myBinder : public BBinder
{
public:
	status_t dump(int fd2, const Vector<String16>& args)
	{
		write(fd2, "myBinder dump called       ", 22);
		return NO_ERROR;
	}

	status_t onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
	{
        switch (code) 
        {
						case 1: {
							printf("onTransact called, case 1\n");
							int in_data = data.readInt32();
							
							reply->writeInt32(in_data * 2);
              return NO_ERROR;
            }
						case 2:{
              printf("onTransact called, case 2\n");
           	
            	return NO_ERROR;
            }
            case 3:{
              printf("onTransact called, case 3\n");
           			reply->writeFileDescriptor(fd);
            	return NO_ERROR;
            }
        }

        return BBinder::onTransact(code, data, reply, flags);
	}
};



int main(int argc, char** argv)
{		 
	sp < ProcessState > proc(ProcessState::self());
	sp < IServiceManager > sm = defaultServiceManager();

	sm->addService(String16("atest"), new myBinder());

	
	//test ashmem
	//ashmem_create_region and mmap is called in the init of MemoryHeapBase
	sp<MemoryHeapBase> heap = new MemoryHeapBase(32, 0, "testmem");
	if (heap != NULL)
	{
		pdata = (int32_t*)heap->getBase();
		if (pdata != NULL)
		{
			//*pdata = 1;
			pdata[0] = 1;
			pdata[1] = 2;
			pdata[2] = 3;
			pdata[3] = 4;
			
			
			int* pos = pdata;
			int* p0 = pdata;
	

			
			for (int i = 0; i < 4; i++)
			{
				cout << "data[" << i << "] = " << *(p0 + i) << endl;
			}
		}
		
		fd = heap->getHeapID();
		
	}
            
	printf("add myService\n");
        	
	ProcessState::self()->startThreadPool();
	IPCThreadState::self()->joinThreadPool();

	return 0;
}

服务端创建了共享内存,并且向里面写入了数据

再来测试下客户端使用这个共享内存

#include <stdio.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <iostream>
#include <iomanip>

#include <unistd.h>

//for lseek
#include <sys/types.h>

//for mmap
#include <sys/mman.h>

using namespace android;
using namespace std;

class Observer : public IBinder::DeathRecipient
{
public:
	//
	void binderDied(const wp<IBinder>& who)
	{
		printf("binderDied !\n"); 
	}
};

int main(int argc, char* const argv[])
{
    sp<IServiceManager> sm = defaultServiceManager();

    sp<IBinder> service = sm->checkService(String16("atest"));//test

    Parcel data;
    Parcel reply;

		int fd = -1;
    int err = service->transact(3, data, &reply, 0);
    if (err == NO_ERROR)
    {    		
    	fd = reply.readFileDescriptor();
        printf("\n get reply, result is %d \n", fd);
  //mmap   
  int32_t* base = (int32_t*)mmap(0, 64, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  cout << "base[0] = " << *base << " ,base[1] = " << base[1] << endl;
     
        int data = 0;
        //read 4 byte from fd to data
        read(fd, (void*)&data, 4);
        
        cout << "data is " << data << endl;
    }
    else
    {
    	printf("error \n");
    }


    return 0;
}


客户端对接收到的fd进行mmap操作后,获取到了映射的内存地址,就可以进行读写操作了,

客户端也可以使用read(fd)的方式去读取数据,但是需要注意的是,这会导致文件偏移,一般还是使用内存操作比较方便

相应的mk文件

LOCAL_PATH := $(call my-dir)

#for service

include $(CLEAR_VARS)


LOCAL_SRC_FILES:= \
        service.cpp 
        

LOCAL_SHARED_LIBRARIES := \
        libbase \
        libutils \
        liblog \
        libbinder


        
ifeq ($(TARGET_OS),linux)
        LOCAL_CFLAGS += -DXP_UNIX
        #LOCAL_SHARED_LIBRARIES += librt
endif

LOCAL_MODULE:= binderServer

include $(BUILD_EXECUTABLE)


#for client

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
        client.cpp 


LOCAL_SHARED_LIBRARIES := \
        libbase \
        libutils \
        liblog \
        libbinder

        
ifeq ($(TARGET_OS),linux)
        LOCAL_CFLAGS += -DXP_UNIX
        #LOCAL_SHARED_LIBRARIES += librt
endif

LOCAL_MODULE:= binderClient

include $(BUILD_EXECUTABLE)

发布了336 篇原创文章 · 获赞 13 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/aaajj/article/details/89716038
今日推荐