linux26内核分析lru链表.docx

上传人:b****3 文档编号:27058186 上传时间:2023-06-26 格式:DOCX 页数:9 大小:18.31KB
下载 相关 举报
linux26内核分析lru链表.docx_第1页
第1页 / 共9页
linux26内核分析lru链表.docx_第2页
第2页 / 共9页
linux26内核分析lru链表.docx_第3页
第3页 / 共9页
linux26内核分析lru链表.docx_第4页
第4页 / 共9页
linux26内核分析lru链表.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

linux26内核分析lru链表.docx

《linux26内核分析lru链表.docx》由会员分享,可在线阅读,更多相关《linux26内核分析lru链表.docx(9页珍藏版)》请在冰豆网上搜索。

linux26内核分析lru链表.docx

linux26内核分析lru链表

linux2.6内核分析——LRU链表

LRU链表

本文转自

lru链表是统称,细分为:

活动链表、非活动链表。

链表中存放的是属于进程用户态地址空间或者页高速缓存的所有页。

前者是最近被访问过的页,后者是一段时间内未曾访问过的页,这样的好处是提高效率,减少搬运次数。

而lru也是页框回收算法的核心数据结构。

这两个双向链表是通过zone描述符结合入系统中,在zone中,有两个字段:

active_list,inactive_list.一个是活动链表的表头,一个是非活动链表的表头。

而同时,处于此两个链表中的页框标志位也需要相应设置:

PG_lru,PG_active.前者的标志表明页在活动或非活动页链表中,而后者是页在活动链表中。

当是属于非活动链表时,标志位要清。

而页描述符中的字段lru指向的是链表中的下一页。

如此,则形成了从zone管理区描述符中一个字段为起始点链接而成的lru链表。

而处理链表也有几个相应的函数:

staticinlinevoidadd_page_to_active_list(structzone*zone,structpage*page)

staticinlinevoidadd_page_to_inactive_list(structzone*zone,structpage*page)

staticinlinevoiddel_page_from_active_list(structzone*zone,structpage*page)

staticinlinevoiddel_page_from_inactive_list(structzone*zone,structpage*page)

staticinlinevoiddel_page_from_lru(structzone*zone,structpage*page)

voidfastcallactivate_page(structpage*page)

voidfastcalllru_cache_add(structpage*page)

voidfastcalllru_cache_add_active(structpage*page)

两个插入和删除链表的函数是很简单的,参数都是zone和page.使用的语句也是链表操作语句:

list_add,list_del所不同的是,其中的参数传递:

list_add(&page->lru,&zone->active_list);

list_add(&page->lru,&zone->inactive_list);

list_del(&page->lru);

list_del(&page->lru);

而加入完毕后,zone中表示页数目的字段也相应增加:

zone->nr_active++;

zone->nr_inactive++;

zone->nr_active--;

zone->nr_inactive--;

而del_page_from_lru也与前两个大同小异其中不同之处在于判断了页的PG_active标志位。

staticinlinevoiddel_page_from_lru(structzone*zone,structpage*page)

{

list_del(&page->lru);

if(PageActive(page)){

ClearPageActive(page);

zone->nr_active--;

}else{

zone->nr_inactive--;

}

}

而activate_page函数的目的就是将页从非活动链表中移动到活动链表,其中的if块就是这个作用,首先检查是不是lru链表中的,然后判断页是不是在非活动链表中。

如果在,就删除。

而删除的目的是为了移动到活动链表中,而在活动链表中的页的PG_active标志位需要置位,于是SetPageActive(page);

voidfastcallactivate_page(structpage*page)

{

structzone*zone=page_zone(page);

spin_lock_irq(&zone->lru_lock);

if(PageLRU(page)&&!

PageActive(page)){

del_page_from_inactive_list(zone,page);

SetPageActive(page);

add_page_to_active_list(zone,page);

inc_page_state(pgactivate);

}

spin_unlock_irq(&zone->lru_lock);

}

而之所以设计这个框架,目的就是为了便于PFRA移动页。

而这中有涉及到一个页标志的使用:

PG_referenced(刚被访问过的页)。

