Android記憶體管理基礎,android記憶體管理
虛擬記憶體:將外儲存空間的部分空間作為記憶體的擴充,資源不足時按演算法儲存起來 當要用到資料區塊時交換回記憶體。邏輯地址=Segment Selector + Offset;線性地址物理地址Android系統記憶體配置和回收
Native層
智能指標的實現原理規避對象的產生和銷毀
Java層
相對C層做出了一定的努力,並對Android記憶體提供了管理機制
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);
start:映射區的開始地址
length:映射區的長度。
prot:期望的記憶體保護標誌(操作許可權)
flags:指定程式對記憶體塊的影響。
fd:有效檔案描述詞。一般是由open()函數返回
offset:被對應檔記憶體起點。
mmap將一個檔案或者其它對象映射進記憶體。檔案被映射到多個頁上,如果檔案的大小不是所有頁的大小之和,
最後一個頁不被使用的空間將會清零。
Android Low memory killer (LMK驅動)
/**以下代碼為kernel3.8_為例*/static int __init lowmem_init(void){ task_free_register(&task_nb); register_shrinker(&lowmem_shrinker); return 0;}//表示某一級要處理的對應的進程數static int lowmem_adj[6] = { 0, 1, 6, 12,};static int lowmem_adj_size = 4;//頁大小//表示當剩下記憶體少於對應層級時,執行清理操作。static size_t lowmem_minfree[6] = { 3 * 512, /* 6MB */ 2 * 1024, /* 8MB */ 4 * 1024, /* 16MB */ 16 * 1024, /* 64MB */};static int lowmem_minfree_size = 4;
3.如何知道需要被清理的進程,如下 Android定義了一系列的ADJ
static final int EMPTY_APP_ADJ = 15; //當前只運行了不可見Activity組件的進程 static final int HIDDEN_APP_MAX_ADJ = 15; static int HIDDEN_APP_MIN_ADJ = 7; //Luancher進程 static final int HOME_APP_ADJ = 6; // 2級服務 // system/rootdir/init.rc on startup. static final int SECONDARY_SERVER_ADJ = 5; // 承載backup相關操作進程 static final int BACKUP_APP_ADJ = 4; // 重量級應用程式進程 static final int HEAVY_WEIGHT_APP_ADJ = 3; // This is a process only hosting components that are perceptible to the // user, and we really want to avoid killing them, but they are not // immediately visible. An example is background music playback. Value set in // system/rootdir/init.rc on startup. static final int PERCEPTIBLE_APP_ADJ = 2; // 前台可見進程 static final int VISIBLE_APP_ADJ = 1; // 前台運行與使用者互動的進程 static final int FOREGROUND_APP_ADJ = 0; // 核心進程 如telephony進程 static final int CORE_SERVER_ADJ = -12; // 系統進程 static final int SYSTEM_ADJ = -16;
4.可以通過檔案修改某個進程對應ADJ值。也可以在application標籤中添加android:persistent=true屬性,
此屬性是將程式設定為常駐記憶體.
Android 匿名共用記憶體Anonymous Shared Momery
定義:將制定的物理地址映射到各個進程的虛擬位址空間中。
//early-init時載入ashmem.c檔案 如下調用ashmem_initstatic int __init ashmem_init(void){ //通過kmem_cache_create建立的kmem_cache //它的類型是struct kmem_cache,表示這是一個slab緩衝區,由核心中的記憶體管理系統進行管理。 ashmem_area_cachep = kmem_cache_create("ashmem_area_cache", sizeof(struct ashmem_area), 0, 0, NULL); ashmem_range_cachep = kmem_cache_create("ashmem_range_cache", sizeof(struct ashmem_range), 0, 0, NULL); ret = misc_register(&ashmem_misc); register_shrinker(&ashmem_shrinker); printk(KERN_INFO "ashmem: initialized\n"); return 0;}//ashmem時一個雜項裝置(misc device),他調用ashmem_misc註冊static struct miscdevice ashmem_misc = { .minor = MISC_DYNAMIC_MINOR, .name = "ashmem", .fops = &ashmem_fops,};//定義了進程間匿名共用記憶體的分配步驟ashmem_open,ashmem_ioctl,ashmem_mmap,ashmem_releasestatic struct file_operations ashmem_fops = { .owner = THIS_MODULE, .open = ashmem_open, .release = ashmem_release, .read = ashmem_read, .llseek = ashmem_llseek, .mmap = ashmem_mmap, .unlocked_ioctl = ashmem_ioctl, .compat_ioctl = ashmem_ioctl,};struct ashmem_area { char name[ASHMEM_FULL_NAME_LEN];// 這個名字會顯示/proc/<pid>/maps檔案中,<pid>表示開啟這個共用記憶體檔案的進程ID struct list_head unpinned_list; // 列表頭,它把這塊共用記憶體中所有被解鎖的記憶體塊串連在一起 struct file *file; // 域file表示這個共用記憶體在臨時檔案系統tmpfs中對應的檔案 size_t size; /* size of the mapping, in bytes */ unsigned long prot_mask; // 表示這塊共用記憶體的訪問保護位。};//建立記憶體指定檔案,操作記憶體即操作檔案static int ashmem_open(struct inode *inode, struct file *file){ struct ashmem_area *asma; int ret; ret = generic_file_open(inode, file); if (unlikely(ret)) return ret; //從ashmem_area_cachep分配一塊ashmem_area記憶體 asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL); if (unlikely(!asma)) return -ENOMEM; //設定名字 許可權等 INIT_LIST_HEAD(&asma->unpinned_list); memcpy(asma->name, ASHMEM_NAME_PREFIX, ASHMEM_NAME_PREFIX_LEN); asma->prot_mask = PROT_MASK; //記錄在private_data中 file->private_data = asma; return 0;}//為每個子模組建立單獨的記憶體static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg){ struct ashmem_area *asma = file->private_data; long ret = -ENOTTY; switch (cmd) { case ASHMEM_SET_NAME: ret = set_name(asma, (void __user *) arg); break; case ASHMEM_GET_NAME: ret = get_name(asma, (void __user *) arg); break; case ASHMEM_SET_SIZE: ret = -EINVAL; if (!asma->file) { ret = 0; asma->size = (size_t) arg; } break; ... break; } return ret;}//執行對子模組的映射static int ashmem_mmap(struct file *file, struct vm_area_struct *vma){ struct ashmem_area *asma = file->private_data; int ret = 0; mutex_lock(&ashmem_mutex);//互斥鎖 /* 通過ioctl設定大小 */ if (unlikely(!asma->size)) { ret = -EINVAL; goto out; } //請求的許可權保護必須匹配我們設定的許可權值 if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask)) & calc_vm_prot_bits(PROT_MASK))) { ret = -EPERM; goto out; } vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_mask); if (!asma->file) {//建立asm的臨時支援檔案 char *name = ASHMEM_NAME_DEF; struct file *vmfile; if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') name = asma->name; //由linux提供的在tmpfs中建立一個臨時檔案 vmfile = shmem_file_setup(name, asma->size, vma->vm_flags); if (unlikely(IS_ERR(vmfile))) { ret = PTR_ERR(vmfile); goto out; } asma->file = vmfile; } get_file(asma->file); if (vma->vm_flags & VM_SHARED) shmem_set_file(vma, asma->file);//記憶體映射 else { if (vma->vm_file) fput(vma->vm_file); vma->vm_file = asma->file; } vma->vm_flags |= VM_CAN_NONLINEAR;out: mutex_unlock(&ashmem_mutex); return ret;}//清楚記憶體共用區static int ashmem_release(struct inode *ignored, struct file *file){ struct ashmem_area *asma = file->private_data; struct ashmem_range *range, *next; mutex_lock(&ashmem_mutex); list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) range_del(range); mutex_unlock(&ashmem_mutex); if (asma->file) fput(asma->file); kmem_cache_free(ashmem_area_cachep, asma); return 0;}
MemoryFile.java
public MemoryFile(String name, int length) throws IOException { mLength = length; mFD = native_open(name, length); ...}private static native FileDescriptor native_open(String name, int length) throws IOException;
android_os_MemoryFile.cpp
static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length){ ... int result = ashmem_create_region(namestr, length); ...}
\system\core\libcutils\ashmem-dev.c
int ashmem_create_region(const char *name, size_t size){ int fd, ret; fd = open(ASHMEM_DEVICE, O_RDWR); if (fd < 0) return fd; if (name) { ... ret = ioctl(fd, ASHMEM_SET_NAME, buf); ... } ret = ioctl(fd, ASHMEM_SET_SIZE, size); ... return fd;error: close(fd); return ret;}
MemoryFile.java
public MemoryFile(String name, int length) throws IOException { ...... mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE); ...... }
android_os_MemoryFile.cpp
static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor, jint length, jint prot) { ... jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0); ... return result; }
未完。。。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。