ashmem

ashmem是android的内存分配/共享机制,在dev目录下对应的设备是/dev/ashmem,相比于传统的内存分配机制,如malloc、anonymous/namedmmap,其好处是提供了辅助内核内存回收算法的pin/unpin机制。

ashmme的典型用法是先打开设备文件,然后做mmap映射。

第一步通过调用ashmem_create_region函数,这个函数完成这几件事:

1)fd = open("/dev/ashmem", O_RDWR);
2)ioctl(fd, ASHMEM_SET_NAME, region_name); // 这一步可选
3)ioctl(fd, ASHMEM_SET_SIZE, region_size);

第二步,应用程序一般会调用mmap来把ashmem分配的空间映射到进程空间:

mapAddr = mmap(NULL, pHdr->mapLength, PROT_READ |PROT_WRITE, MAP_PRIVATE, fd, 0);

应用程序还可以通过ioctl来pin和unpin某一段映射的空间,以提示内核的pagecache算法可以把哪些页面回收,这是一般mmap做不到的。

可以说ashmem以较小的代价(用户需进行额外的ioctl调用来设置名字,大小,pin和unpin),获得了一些内存使用的智能性。

ashmem本身实现也很小巧,只有不到700行。原因是借助了内核已经有的工具,例如shmem_file_setup(支撑文件),cache_shrinker(slab分配算法的页面回收的回调函数)等。

如果ashmem不使用内核驱动实现,则pin/unpin的语义比较难以实现,或者即使实现,效率也不会很高。但查询android源码,使用pin/unpin很少,看来ashmem还是没有很好地用起来。

如果不使用ashmem驱动,并且舍弃pin/unpin语义,那么模拟ashmem的语义还是很简单的。首先,ashmem_create_region可以为进程创建一个唯一的文件(如进程名+时戳),打开,然后返回这个文件的fd;接着应用程序可以进性一般的mmap操作了。如果不使用ashmem_create_region接口函数,那么使用anonymous的mmap就可以了,但这种方式属于正在被丢弃的方式,而且并不是所有的系统都支持,比如Macos就不支持。


几个与内存相关的类的头文件如下所示:
IMemory.h:定义内存相关类的接口,表示堆内存的类IMemoryHeap和BnMemoryHeap,表示一般内存的类IMemory和BnMemory。
MemoryHeapBase.h:定义类MemoryHeapBase,继承并实现BnMemoryHeap
MemoryBase.h:定义类MemoryBase,继承并实现BnMemory
在一般的使用过程中,通常是以使用MemoryHeapBase类分配一块堆内存(类似malloc),而MemoryBase表示从一块分配好堆内存中的一部分内存。

class AudioTrackJniStorage {

public:

sp<MemoryHeapBase>mMemHeap;//这两个Memory很重要

sp<MemoryBase>mMemBase;

audiotrack_callback_cookie mCallbackData;

intmStreamType;

bool allocSharedMem(int sizeInBytes) {

mMemHeap = new MemoryHeapBase(sizeInBytes, 0, "AudioTrack Heap Base");

mMemBase = new MemoryBase(mMemHeap, 0, sizeInBytes);

//注意用法,先弄一个HeapBase,再把HeapBase传入到MemoryBase中去。

return true;

}

};

2 MemoryHeapBase

MemroyHeapBase也是Android搞的一套基于Binder机制的对内存操作的类。既然是Binder机制,那么肯定有一个服务端(Bnxxx),一个代理端Bpxxx。看看MemoryHeapBase定义:

class MemoryHeapBase : public virtual BnMemoryHeap

{

果然,从BnMemoryHeap派生,那就是Bn端。这样就和Binder挂上钩了

//Bp端调用的函数最终都会调到Bn这来

对Binder机制不了解的,可以参考:

http://blog.csdn.net/Innost/archive/2011/01/08/6124685.aspx

有好几个构造函数,我们看看我们使用的:

MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)

