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.csdn.net/download/new_abc/4744981