当非活动链表中的某一个页被访问时,那么并不是立刻移入活动链表,而是先检查这个标志位,如果这个标志置位为0则置位(为1),此页依然保留在非活动链表中。

当再次访问到此页时,检查此标识符,如果为1,那么移入活动链表。

如果两次访问时间间距超过了给定间隔,那么就要重新设置此标志位。

如果移动进入了活动链表,那么PG_active标志位也将被置位。

可以说,在移动移出这两个动作中,PG_referenced和PG_active两个标志位是配合使用的。

而涉及到这两个动作的关键函数有三个:

voidfastcallmark_page_accessed(structpage*page)

intpage_referenced(structpage*page,intis_locked,intignore_token)

staticvoidrefill_inactive_zone(structzone*zone,structscan_control*sc)

/*

*Markapageashavingseenactivity.

*

*inactive,unreferenced->inactive,referenced

*inactive,referenced->active,unreferenced

*active,unreferenced->active,referenced

*/

voidfastcallmark_page_accessed(structpage*page)

{

if(!

PageActive(page)&&PageReferenced(page)&&PageLRU(page)){

activate_page(page);

ClearPageReferenced(page);

}elseif(!

PageReferenced(page)){

SetPageReferenced(page);

}

}

这个函数的作用就是必须把页标记为访问过时调用。

看函数的注释,三种状态之间的转化:

当非活动链表和未使用过时调用函数,变为非活动链表和使用过;当非活动链表和使用过时调用函数,变为活动链表和未使用过;当活动链表未使用过时调用函数,变为活动链表并使用过。

完成以上功能的就是函数的目的。

在函数体的if第一个判断中,首先是判断页是否在lru链表中,还要判断页的标志PG_referenced是否置位,还要判断页的PG_active标志是否置位。

如果此时页标志的组合是:

在lru链表中,并且在单位时间内使用过,并且未在活动链表中,则将此页调入活动链表,并且清除PG_referenced标志。

然后在下一个判断语句中,条件是页没有被刚刚使用过。

也就是PG_referenced标志位并没有置位为1.那么此时就要置未。

而函数page_referenced的作用就是扫描时,对部分标志位进行清零工作,比如PG_referenced.

回收函数的重点是refill_inactive_zone函数。

而函数中用到一个重要结构:

scan_control,这个结构也是被PFRA广泛使用,其中的各个字段存放着回首操作执行的各种信息,直接影响到系统的策略取舍。

structscan_control{

unsignedlongnr_to_scan;活动链表中待扫描的目标页数

unsignedlongnr_scanned;当前迭代中扫描过的非活动页数

unsignedlongnr_reclaimed;当前迭代中回收的页数

unsignedlongnr_mapped;用户态地址空间引用的页数

intnr_to_reclaim;待回收的目标页数

unsignedintpriority;扫描优先级范围从12到0,低优先级表示扫描更多的页

unsignedintgfp_mask;调用进程传来的GFP掩码

intmay_writepage;如果置位,则允许将脏页写到磁盘(只针对便携情形)

};

这个函数所从事的基本工作始终是循环判断标志,然后将页插入不同的链表。

前后需要四次循环。

在移动过程中的判断,需要一个临时的辅助链表LIST_HEAD(l_hold);

第一次循环:

在这个循环判断语句中,intpgscanned=0;intnr_pages=sc->nr_to_scan(活动链表中待扫描的目标页数);可见循环的第一个条件就是活动链表中的目标页的个数,下一个条件就是list_empty(&zone->active_list)或者链表为空时结束。

将扫描页加入到临时链表中list_add(&page->lru,&l_hold);而如果标志为0,则一定是伙伴系统中的,所以要放回到活动链表中。

因为伙伴系统是准备分配大块内存区时使用,而并不是“零星”使用的。

while(pgscanned<nr_pages&&!

list_empty(&zone->active_list)){

page=lru_to_page(&zone->active_list);

prefetchw_prev_lru_page(page,&zone->active_list,flags);

list_del(&page->lru);

if(get_page_testone(page)){

__put_page(page);

SetPageLRU(page);

list_add(&page->lru,&zone->active_list);

}else{

list_add(&page->lru,&l_hold);

pgmoved++;

}

pgscanned++;

}

 