: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),

mDevice(0), mNeedUnmap(false)

{

const size_t pagesize = getpagesize();

size = ((size + pagesize-1) & ~(pagesize-1));

//创建共享内存,ashmem_create_region这个是系统提供的,可以不管它

//设备上打开的是/dev/ashmem设备,而Host上打开的是一个tmp文件

int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size);

mapfd(fd, size);//把刚才那个fd通过mmap方式得到一块内存

//不明白得去man mmap看看

mapfd完了后,mBase变量指向内存的起始位置, mSize是分配的内存大小,mFd是

ashmem_create_region返回的文件描述符

}

MemoryHeapBase提供了一下几个函数,可以获取共享内存的大小和位置。

getBaseID()--->返回mFd,如果为负数,表明刚才创建共享内存失败了

getBase()->返回mBase,内存位置

getSize()->返回mSize,内存大小

有了MemoryHeapBase,又搞了一个MemoryBase,这又是一个和Binder机制挂钩的类。

唉,这个估计是一个在MemoryHeapBase上的方便类吧?因为我看见了offset

那么估计这个类就是一个能返回当前Buffer中写位置(就是offset)的方便类

这样就不用用户到处去计算读写位置了。


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

使用步骤:

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

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

相关代码实现

首先看一下binder基类

  1. #ifndef ANDROID_ITESTBINDERSERVICE_H_  
  2. #define ANDROID_ITESTBINDERSERVICE_H_  
  3.   
  4. #include <utils/RefBase.h>  
  5. #include <binder/IInterface.h>  
  6. #include <binder/Parcel.h>  
  7.   
  8.   
  9. namespace android {  
  10.   
  11. class Parcel;  
  12.   
  13. class ITestBinderService: public IInterface {  
  14. public:  
  15.     DECLARE_META_INTERFACE(TestBinderService);  
  16.     virtual int allocbuf(int pipe_fd, const char* name, int bs) = 0;  
  17. };  
  18.   
  19. class BnTestBinderService: public BnInterface<ITestBinderService> {  
  20. public:  
  21.     virtual status_t onTransact(uint32_t code, const Parcel& data,  
  22.             Parcel* reply, uint32_t flags = 0);  
  23. };  
  24.   
  25. }  
  26.   
  27. #endif /* ANDROID_ITESTBINDERSERVICE_H_ */  

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

