匿名共享内存Ashmem实例--C++

ashmem主要 用于两个进程 的内存共享.

使用步骤:

1、server端调用ashmem_create_region创建一个共享内存,调用mmap进行内存映射,并把这个fd通过binder返回给client端面

2、client使用从server端拿到的句柄fd,调用mmap进行内存映射,这样client和server端 就映射到了同一块内存区域,从而实现共享。

相关代码实现

首先看一下binder基类

#ifndef ANDROID_ITESTBINDERSERVICE_H_
#define ANDROID_ITESTBINDERSERVICE_H_

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>


namespace android {

class Parcel;

class ITestBinderService: public IInterface {
public:
	DECLARE_META_INTERFACE(TestBinderService);
	virtual int allocbuf(int pipe_fd, const char* name, int bs) = 0;
};

class BnTestBinderService: public BnInterface<ITestBinderService> {
public:
	virtual status_t onTransact(uint32_t code, const Parcel& data,
			Parcel* reply, uint32_t flags = 0);
};

}

#endif /* ANDROID_ITESTBINDERSERVICE_H_ */

定义一个ITestBinderService的基类,还有一个BnTestBinderService实现binder的Bn服务端,这里定义了一个方法allocbuf,传入一个管道的一端面,还有共享内存的名字,长度。

现来看一下Bp的实现

#include <utils/Log.h>

#include "../TestBinderServer_new/ITestBinderService.h"

namespace android {

enum {
	TEST_ALLOCBUF = IBinder::FIRST_CALL_TRANSACTION,
};

class BpTestBinderService: public BpInterface<ITestBinderService> {
public:
	BpTestBinderService(const sp<IBinder>& impl) :
		BpInterface<ITestBinderService> (impl) {
	}

