Android系统实现用户态swap(研究贴)

一. Android下用户态swap的意义

二. Android下用户态swap的实现方法

1. 首先实现系统调用swap_process

(在Andriod的内核层实现系统调用,可以参考我前面的文章。)

2. $kernel/mm/swap_state.c

定义系统调用函数swap_process,参数为pid(用户层传过来的进程id)

/**
 * swap inactive pages of process with pid
 */
SYSCALL_DEFINE1(swap_process, pid_t, pid)
{
	struct task_struct* p = NULL;
	LIST_HEAD(pagelist);
	unsigned long nr_reclaimed_pages = 0;

	//1. find the process ds() through pid
	printk(KERN_INFO "user pid: %d\n", pid);
	p = find_task_by_pid_ns(pid, current->nsproxy->pid_ns);
	if(NULL == p)
	{
		printk(KERN_ERR "+++could not find task_struct with the pid+++\n");
		return 0;
	}

	//2. filter the inactive pages and add them to swap cache
	traverse_pages(p, &pagelist);

	//3. swap out pages
	if(!list_empty(&pagelist)){
		//path: mm/vmscan.c
		nr_reclaimed_pages = shrink_process_list(&pagelist);
		printk(KERN_INFO "reclaimed pages: %lu\n", nr_reclaimed_pages);
	}
	
	return (int)nr_reclaimed_pages;
}


遍历进程的地址空间(各个线性区)

/**
 * traverse the page frames of the given process
 * parameter: process des, 
 */
int traverse_pages(struct task_struct* p, struct list_head *pagelist)
{
	struct mm_struct* mm = NULL;
	struct vm_area_struct* temp_vm = NULL;
	struct vm_area_struct* init_vm = NULL;
	struct page * reclaim_page = NULL;
	unsigned long PAGE_INNER = (1 << PAGE_SHIFT) -1, temp_addr = 0;
	int inactive_page_count = 0;
	int err = 0;
	LIST_HEAD(page_list);

	if(!p)
		goto out;
	
	mm = p->mm;
	if(!mm)
		goto out;
	
	down_read(&mm->mmap_sem);

	init_vm = mm->mmap;
	temp_vm = init_vm;
	
	do{
		if(temp_vm->vm_flags)
		for(temp_addr=temp_vm->vm_start; temp_addr < temp_vm->vm_end; temp_addr+=PAGE_SIZE)
		{
			if(!(temp_addr & PAGE_INNER))
			{
				//reclaim_page = get_inactive_page(mm, temp_addr);
				reclaim_page = follow_page(temp_vm, temp_addr, FOLL_GET|FOLL_SPLIT);
				if(IS_ERR(reclaim_page) || !reclaim_page)
					continue;
				
				err = isolate_lru_page(reclaim_page);
				if(!err){
				//if(page_lru(reclaim_page) == LRU_INACTIVE_ANON){
					list_add_tail(&reclaim_page->lru, pagelist);
					inc_zone_page_state(reclaim_page, NR_ISOLATED_ANON + page_is_file_cache(reclaim_page));
					inactive_page_count++;
				//}
				}
			}
		}

		if(temp_vm->vm_next == NULL)
			break;
		temp_vm = temp_vm->vm_next;
	}while(true);

	printk(KERN_INFO "swap process success: inactive pages = %d map_count:%d\n", inactive_page_count, mm->map_count);

	up_read(&mm->mmap_sem);
	return 1;
out:
	up_read(&mm->mmap_sem);
	printk(KERN_ERR "traverse page error!\n");
	return 0;
}


根据线性地址找到页表项,进而找到数据所处的物理页面
/**
 * get inactive pages of the given linear address
 * parameter: pgd, linear addr
 */
struct page* get_inactive_page(struct mm_struct* mm, unsigned long addr)
{
	struct page* inactive_page = NULL;
	pgd_t* pgd;
	pmd_t* pmd;
	pte_t* pte;

	pgd = pgd_offset(mm, addr);
	if(pgd_none(*pgd) || pgd_bad(*pgd))
		goto out;

	//pmd = pmd_offset(pgd, addr);
	pmd = (pmd_t*) pgd;
	if(pmd_none(*pmd) || pmd_bad(*pmd))
		goto out;
	
	pte = pte_offset_map(pmd, addr);
	if(!pte)
		goto out;

	inactive_page = pte_page(*pte);

	if(page_lru(inactive_page) == LRU_INACTIVE_ANON)
		return inactive_page;

out:
	printk(KERN_ERR "+++walk through invalid page table+++\n");
	return NULL;
}


3. $kernel/mm/vmscan.c

将指定的页面链表换出到flash swap区域

unsigned long shrink_process_list(struct list_head *pagelist)
{
	int priority = 0;
	unsigned long ret_nr_dirty = 0, ret_nr_writeback = 0, nr_reclaimed_pages = 1;
	struct zone *zone;
	struct scan_control sc = {
		.gfp_mask = GFP_USER,
		.may_writepage = !laptop_mode,
		.nr_to_reclaim = SWAP_CLUSTER_MAX,
		.may_unmap = 1,
		.may_swap = 1,
		.order = 0,
		.target_mem_cgroup = NULL,
	};
	struct mem_cgroup *root = sc.target_mem_cgroup;
	struct mem_cgroup_reclaim_cookie reclaim = {
		.priority = priority,
	};
	struct mem_cgroup *memcg;

	struct mem_cgroup_zone mz;

	struct page *page = lru_to_page(pagelist);
	zone = page_zone(page);

	reclaim.zone = zone;

	memcg = mem_cgroup_iter(root, NULL, &reclaim);
	mz.mem_cgroup = memcg;
	mz.zone = zone;

	nr_reclaimed_pages = shrink_page_list(pagelist, &mz, &sc, priority, &ret_nr_dirty, &ret_nr_writeback);
	
	return nr_reclaimed_pages;
}

三. 评估以及后记

你可能感兴趣的:(Android编程,Linux,c++,c语言)