现来看一下Bp的实现

  1. #include <utils/Log.h>  
  2.   
  3. #include "../TestBinderServer_new/ITestBinderService.h"  
  4.   
  5. namespace android {  
  6.   
  7. enum {  
  8.     TEST_ALLOCBUF = IBinder::FIRST_CALL_TRANSACTION,  
  9. };  
  10.   
  11. class BpTestBinderService: public BpInterface<ITestBinderService> {  
  12. public:  
  13.     BpTestBinderService(const sp<IBinder>& impl) :  
  14.         BpInterface<ITestBinderService> (impl) {  
  15.     }  
  16.   
  17.     int allocbuf(int pipe_fd, const char* name, int bs) {  
  18.             Parcel data, reply;  
  19.         LOGI("Enter BpTestBinderService allocbuf,pipe_fd = %d , bs = %d", pipe_fd, bs);  
  20.         data.writeInterfaceToken(ITestBinderService::getInterfaceDescriptor());  
  21.         data.writeFileDescriptor(pipe_fd);  
  22.         data.writeCString(name);  
  23.         data.writeInt32(bs);  
  24.         remote()->transact(TEST_ALLOCBUF, data, &reply);  
  25.         int fd = reply.readFileDescriptor();  
  26.         LOGI("BpTestBinderService fd = %d", fd);  
  27.          int fd2 = dup(fd);  
  28.          LOGI("fd2 = %d", fd2);  
  29.          perror("3dup: ");  
  30.         return fd2;  
  31.           
  32.     }  
  33. };  
  34.   
  35. IMPLEMENT_META_INTERFACE(TestBinderService, "android.test.ITestBinderService");  
  36.   
  37. // ----------------------------------------------------------------------  
  38.   
  39. status_t BnTestBinderService::onTransact(uint32_t code, const Parcel& data,  
  40.         Parcel* reply, uint32_t flags) {  
  41.     switch (code) {  
  42.   
  43.   
  44.     case TEST_ALLOCBUF: {  
  45.           
  46.         CHECK_INTERFACE(ITestBinderService, data, reply);  
  47.         int pipe_fd = data.readFileDescriptor();  
  48.         const char *name = data.readCString();  
  49.         int bs = data.readInt32();  
  50.           
  51.         LOGI("Enter BnTestBinderService add,pipe_fd = %d , bs = %d", pipe_fd, bs);  
  52.         int sum = 0;  
  53.         int fd  = allocbuf(pipe_fd, name, bs);  
  54.         LOGI("2BnTestBinderService fd = %d", fd);  
  55.          reply->writeFileDescriptor(fd);  
  56.          int fd2= dup(fd);  
  57.           LOGI("fd2 = %d", fd2);  
  58.          perror("2dup: ");  
  59.         return sum;  
  60.     }  
  61.     default:  
  62.         return BBinder::onTransact(code, data, reply, flags);  
  63.     }  
  64. }  
Bp端调用writeFileDescriptor把管道句柄写进去,然后和Server端面通信后读出共享内存的句柄,注意这里是调用writeFileDescriptor和readFileDescriptor,还有一个就是在Server端返回后,读到的句柄要dup,否则直接使用会报错,而且好像必须这里返回之后就必须 dup,如果直接返回fd再dup好像也是会有问题

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

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

  1. #include <utils/KeyedVector.h>  
  2. #include "ITestBinderService.h"  
  3.   
  4. namespace android {  
  5.   
  6. class TestBinderService: public BnTestBinderService {  
  7. public:  
  8.     static void instantiate();  
  9.     int add(int a,int b);  
  10.     int allocbuf(int pipe_fd, const char* name, int bs);  
  11.     static void* test_proc(void*a);  
  12.   
  13.       
  14. private:  
  15.     TestBinderService();  
  16.     virtual ~TestBinderService();  
  17. };  
  18.   
  19. }  

  1. #include <utils/Log.h>  
  2. #include <pthread.h>  
  3. #include <unistd.h>  
  4. #include <sys/mman.h>  
  5. #include <cutils/ashmem.h>  
  6.   
  7. #include <binder/IServiceManager.h>  
  8. #include <binder/IPCThreadState.h>  
  9. #include "binderservice.h"  
  10. #include "TestBinderService.h"  
  11.   
  12.   
  13. static int m_fd ;  
  14. static int m_pipe_fd;  
  15. char *m_buf;  
  16. namespace android {  
  17.   
  18.   
  19.   
  20. void TestBinderService::instantiate() {  
  21.     LOGI("Enter TestBinderService::instantiate");  
  22.     status_t st = defaultServiceManager()->addService(  
  23.             String16("my.test.binder"), new TestBinderService());  
  24.     LOGD("ServiceManager addService ret=%d", st);  
  25.     LOGD("instantiate> end");  
  26. }  
  27.   
  28. TestBinderService::TestBinderService() {  
  29.     m_fd = -1;  
  30.     m_buf = NULL;  
  31.     m_pipe_fd = -1;  
  32.     LOGD(" TestBinderServicet");  
  33. }  
  34.   
  35. TestBinderService::~TestBinderService() {  
  36.     LOGD("TestBinderService destroyed,never destroy normally");  
  37. }  
  38.   
  39. void* TestBinderService::test_proc(void*a) {  
  40.     char buf[100];  
  41.     int len = 100;  
  42.     int read_len = -1;  
  43.     int write_len = -1;  
  44.     while(1)  
  45.     {  
  46.         read_len = read(m_pipe_fd, buf, 12);  
  47.         LOGI("TestBinderService::read_len = %d.buf = %s",read_len, buf);      
  48.         sleep(1);  
  49.         if(read_len > 0)  
  50.         {  
  51.             //write_len = write(m_fd, "from server", 12);  
  52.             strncpy(m_buf, "from server", 12);  
  53.         }  
  54.         LOGI("TestBinderService::write_len = %d.",write_len);  
  55.     }  
  56.       
  57.     return NULL;  
  58. }  
  59.   
  60. int TestBinderService::allocbuf(int pipe_fd, const char* name, int bs) {  
  61.     int result = -1;  
  62.     pthread_t th;  
  63.       
  64.     LOGI("TestBinderService::allocbuf pipe_fd = %d, bs = %d.", pipe_fd , bs);     
  65.     m_pipe_fd = dup(pipe_fd);  
  66.     LOGI("m_pipe_fd = %d", m_pipe_fd);  
  67.     m_fd = ashmem_create_region(name, bs);  
  68.     if(m_fd > 0)  
  69.     {  
  70.         m_buf = (char *)mmap(0, bs, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd , 0);  
  71.         if(m_buf == (void*)-1)  
  72.             LOGI("TestBinderService mmap fail");  
  73.     }  
  74.     LOGI("TestBinderService::m_fd = %d. m_buf = 0x%x",m_fd, m_buf);   
  75.      int fd2 = dup(m_fd);  
  76.      LOGI("fd2 = %d", fd2);  
  77.      perror("1dup: ");  
  78.     pthread_create(&th, NULL, test_proc, NULL);  
  79.     return m_fd;  
  80. }   
  81.   
  82.   
  83. }  

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

接下来就要启动这个Service

  1. #include <binder/IPCThreadState.h>  
  2. #include <binder/ProcessState.h>  
  3. #include <binder/IServiceManager.h>  
  4. #include <utils/Log.h>  
  5.   
  6.   
  7. #include "TestBinderService.h"  
  8.   
  9. using namespace android;  
  10.   
  11. int main(int argc, char** argv)  
  12.  {  
  13.       
  14.     sp<ProcessState> proc(ProcessState::self());  
  15.     sp<IServiceManager> sm = defaultServiceManager();  
  16.     LOGI("TestBinderService before");  
  17.     TestBinderService::instantiate();  
  18.     LOGI("TestBinderService End");  
  19.     ProcessState::self()->startThreadPool();  
  20.     IPCThreadState::self()->joinThreadPool();  
  21.     return 0;  
  22.   
  23. }  

再就是测试case

  1. #include <binder/IServiceManager.h>  
  2. #include "../TestBinderServer_new/ITestBinderService.h"  
  3. //#include  "testBinder.h"  
  4.   
  5. #include "TestBinderService.h"  
  6.   
  7. using namespace android;  
  8.   
  9.   
  10. int write_pipe_fd = -1;  
  11. int m_fd = -1;  
  12. char *m_buf = NULL;  
  13. static void* test_proc(void*a) {  
  14.     char buf[100];  
  15.     int len = 100;  
  16.     int read_len = -1;  
  17.     int write_len = -1;  
  18.     while(1)  
  19.     {  
  20.         write_len = write(write_pipe_fd, "from client", 12);  
  21.           
  22.         LOGI("TestBinderClient::write_len = %d.",write_len);      
  23.         sleep(1);  
  24.         if(write_len > 0)  
  25.         {  
  26.               
  27.         }  
  28.         if(m_buf != (void*)-1)  
  29.             LOGI("TestBinderClient::read_len = %d.m_buf = %s",read_len, m_buf);  
  30.     }  
  31.       
  32.     return NULL;  
  33. }  
  34. int main()  
  35. {  
  36.     int sum = 0;  
  37.     pthread_t th;     
  38.     sp<ITestBinderService> mTestBinserService;  
  39.     if (mTestBinserService.get() == 0) {  
  40.         sp<IServiceManager> sm = defaultServiceManager();  
  41.         sp<IBinder> binder;  
  42.         do {  
  43.             binder = sm->getService(String16("my.test.binder"));  
  44.             if (binder != 0)  
  45.                 break;  
  46.                 LOGI("getService fail");  
  47.             usleep(500000); // 0.5 s  
  48.         } while (true);  
  49.         mTestBinserService = interface_cast<ITestBinderService> (binder);  
  50.         LOGE_IF(mTestBinserService == 0, "no ITestBinserService!?");  
  51.     }  
  52.       
  53.     sum = mTestBinserService->add(3, 4);  
  54.     int pipe_fd[2];  
  55.     pipe(pipe_fd);  
  56.     write_pipe_fd = pipe_fd[1];  
  57.     LOGI("pipe_fd[0] = %d, pipe_fd[1] = %d", pipe_fd[0], pipe_fd[1]);  
  58.      m_fd = mTestBinserService->allocbuf(pipe_fd[0], "test", 1024);  
  59.      close(pipe_fd[0]);  
  60.      LOGI("m_fd = %d", m_fd);  
  61.      m_fd = dup(m_fd);  
  62.      perror("dup: ");  
  63.      LOGI("m_fd = %d", m_fd);  
  64.     m_buf = (char *)mmap(0, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd , 0);  
  65.     if(m_buf == (void*)-1){  
  66.             LOGI("TestBinderService mmap fail");  
  67.             perror("mmap: ");}  
  68.      LOGI("m_fd = %d m_buf = 0x%x", m_fd, m_buf);  
  69.     pthread_create(&th, NULL, test_proc, NULL);  
  70.     close(pipe_fd[0]);  
  71.     while(1)  
  72.         sleep(1);  
  73.       
  74.     return 0;  
  75.   
  76. }  

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

相应log:

  1. I/        ( 1433): TestBinderService before  
  2. I/TestBinderService( 1433): Enter TestBinderService::instantiate  
  3. D/TestBinderService( 1433):  TestBinderServicet  
  4. D/TestBinderService( 1433): ServiceManager addService ret=0  
  5. D/TestBinderService( 1433): instantiate> end  
  6. I/        ( 1433): TestBinderService End  
  7. D/KeyguardUpdateMonitor( 1058): received broadcast android.intent.action.TIME_TICK  
  8. D/KeyguardUpdateMonitor( 1058): handleTimeUpdate  
  9. I/        ( 1436): int the main function  
  10. I/ITeeveePlayerService( 1436): Enter BpTestBinderService add,a = 3 , b = 4  
  11. I/ITeeveePlayerService( 1433): Enter BnTestBinderService add,a = 3 , b = 4  
  12. I/TestBinderService( 1433): TestBinderService::add a = 3, b = 4.  
  13. D/        ( 1433):  sum2 a = 3, b = 4  
  14. I/TestBinderService( 1433): TestBinderService::result = 7.  
  15. I/ITeeveePlayerService( 1433): BnTestBinderService sum = 7  
  16. I/ITeeveePlayerService( 1436): BpTestBinderService sum = 7  
  17. I/TestBinserService( 1436): pipe_fd[0] = 28, pipe_fd[1] = 29  
  18. I/ITeeveePlayerService( 1436): Enter BpTestBinderService allocbuf,pipe_fd = 28 , bs = 1024  
  19. I/ITeeveePlayerService( 1433): Enter BnTestBinderService add,pipe_fd = 28 , bs = 1024  
  20. I/TestBinderService( 1433): TestBinderService::allocbuf pipe_fd = 28, bs = 1024.  
  21. I/TestBinderService( 1433): m_pipe_fd = 29  
  22. I/TestBinderService( 1433): TestBinderService::m_fd = 30. m_buf = 0x40107000  
  23. I/TestBinderService( 1433): fd2 = 31  
  24. I/ITeeveePlayerService( 1433): 2BnTestBinderService fd = 30  
  25. I/ITeeveePlayerService( 1433): fd2 = 32  
  26. I/ITeeveePlayerService( 1436): BpTestBinderService fd = 30  
  27. I/ITeeveePlayerService( 1436): fd2 = 31  
  28. I/TestBinserService( 1436): m_fd = 31  
  29. I/TestBinserService( 1436): m_fd = 28  
  30. I/TestBinserService( 1436): m_fd = 28 m_buf = 0x40107000  
  31. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  32. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  33. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  34. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  35. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  36. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  37. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  38. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  39. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  40. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  41. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  42. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  43. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  44. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  45. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  46. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  47. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  48. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  49. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  50. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  51. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  52. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  53. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  54. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  55. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  56. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  57. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  58. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  59. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  60. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  61. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  62. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  63. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  64. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  65. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  66. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  67. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  68. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  69. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  70. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  71. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  72. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  73. I/TestBinserService( 1436): TestBinderClient::read_len = -1.m_buf = from server  
  74. I/TestBinserService( 1436): TestBinderClient::write_len = 12.  
  75. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  76. I/TestBinderService( 1433): TestBinderService::read_len = 12.buf = from client  
  77. init: untracked pid 1436 exited  
  78. I/TestBinderService( 1433): TestBinderService::write_len = -1.  
  79. I/TestBinderService( 1433): TestBinderService::read_len = 0.buf = from client  
  80. init: untracked pid 1433 exited  
  81. I/ServiceManager(  766): service 'my.test.binder' died  


实例代码:

http://download.csdn.NET/download/new_abc/4744981


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个 Android 应用程序的内存使用情况输出,其中: - Pss 表示应用程序的实际内存使用量; - Private Dirty 表示应用程序的私有内存使用量; - Private Clean 表示应用程序的私有干净内存使用量; - Swap 表示应用程序的交换内存使用量; - Heap Size 表示应用程序的堆内存总大小; - Heap Alloc 表示应用程序的堆内存已分配大小; - Heap Free 表示应用程序的堆内存未分配大小。 具体来说,输出结果中的各字段含义如下: - Native Heap 表示应用程序的本地堆内存使用情况,其中 Pss 表示实际内存使用量,Private 表示私有内存使用量,Private Clean 和 Private Dirty 分别表示私有干净内存和私有脏内存使用量; - Dalvik Heap 表示应用程序的 Dalvik 堆内存使用情况,其中 Pss 表示实际内存使用量,Private 表示私有内存使用量,Private Clean 和 Private Dirty 分别表示私有干净内存和私有脏内存使用量; - Dalvik Other 表示应用程序的 Dalvik 其他内存使用情况,其中 Pss 表示实际内存使用量,Private 表示私有内存使用量; - Stack、Ashmem、Gfx dev、Other dev、.so mmap、.jar mmap、.apk mmap、.ttf mmap、.dex mmap、.oat mmap、.art mmap、Other mmap、EGL mtrack、GL mtrack、Unknown 分别表示应用程序的栈内存、匿名共享内存、图形设备显存、其他设备显存、共享库内存、Java 包文件内存、安装包文件内存、字体文件内存、Dalvik 可执行文件内存、OAT 可执行文件内存、ART 可执行文件内存、其他内存、EGL 内存跟踪、GL 内存跟踪、未知内存的使用情况,其中 Pss 表示实际内存使用量,Private 和 Private Dirty 表示私有内存使用量; - TOTAL 表示应用程序的总内存使用情况,其中 Pss 表示实际内存使用量,Private 和 Private Dirty 分别表示私有内存使用量,Clean 表示干净内存使用量,Swap 表示交换内存使用量,Heap Size、Heap Alloc 和 Heap Free 分别表示堆内存总大小、已分配大小和未分配大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值