	int allocbuf(int pipe_fd, const char* name, int bs) {
			Parcel data, reply;
		LOGI("Enter BpTestBinderService allocbuf,pipe_fd = %d , bs = %d", pipe_fd, bs);
		data.writeInterfaceToken(ITestBinderService::getInterfaceDescriptor());
		data.writeFileDescriptor(pipe_fd);
		data.writeCString(name);
		data.writeInt32(bs);
		remote()->transact(TEST_ALLOCBUF, data, &reply);
		int fd = reply.readFileDescriptor();
		LOGI("BpTestBinderService fd = %d", fd);
		 int fd2 = dup(fd);
		 LOGI("fd2 = %d", fd2);
		 perror("3dup: ");
		return fd2;
		
	}
};

IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService");

// ----------------------------------------------------------------------

status_t BnTestBinderService::onTransact(uint32_t code, const Parcel& data,
		Parcel* reply, uint32_t flags) {
	switch (code) {


	case TEST_ALLOCBUF: {
		
		CHECK_INTERFACE(ITestBinderService, data, reply);
		int pipe_fd = data.readFileDescriptor();
		const char *name = data.readCString();
		int bs = data.readInt32();
		
		LOGI("Enter BnTestBinderService add,pipe_fd = %d , bs = %d", pipe_fd, bs);
		int sum = 0;
		int fd  = allocbuf(pipe_fd, name, bs);
		LOGI("2BnTestBinderService fd = %d", fd);
		 reply->writeFileDescriptor(fd);
		 int fd2= dup(fd);
		  LOGI("fd2 = %d", fd2);
		 perror("2dup: ");
		return sum;
	}
	default:
		return BBinder::onTransact(code, data, reply, flags);
	}
}
Bp端调用writeFileDescriptor把管道句柄写进去,然后和Server端面通信后读出共享内存的句柄,注意这里是调用writeFileDescriptor和readFileDescriptor,还有一个就是在Server端返回后,读到的句柄要dup,否则直接使用会报错,而且好像必须这里返回之后就必须 dup,如果直接返回fd再dup好像也是会有问题

BnTestBinderService则恰好相反,读到相关参数,调用allocbuf函数,再把结果返回给Client端

再来看一下TestBinderService,主要是实现了BnTestBinderService

#include <utils/KeyedVector.h>
#include "ITestBinderService.h"

namespace android {

class TestBinderService: public BnTestBinderService {
public:
	static void instantiate();
	int add(int a,int b);
	int allocbuf(int pipe_fd, const char* name, int bs);
	static void* test_proc(void*a);

	
private:
	TestBinderService();
	virtual ~TestBinderService();
};

}

#include <utils/Log.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/mman.h>
#include <cutils/ashmem.h>

#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "binderservice.h"
#include "TestBinderService.h"


static int m_fd ;
static int m_pipe_fd;
char *m_buf;
namespace android {



void TestBinderService::instantiate() {
	LOGI("Enter TestBinderService::instantiate");
	status_t st = defaultServiceManager()->addService(
			String16("my.test.binder"), new TestBinderService());
	LOGD("ServiceManager addService ret=%d", st);
	LOGD("instantiate> end");
}

TestBinderService::TestBinderService() {
	m_fd = -1;
	m_buf = NULL;
	m_pipe_fd = -1;
	LOGD(" TestBinderServicet");
}

TestBinderService::~TestBinderService() {
	LOGD("TestBinderService destroyed,never destroy normally");
}

void* TestBinderService::test_proc(void*a) {
	char buf[100];
	int len = 100;
	int read_len = -1;
	int write_len = -1;
	while(1)
	{
		read_len = read(m_pipe_fd, buf, 12);
		LOGI("TestBinderService::read_len = %d.buf = %s",read_len, buf);	
		sleep(1);
		if(read_len > 0)
		{
			//write_len = write(m_fd, "from server", 12);
			strncpy(m_buf, "from server", 12);
		}
		LOGI("TestBinderService::write_len = %d.",write_len);
	}
	
	return NULL;
}

int TestBinderService::allocbuf(int pipe_fd, const char* name, int bs) {
	int result = -1;
	pthread_t th;
	
	LOGI("TestBinderService::allocbuf pipe_fd = %d, bs = %d.", pipe_fd , bs);	
	m_pipe_fd = dup(pipe_fd);
	LOGI("m_pipe_fd = %d", m_pipe_fd);
	m_fd = ashmem_create_region(name, bs);
	if(m_fd > 0)
	{
		m_buf = (char *)mmap(0, bs, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd , 0);
		if(m_buf == (void*)-1)
			LOGI("TestBinderService mmap fail");
	}
	LOGI("TestBinderService::m_fd = %d. m_buf = 0x%x",m_fd, m_buf);	
	 int fd2 = dup(m_fd);
	 LOGI("fd2 = %d", fd2);
	 perror("1dup: ");
	pthread_create(&th, NULL, test_proc, NULL);
	return m_fd;
} 


}

这里调用ashmem_create_region 创建匿名共享内存,然后调用mmap进行内存映射,创建一个线程,从管道读数据,并拷贝数据到共享内存

接下来就要启动这个Service

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>


#include "TestBinderService.h"

using namespace android;

int main(int argc, char** argv)
 {
	
	sp<ProcessState> proc(ProcessState::self());
	sp<IServiceManager> sm = defaultServiceManager();
	LOGI("TestBinderService before");
	TestBinderService::instantiate();
	LOGI("TestBinderService End");
	ProcessState::self()->startThreadPool();
	IPCThreadState::self()->joinThreadPool();
	return 0;

}

再就是测试case

#include <binder/IServiceManager.h>
#include "../TestBinderServer_new/ITestBinderService.h"
//#include	"testBinder.h"

#include "TestBinderService.h"

using namespace android;


int write_pipe_fd = -1;
int m_fd = -1;
char *m_buf = NULL;
static void* test_proc(void*a) {
	char buf[100];
	int len = 100;
	int read_len = -1;
	int write_len = -1;
	while(1)
	{
		write_len = write(write_pipe_fd, "from client", 12);
		
		LOGI("TestBinderClient::write_len = %d.",write_len);	
		sleep(1);
		if(write_len > 0)
		{
			
		}
		if(m_buf != (void*)-1)
			LOGI("TestBinderClient::read_len = %d.m_buf = %s",read_len, m_buf);
	}
	
	return NULL;
}
int main()
{
	int sum = 0;
	pthread_t th;	
	sp<ITestBinderService> mTestBinserService;
	if (mTestBinserService.get() == 0) {
		sp<IServiceManager> sm = defaultServiceManager();
		sp<IBinder> binder;
		do {
			binder = sm->getService(String16("my.test.binder"));
			if (binder != 0)
				break;
				LOGI("getService fail");
			usleep(500000); // 0.5 s
		} while (true);
		mTestBinserService = interface_cast<ITestBinderService> (binder);
		LOGE_IF(mTestBinserService == 0, "no ITestBinserService!?");
	}
	
	sum = mTestBinserService->add(3, 4);
	int pipe_fd[2];
	pipe(pipe_fd);
	write_pipe_fd = pipe_fd[1];
	LOGI("pipe_fd[0] = %d, pipe_fd[1] = %d", pipe_fd[0], pipe_fd[1]);
	 m_fd = mTestBinserService->allocbuf(pipe_fd[0], "test", 1024);
	 close(pipe_fd[0]);
	 LOGI("m_fd = %d", m_fd);
	 m_fd = dup(m_fd);
	 perror("dup: ");
	 LOGI("m_fd = %d", m_fd);
	m_buf = (char *)mmap(0, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd , 0);
	if(m_buf == (void*)-1){
			LOGI("TestBinderService mmap fail");
			perror("mmap: ");}
	 LOGI("m_fd = %d m_buf = 0x%x", m_fd, m_buf);
	pthread_create(&th, NULL, test_proc, NULL);
	close(pipe_fd[0]);
	while(1)
		sleep(1);
	
	return 0;

}

首先获取Service,然后调用allocbuf把管道的读端传过去,返回一个共享内在的句柄后,调用mmap进行内存映射,同样也是新建一个进程,不断的往管道里面写数据,然后把映射的共享内存的值打印出来,这个值是Service端写进去的。

相应log:

I/        ( 1433): TestBinderService before
I/TestBinderService( 1433): Enter TestBinderService::instantiate
D/TestBinderService( 1433):  TestBinderServicet
D/TestBinderService( 1433): ServiceManager addService ret=0
D/TestBinderService( 1433): instantiate> end
I/        ( 1433): TestBinderService End
D/KeyguardUpdateMonitor( 1058): received broadcast android.intent.action.TIME_TICK
D/KeyguardUpdateMonitor( 1058): handleTimeUpdate
I/        ( 1436): int the main function
I/ITeeveePlayerService( 1436): Enter BpTestBinderService add,a = 3 , b = 4
I/ITeeveePlayerService( 1433): Enter BnTestBinderService add,a = 3 , b = 4
I/TestBinderService( 1433): TestBinderService::add a = 3, b = 4.
D/        ( 1433):  sum2 a = 3, b = 4
I/TestBinderService( 1433): TestBinderService::result = 7.
I/ITeeveePlayerService( 1433): BnTestBinderService sum = 7
I/ITeeveePlayerService( 1436): BpTestBinderService sum = 7
I/TestBinserService( 1436): pipe_fd[0] = 28, pipe_fd[1] = 29
I/ITeeveePlayerService( 1436): Enter BpTestBinderService allocbuf,pipe_fd = 28 , bs = 1024
I/ITeeveePlayerService( 1433): Enter BnTestBinderService add,pipe_fd = 28 , bs = 1024
I/TestBinderService( 1433): TestBinderService::allocbuf pipe_fd = 28, bs = 1024.
I/TestBinderService( 1433): m_pipe_fd = 29
I/TestBinderService( 1433): TestBinderService::m_fd = 30. m_buf = 0x40107000
I/TestBinderService( 1433): fd2 = 31
I/ITeeveePlayerService( 1433): 2BnTestBinderService fd = 30
I/ITeeveePlayerService( 1433): fd2 = 32
I/ITeeveePlayerService( 1436): BpTestBinderService fd = 30
I/ITeeveePlayerService( 1436): fd2 = 31
I/TestBinserService( 1436): m_fd = 31
I/TestBinserService( 1436): m_fd = 28
I/TestBinserService( 1436): m_fd = 28 m_buf = 0x40107000
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server
I/TestBinserService( 1436): TestBinderClient::write_len = 12.
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client
init: untracked pid 1436 exited
I/TestBinderService( 1433): TestBinderService::write_len = -1.
I/TestBinderService( 1433): TestBinderService::read_len = 0.buf = from client
init: untracked pid 1433 exited
I/ServiceManager(  766): service 'my.test.binder' died


实例代码:

http://download.youkuaiyun.com/download/new_abc/4744981

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值