在完成第一个循环体后,临时链表中已经有了页,而在活动链表中也已经摘除了部分页,这些是准备回收的页。

然后就是准备工作以及“计算交换值”。

zone->pages_scanned+=pgscanned;

zone->nr_active-=pgmoved;

distress=100>>zone->prev_priority;

mapped_ratio=(sc->nr_mapped*100)/total_memory;

swap_tendency=mapped_ratio/2+distress+vm_swappiness;

if(swap_tendency>=100)

reclaim_mapped=1;

交换倾向值是用来决定系统回收方式的。

它的目的是用来判断不同情况下,回收数量的多少。

也就是说,当回收的页框数量太多的时候,那么系统的效率就会受到很大的影响,也就是回收了过多的活动链表中的页。

而如果回收的数量太少,那么同样非活动链表中的准备引用页数量不足以弥补系统调用,那么效率也会受到影响,而如何保持均衡,就是通过这个数值来判断的。

而在结构sc_contrl中的字段priority,是对应zone中的prev_priority;后者是管理区优先级。

而另一种方式就是通过计算,也就是交换倾向数值。

lru链表中有两类页:

属于用户态地址空间的页、不属于任何用户态进程且在页高速缓存中的页。

而PFRA倾向与把用户态进程的页保留在ram中,从而压缩页高速缓存。

而这个数值的作用就是决定函数是移动所有的页,还是仅仅移动不属于用户态进程的页。

交换倾向值=映射比率/2+负荷值+交换值

其中映射比率由字段:

nr_mapped来表示,也就是占有可分配页框的比率。

如果这个数值大,那么系统中的大部分动态内存大部分用于用户态进程,反之则用于页高速缓存。

而负荷值是表示回收页框算法在管理区中回收页框的效率。

也就是字段:

prev_priority

交换值则为用户定义的常数,通常为60,在/proc/sys/vm/swappiness中可以修改数值。

当交换倾向数值大于100时,页将从进程地址空间回收。

当交换值被人为设置为0时,那么系统不会从用户态地址空间回收。

如果人为设置为100时,那么每次调用此函数都会从用户态地址空间回收。

以上就是这段程序的用途。

第二次循环:

则是通过上面的交换数值以及一些条件来判断是否加入活动链表,其余的一概加入非活动链表。

也就是从第一次循环中摘出的那些页的第二次再分配。

while(!

list_empty(&l_hold)){

cond_resched();

page=lru_to_page(&l_hold);

list_del(&page->lru);

if(page_mapped(page)){

if(!

reclaim_mapped||(total_swap_pages==0&&PageAnon(page))||page_referenced(page,0,sc->priority<=0)){

list_add(&page->lru,&l_active);

continue;

}

}

list_add(&page->lru,&l_inactive);

}

 

第三次循环:

将页移入到管理区非活动链表中。

while(!

list_empty(&l_inactive)){

page=lru_to_page(&l_inactive);

prefetchw_prev_lru_page(page,&l_inactive,flags);

list_move(&page->lru,&zone->inactive_list);

pgmoved++;

if(!

pagevec_add(&pvec,page)){

zone->nr_inactive+=pgmoved;

spin_unlock_irq(&zone->lru_lock);

pgdeactivate+=pgmoved;

pgmoved=0;

if(buffer_heads_over_limit)

pagevec_strip(&pvec);

__pagevec_release(&pvec);

spin_lock_irq(&zone->lru_lock);

}

}

 

第四次循环,将页移入到管理区的活动链表中。

while(!

list_empty(&l_active)){

page=lru_to_page(&l_active);

prefetchw_prev_lru_page(page,&l_active,flags);

if(TestSetPageLRU(page))

BUG();

BUG_ON(!

PageActive(page));

list_move(&page->lru,&zone->active_list);

pgmoved++;

if(!

pagevec_add(&pvec,page)){

zone->nr_active+=pgmoved;

pgmoved=0;

spin_unlock_irq(&zone->lru_lock);

__pagevec_release(&pvec);

spin_lock_irq(&zone->lru_lock);

}

}

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1