Linux内核内存管理( 八 )


返回;
一旦写操作完成,()被执行 。该函数唤醒等待页面标志清除的进程,清除标志,是否bio描述符 。
换入页面
换入页面操作发生在一个进程访问被换出到磁盘上的页面时 。当下列条件发生时页面出错处理程序会进行换入操作:
包含引发异常的地址的页面是一个当前进程内存区域的有效页面;
该页面不在内存中,PTE的页面present表示被清0;
与页面相关的pte不为null,Dirty位被清0,这意味着该pte包含换出页的标志;
当上述条件同时满足时,()调用()函数换入请求页面 。
(*mm,*vma,
long , pte_t *, pmd_t *pmd,
int , pte_t )
该函数处理流程如下:
entry = pte_to_swp_entry(orig_pte)得到交换槽位信息;
page = lookup_swap_cache(entry)查看交换槽对应的页面是否存在于交换缓存中,如果是则跳到第6步;
调用swapin_readahead(entry, address, vma)从交换区中读取一组页面,对每个页面调用read_swap_cache_async()读取该页面;
对于进程访问异常的页面再次调用read_swap_cache_async() 。因为swapin_readahead调用可能失败,在它成功的情况下read_swap_cache_async()发现该页面在交换缓存里,很快返回;
如果页面还是没有在交换缓存中,可能存在其他内核控制路径已经把该页面换入 。比较page_table对应的pte内容与orig_pte是否相同,如果不同,说明页面已经换入 。函数跳出返回 。
如果页面在交换缓存中,调用mark_page_accessed并锁住该页面;
pte_offset_map_lock(mm, pmd, address, &ptl)获取page_table对应的pte内容,与orig_pte比较,判断是否有其他内核控制路径进行换入操作;
测试PG_uptodate标志,如果未设置,则出错返回;
增加mm->anon_rss的计数;
(page, vma->)创建PTE并设置标志,插入到进程页表中;()为该匿名页插入反向映射数据结构的内容;(entry)释放页槽;检查交换缓存负载是否达到50%,如果是,并且该页面仅被触发页面访问异常的进程占有,则从交换缓存中释放该页 。如果标志为1,说明是COW写时复制,调用()拷贝一份该页面;
释放页锁和页面缓存等,并返回结果 。
【反碎片技术】
1、虚拟可移动区域
2、内存碎片整理
3、内存碎片防治技术
正文
Linux 组织管理物理内存的方式是buddy (伙伴系统),而物理内存碎片正式buddy 的弱点之一,为了预防以及解决碎片问题,采取了一些实用技术,这里将对这些技术进行总结归纳 。
回到顶部
1 低内存时整合碎片
从buddy申请内存页,如果找不到合适的页,则会进行两步调整内存的工作,和 。前者是为了整合碎片,以得到更大的连续内存;后者是回收不一定必须占用内存的缓冲内存 。这里重点了解,整个流程大致如下:
__alloc_pages_nodemask-> __alloc_pages_slowpath-> __alloc_pages_direct_compact-> try_to_compact_pages-> compact_zone_order-> compact_zone-> isolate_migratepages-> migrate_pages-> release_freepages
并不是所有申请不到内存的场景都会,首先要满足order大于0,并且携带和;另外,需要zone的剩余内存情况满足一定条件,称之为“碎片指数”( index),这个值在0~1000之间,默认碎片指数大于500时才能进行,可以通过proc文件来调整这个默认值 。index通过函数来计算:
/** Index is between 0 and 1000** 0 => allocation would fail due to lack of memory* 1000 => allocation would fail due to fragmentation*/return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total)